From df449a7a3132996a80b3a98ec3157f60f38a8ab7 Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Mon, 11 Sep 2023 13:13:22 +0300 Subject: [PATCH 001/207] chore: add kind column by default to TechDocsTable Signed-off-by: Heikki Hellgren --- .changeset/stupid-drinks-trade.md | 5 +++++ plugins/techdocs/api-report.md | 2 ++ plugins/techdocs/src/home/components/Tables/DocsTable.tsx | 7 ++++--- plugins/techdocs/src/home/components/Tables/columns.tsx | 6 ++++++ 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 .changeset/stupid-drinks-trade.md diff --git a/.changeset/stupid-drinks-trade.md b/.changeset/stupid-drinks-trade.md new file mode 100644 index 0000000000..a9eeacec8a --- /dev/null +++ b/.changeset/stupid-drinks-trade.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Add kind column by default to TechDocsTable diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index 3207a16f87..f355fd00d2 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -79,6 +79,7 @@ export const DocsTable: { columns: { createNameColumn(): TableColumn; createOwnerColumn(): TableColumn; + createKindColumn(): TableColumn; createTypeColumn(): TableColumn; }; actions: { @@ -142,6 +143,7 @@ export const EntityListDocsTable: { columns: { createNameColumn(): TableColumn; createOwnerColumn(): TableColumn; + createKindColumn(): TableColumn; createTypeColumn(): TableColumn; }; actions: { diff --git a/plugins/techdocs/src/home/components/Tables/DocsTable.tsx b/plugins/techdocs/src/home/components/Tables/DocsTable.tsx index 5e5b41ee3e..03ba442578 100644 --- a/plugins/techdocs/src/home/components/Tables/DocsTable.tsx +++ b/plugins/techdocs/src/home/components/Tables/DocsTable.tsx @@ -17,16 +17,16 @@ import React from 'react'; import useCopyToClipboard from 'react-use/lib/useCopyToClipboard'; -import { useRouteRef, useApi, configApiRef } from '@backstage/core-plugin-api'; +import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; import { - humanizeEntityRef, getEntityRelations, + humanizeEntityRef, } from '@backstage/plugin-catalog-react'; import { rootDocsRouteRef } from '../../../routes'; import { - LinkButton, EmptyState, + LinkButton, Table, TableColumn, TableOptions, @@ -87,6 +87,7 @@ export const DocsTable = (props: DocsTableProps) => { const defaultColumns: TableColumn[] = [ columnFactories.createNameColumn(), columnFactories.createOwnerColumn(), + columnFactories.createKindColumn(), columnFactories.createTypeColumn(), ]; diff --git a/plugins/techdocs/src/home/components/Tables/columns.tsx b/plugins/techdocs/src/home/components/Tables/columns.tsx index 774cfc5e8a..bc85bb7a63 100644 --- a/plugins/techdocs/src/home/components/Tables/columns.tsx +++ b/plugins/techdocs/src/home/components/Tables/columns.tsx @@ -57,6 +57,12 @@ export const columnFactories = { ), }; }, + createKindColumn(): TableColumn { + return { + title: 'Kind', + field: 'entity.kind', + }; + }, createTypeColumn(): TableColumn { return { title: 'Type', From 6936989db1680a82e414053a6a7d2e43fbf24572 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 20 Sep 2023 15:03:23 +0200 Subject: [PATCH 002/207] root: disable usage of fsevents in jest Signed-off-by: Patrik Oldsberg --- ...jest-haste-map-npm-29.4.3-19b03fcef3.patch | 13 ++++++++++ package.json | 1 + yarn.lock | 25 ++++++++++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 .yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch diff --git a/.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch b/.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch new file mode 100644 index 0000000000..e0dd8bfa8c --- /dev/null +++ b/.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch @@ -0,0 +1,13 @@ +diff --git a/build/watchers/FSEventsWatcher.js b/build/watchers/FSEventsWatcher.js +index 2273a6cbd2110ddbbd1525820289c3d93ab46cac..d637a644239ae4a7db407ce779f43b4dec9a44ed 100644 +--- a/build/watchers/FSEventsWatcher.js ++++ b/build/watchers/FSEventsWatcher.js +@@ -103,7 +103,7 @@ function _interopRequireWildcard(obj, nodeInterop) { + // @ts-ignore: this is for CI which runs linux and might not have this + let fsevents = null; + try { +- fsevents = require('fsevents'); ++ // fsevents = require('fsevents'); + } catch { + // Optional dependency, only supported on Darwin. + } diff --git a/package.json b/package.json index dcdd66f7c3..8c35ec8437 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "resolutions": { "@types/react": "^17", "@types/react-dom": "^17", + "jest-haste-map@^29.4.3": "patch:jest-haste-map@npm%3A29.4.3#./.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch", "mock-fs@^5.2.0": "patch:mock-fs@npm%3A5.2.0#./.yarn/patches/mock-fs-npm-5.2.0-5103a7b507.patch" }, "version": "1.18.0", diff --git a/yarn.lock b/yarn.lock index 51abaf0aa6..c1d27c910c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29690,7 +29690,7 @@ __metadata: languageName: node linkType: hard -"jest-haste-map@npm:^29.4.3": +"jest-haste-map@npm:29.4.3": version: 29.4.3 resolution: "jest-haste-map@npm:29.4.3" dependencies: @@ -29713,6 +29713,29 @@ __metadata: languageName: node linkType: hard +"jest-haste-map@patch:jest-haste-map@npm%3A29.4.3#./.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch::locator=root%40workspace%3A.": + version: 29.4.3 + resolution: "jest-haste-map@patch:jest-haste-map@npm%3A29.4.3#./.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch::version=29.4.3&hash=1e431f&locator=root%40workspace%3A." + dependencies: + "@jest/types": ^29.4.3 + "@types/graceful-fs": ^4.1.3 + "@types/node": "*" + anymatch: ^3.0.3 + fb-watchman: ^2.0.0 + fsevents: ^2.3.2 + graceful-fs: ^4.2.9 + jest-regex-util: ^29.4.3 + jest-util: ^29.4.3 + jest-worker: ^29.4.3 + micromatch: ^4.0.4 + walker: ^1.0.8 + dependenciesMeta: + fsevents: + optional: true + checksum: a25fd71cc650acac4295172b2b84212872c4100a0b8e627e1f4b70a7e74d895a20274a4b0449aafdcb8273da055013fdc8765e55cbcf6dc46ae0351e974ed0c2 + languageName: node + linkType: hard + "jest-leak-detector@npm:^29.4.3": version: 29.4.3 resolution: "jest-leak-detector@npm:29.4.3" From 5b74ce4c1fef7c805faf4e631ea7637fae653e62 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Mon, 25 Sep 2023 10:04:43 +0200 Subject: [PATCH 003/207] docs: fix UserEntity references Signed-off-by: Vincenzo Scamporlino --- docs/integrations/github/org.md | 55 +++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/docs/integrations/github/org.md b/docs/integrations/github/org.md index 39b60c76c5..8d640e714e 100644 --- a/docs/integrations/github/org.md +++ b/docs/integrations/github/org.md @@ -130,13 +130,14 @@ export default async function createPlugin( builder.addProcessor(new ScaffolderEntitiesProcessor()); /* highlight-add-start */ const githubOrgProvider = GithubOrgEntityProvider.fromConfig(env.config, { - id: 'production', - orgUrl: 'https://github.com/backstage', - logger: env.logger, - schedule: env.scheduler.createScheduledTaskRunner({ - frequency: { minutes: 60 }, - timeout: { minutes: 15 }, - }), + id: 'production', + orgUrl: 'https://github.com/backstage', + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 60 }, + timeout: { minutes: 15 }, + }), + }); env.eventBroker.subscribe(githubOrgProvider); builder.addEntityProvider(githubOrgProvider); /* highlight-add-end */ @@ -254,23 +255,37 @@ configured such an email in their own account. The API will only return these values when using GitHub App authentication and with the correct app permission allowing access to emails. -You can decorate the `defaultUserTransformer` to replace the org email in the +You can decorate the default `userTransformer` to replace the org email in the returned identity. -```typescript -async (user, ctx): Promise => { - const entity = await defaultUserTransformer(user, ctx); - - if (entity && user.organizationVerifiedDomainEmails?.length) { - entity.spec.profile!.email = user.organizationVerifiedDomainEmails[0]; - } - - return entity; -}, +```ts title="packages/backend/src/plugins/catalog.ts" +const githubOrgProvider = GithubOrgEntityProvider.fromConfig(env.config, { + id: 'production', + orgUrl: 'https://github.com/backstage', + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 60 }, + timeout: { minutes: 15 }, + }), + /* highlight-add-start */ + userTransformer: async (user, ctx) => { + const entity = await defaultUserTransformer(user, ctx); + if ( + entity && + isUserEntity(entity) && + entity.spec.profile && + user.organizationVerifiedDomainEmails?.length + ) { + entity.spec.profile!.email = user.organizationVerifiedDomainEmails[0]; + } + return entity; + }, + /* highlight-add-end */ +}); ``` -Once you have imported the emails you can resolve users in your sign-in in -resolver using the catalog entity search via email +Once you have imported the emails you can resolve users in your [sign-in +resolver](../../auth/github/provider.md) using the catalog entity search via email ```typescript title="packages/backend/src/plugins/auth.ts" ctx.signInWithCatalogUser({ From 1a0616fa10a79eaadc8b91cf6ad91a6f2c96d2db Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Mon, 11 Sep 2023 09:45:47 +0300 Subject: [PATCH 004/207] fix: add missing resource app icon Signed-off-by: Heikki Hellgren --- .changeset/mean-dancers-burn.md | 7 +++++++ packages/app-defaults/src/defaults/icons.tsx | 2 ++ packages/core-app-api/api-report.md | 2 ++ packages/core-app-api/src/app/types.ts | 11 ++++++----- .../test-utils/src/testUtils/appWrappers.tsx | 19 ++++++++++--------- 5 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 .changeset/mean-dancers-burn.md diff --git a/.changeset/mean-dancers-burn.md b/.changeset/mean-dancers-burn.md new file mode 100644 index 0000000000..a51ca7b8de --- /dev/null +++ b/.changeset/mean-dancers-burn.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-app-api': patch +'@backstage/app-defaults': patch +'@backstage/test-utils': patch +--- + +Add missing resource and template app icons diff --git a/packages/app-defaults/src/defaults/icons.tsx b/packages/app-defaults/src/defaults/icons.tsx index 80fa4dcf12..fbdfb14e5b 100644 --- a/packages/app-defaults/src/defaults/icons.tsx +++ b/packages/app-defaults/src/defaults/icons.tsx @@ -35,6 +35,7 @@ import MuiPeopleIcon from '@material-ui/icons/People'; import MuiPersonIcon from '@material-ui/icons/Person'; import MuiWarningIcon from '@material-ui/icons/Warning'; import MuiWorkIcon from '@material-ui/icons/Work'; +import MuiFeaturedPlayListIcon from '@material-ui/icons/FeaturedPlayList'; export const icons = { brokenImage: MuiBrokenImageIcon as IconComponent, @@ -58,6 +59,7 @@ export const icons = { 'kind:system': MuiCategoryIcon as IconComponent, 'kind:user': MuiPersonIcon as IconComponent, 'kind:resource': MuiWorkIcon as IconComponent, + 'kind:template': MuiFeaturedPlayListIcon as IconComponent, user: MuiPersonIcon as IconComponent, warning: MuiWarningIcon as IconComponent, }; diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index 6824dbcf4c..05071255ba 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -179,6 +179,8 @@ export type AppIcons = { 'kind:location': IconComponent; 'kind:system': IconComponent; 'kind:user': IconComponent; + 'kind:resource': IconComponent; + 'kind:template': IconComponent; brokenImage: IconComponent; catalog: IconComponent; chat: IconComponent; diff --git a/packages/core-app-api/src/app/types.ts b/packages/core-app-api/src/app/types.ts index 523e35e9cb..9d2c77292c 100644 --- a/packages/core-app-api/src/app/types.ts +++ b/packages/core-app-api/src/app/types.ts @@ -18,13 +18,13 @@ import { ComponentType, PropsWithChildren } from 'react'; import { AnyApiFactory, AppTheme, - IconComponent, BackstagePlugin, + ExternalRouteRef, + FeatureFlag, + IconComponent, + IdentityApi, RouteRef, SubRouteRef, - ExternalRouteRef, - IdentityApi, - FeatureFlag, } from '@backstage/core-plugin-api'; import { AppConfig } from '@backstage/config'; @@ -99,7 +99,8 @@ export type AppIcons = { 'kind:location': IconComponent; 'kind:system': IconComponent; 'kind:user': IconComponent; - + 'kind:resource': IconComponent; + 'kind:template': IconComponent; brokenImage: IconComponent; catalog: IconComponent; chat: IconComponent; diff --git a/packages/test-utils/src/testUtils/appWrappers.tsx b/packages/test-utils/src/testUtils/appWrappers.tsx index ebded4d813..8bc69e184a 100644 --- a/packages/test-utils/src/testUtils/appWrappers.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.tsx @@ -16,24 +16,23 @@ import React, { ComponentType, - ReactNode, - ReactElement, PropsWithChildren, + ReactElement, + ReactNode, } from 'react'; -import { MemoryRouter } from 'react-router-dom'; -import { Route } from 'react-router-dom'; -import { UnifiedThemeProvider, themes } from '@backstage/theme'; +import { MemoryRouter, Route } from 'react-router-dom'; +import { themes, UnifiedThemeProvider } from '@backstage/theme'; import MockIcon from '@material-ui/icons/AcUnit'; import { createSpecializedApp } from '@backstage/core-app-api'; import { - BootErrorPageProps, - RouteRef, - ExternalRouteRef, attachComponentData, + BootErrorPageProps, createRouteRef, + ExternalRouteRef, + RouteRef, } from '@backstage/core-plugin-api'; import { MatcherFunction, RenderResult } from '@testing-library/react'; -import { renderWithEffects, LegacyRootOption } from './testingLibrary'; +import { LegacyRootOption, renderWithEffects } from './testingLibrary'; import { defaultApis } from './defaultApis'; import { mockApis } from './mockApis'; @@ -45,6 +44,8 @@ const mockIcons = { 'kind:location': MockIcon, 'kind:system': MockIcon, 'kind:user': MockIcon, + 'kind:resource': MockIcon, + 'kind:template': MockIcon, brokenImage: MockIcon, catalog: MockIcon, From 95c8a9f72ed2c8fef29912ae440bceb846af6b1a Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Mon, 25 Sep 2023 14:35:16 +0200 Subject: [PATCH 005/207] Changed colour of the overlay components to match navigation color Signed-off-by: Jasper Boeijenga --- packages/core-components/src/layout/Sidebar/MobileSidebar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx index 5dcf31d884..e124036648 100644 --- a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx +++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx @@ -79,14 +79,14 @@ const useStyles = makeStyles( overlayHeader: { display: 'flex', - color: theme.palette.text.primary, + color: theme.palette.navigation.color, alignItems: 'center', justifyContent: 'space-between', padding: theme.spacing(2, 3), }, overlayHeaderClose: { - color: theme.palette.text.primary, + color: theme.palette.navigation.color, }, marginMobileSidebar: props => ({ From 16126dbe6a162ef0c9cc81f6db2ad55bf890715f Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Mon, 25 Sep 2023 16:31:14 +0200 Subject: [PATCH 006/207] Added changeset Signed-off-by: Jasper Boeijenga --- .changeset/violet-beers-cross.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/violet-beers-cross.md diff --git a/.changeset/violet-beers-cross.md b/.changeset/violet-beers-cross.md new file mode 100644 index 0000000000..bdbb9da64e --- /dev/null +++ b/.changeset/violet-beers-cross.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Change overlay header colors in the mobile menu to use navigation color from the theme From a8ee2a7deb18caaeeff5d021ba24f71eb2b3f33a Mon Sep 17 00:00:00 2001 From: Anton Ganhammar Date: Tue, 26 Sep 2023 11:44:46 +0200 Subject: [PATCH 007/207] fix: correct coverage history statistics Signed-off-by: Anton Ganhammar --- .../components/CoverageHistoryChart/CoverageHistoryChart.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx index 1e5341eb50..09f499fafd 100644 --- a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx +++ b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx @@ -113,8 +113,8 @@ export const CoverageHistoryChart = () => { ); } - const oldestCoverage = valueHistory.history[0]; - const [latestCoverage] = valueHistory.history.slice(-1); + const [oldestCoverage] = valueHistory.history.slice(-1); + const latestCoverage = valueHistory.history[0]; const getTrendForCoverage = (type: Coverage) => { if (!oldestCoverage[type].percentage) { From 88b0b325479885d419d1c2f3c7f6fbe6dd295cbb Mon Sep 17 00:00:00 2001 From: Anton Ganhammar Date: Tue, 26 Sep 2023 11:46:27 +0200 Subject: [PATCH 008/207] chore: add changeset Signed-off-by: Anton Ganhammar --- .changeset/cold-seas-repeat.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/cold-seas-repeat.md diff --git a/.changeset/cold-seas-repeat.md b/.changeset/cold-seas-repeat.md new file mode 100644 index 0000000000..0072c4327d --- /dev/null +++ b/.changeset/cold-seas-repeat.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-code-coverage': patch +--- + +Fixed the coverage history statistics to compare newest with oldest record From f6c84edf55a996a34de98d7514e144a85212bf35 Mon Sep 17 00:00:00 2001 From: Miguel Alexandre Date: Tue, 26 Sep 2023 14:23:47 +0200 Subject: [PATCH 009/207] Update configuring-ci-cd.md Signed-off-by: Miguel Alexandre --- docs/features/techdocs/configuring-ci-cd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/configuring-ci-cd.md b/docs/features/techdocs/configuring-ci-cd.md index 692128bf7b..20a73798a4 100644 --- a/docs/features/techdocs/configuring-ci-cd.md +++ b/docs/features/techdocs/configuring-ci-cd.md @@ -29,7 +29,7 @@ cd repo # Install @techdocs/cli, mkdocs and mkdocs plugins npm install -g @techdocs/cli -pip install mkdocs-techdocs-core==1.* +pip install "mkdocs-techdocs-core==1.*" # Generate techdocs-cli generate --no-docker From 817f2acbb18b9e4b559f1c5c8c9ce3936efbf354 Mon Sep 17 00:00:00 2001 From: ivgo Date: Tue, 26 Sep 2023 15:49:36 +0200 Subject: [PATCH 010/207] Make sure a default factory badge is selected Signed-off-by: ivgo --- .changeset/many-swans-eat.md | 5 +++++ plugins/badges-backend/src/plugin.ts | 2 ++ plugins/badges-backend/src/service/router.ts | 5 ++++- 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 .changeset/many-swans-eat.md diff --git a/.changeset/many-swans-eat.md b/.changeset/many-swans-eat.md new file mode 100644 index 0000000000..86580d7cfe --- /dev/null +++ b/.changeset/many-swans-eat.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-badges-backend': patch +--- + +Make sure the default badge factory is used if nothing is defined diff --git a/plugins/badges-backend/src/plugin.ts b/plugins/badges-backend/src/plugin.ts index 3e462e88e9..e5a51d763f 100644 --- a/plugins/badges-backend/src/plugin.ts +++ b/plugins/badges-backend/src/plugin.ts @@ -20,6 +20,7 @@ import { createBackendPlugin, } from '@backstage/backend-plugin-api'; import { createRouter } from './service/router'; +import { createDefaultBadgeFactories } from './badges'; /** * Badges backend plugin @@ -50,6 +51,7 @@ export const badgesPlugin = createBackendPlugin({ await createRouter({ config, logger: loggerToWinstonLogger(logger), + badgeFactories: createDefaultBadgeFactories(), discovery, tokenManager, identity, diff --git a/plugins/badges-backend/src/service/router.ts b/plugins/badges-backend/src/service/router.ts index 308865b73a..47bb8fcbe8 100644 --- a/plugins/badges-backend/src/service/router.ts +++ b/plugins/badges-backend/src/service/router.ts @@ -32,6 +32,7 @@ import { Logger } from 'winston'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; import { BadgesStore, DatabaseBadgesStore } from '../database/badgesStore'; +import { createDefaultBadgeFactories } from '../badges'; /** @public */ export interface RouterOptions { @@ -54,7 +55,9 @@ export async function createRouter( options.catalog || new CatalogClient({ discoveryApi: options.discovery }); const badgeBuilder = options.badgeBuilder || - new DefaultBadgeBuilder(options.badgeFactories || {}); + new DefaultBadgeBuilder( + options.badgeFactories || createDefaultBadgeFactories(), + ); const router = Router(); const { config, logger, tokenManager, discovery, identity } = options; From 5c659b100d89d9f6791b22a18ebfba7dd8dbeaec Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:34:52 +0000 Subject: [PATCH 011/207] chore(deps): update dependency @types/express-serve-static-core to v4.17.37 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..bbb1bad8cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17311,14 +17311,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.30, @types/express-serve-static-core@npm:^4.17.33, @types/express-serve-static-core@npm:^4.17.5": - version: 4.17.36 - resolution: "@types/express-serve-static-core@npm:4.17.36" + version: 4.17.37 + resolution: "@types/express-serve-static-core@npm:4.17.37" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: 410b13cbd663f18c0f8729e7f2ff54d960d96de76ebbae7cadb612972f85cc66c54051e00d32f11aa230c0a683d81a6d6fc7f7e4e383a95c0801494c517f36e1 + checksum: 2dab1380e45eb44e56ecc1be1c42c4b897364d2f2a08e03ca28fbcb1e6866e390217385435813711c046f9acd684424d088855dc32825d5cbecf72c60ecd037f languageName: node linkType: hard From 844c860a79b9d983eae56a9890e12465a20c59ae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:35:27 +0000 Subject: [PATCH 012/207] chore(deps): update dependency @types/lodash to v4.14.199 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..e516a35f48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17708,9 +17708,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.151, @types/lodash@npm:^4.14.173, @types/lodash@npm:^4.14.175": - version: 4.14.198 - resolution: "@types/lodash@npm:4.14.198" - checksum: b290e4480707151bcec738bca40527915defe52a0d8e26c83685c674163a265e1a88cb2ee56b0fb587a89819d0cd5df86ada836aec3e9c2e4bf516e7d348d524 + version: 4.14.199 + resolution: "@types/lodash@npm:4.14.199" + checksum: e68d1fcbbfce953ed87b296a628573f62939227bcda0c934954e862b421e8a34c5e71cad6fea27b9980567909e6a4698f09025692958e36d64ea9ed99ec6fb2e languageName: node linkType: hard From 37853ce61027048b8fbeb0fec1437ae84c1c32d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:35:58 +0000 Subject: [PATCH 013/207] chore(deps): update dependency @types/ndjson to v2.0.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..9396fa675f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17838,12 +17838,12 @@ __metadata: linkType: hard "@types/ndjson@npm:^2.0.1": - version: 2.0.1 - resolution: "@types/ndjson@npm:2.0.1" + version: 2.0.2 + resolution: "@types/ndjson@npm:2.0.2" dependencies: "@types/node": "*" "@types/through": "*" - checksum: d7e5ef9d43424851d1d3e1b223c0d6508bf283c4a769eb08312a96b1e6e60011b3454a5599dbecfdad4128f7c9c6c1b5b4abfabe29bb5065d412dead1c20f9e8 + checksum: 2f4d60229a01dadd4ed1d7df923223788cc4517a15d0fc07b56b3dbdefb567646334e173d7f976a8a7ce7b85df74bf78fd8805f41bdd9ebd8d135310f472a2cb languageName: node linkType: hard From cdc326d2449b8c2342c896d045d7edadde6088d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 17:21:27 +0000 Subject: [PATCH 014/207] chore(deps): update dependency @types/archiver to v5.3.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..16e275bebc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16785,11 +16785,11 @@ __metadata: linkType: hard "@types/archiver@npm:^5.1.0, @types/archiver@npm:^5.3.1": - version: 5.3.2 - resolution: "@types/archiver@npm:5.3.2" + version: 5.3.3 + resolution: "@types/archiver@npm:5.3.3" dependencies: "@types/readdir-glob": "*" - checksum: 9db5b4fdc1740fa07d08340ed827598cc6eda97406ac18a06a158670c7124d4120650a3b9cd660e9e39b42f033cf8f052566da32681e8ad91163473df88a3c4c + checksum: e660465ac9a622570ddbad86a306c7234c3272cb28eafe9c3ad7229f06e499dfadae9f0cb0caf41443318eea559b75ef662ea276ae64f19695e72018dae37ee7 languageName: node linkType: hard From 67a0339fd2ab2234ad2b6f51f12405e88ade8f1d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 17:22:16 +0000 Subject: [PATCH 015/207] chore(deps): update dependency @types/d3-selection to v3.0.7 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..db7d01597e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17153,9 +17153,9 @@ __metadata: linkType: hard "@types/d3-selection@npm:*, @types/d3-selection@npm:^3.0.1": - version: 3.0.6 - resolution: "@types/d3-selection@npm:3.0.6" - checksum: 01f9f3a41b98280947109911bcc6ebffff5c8c3e617695979c04ef9beef445a8cdc48a9fbdb3c9cff45a7345e83e8a5d6b346d7ceedca6ebc11dfd9717dbff6b + version: 3.0.7 + resolution: "@types/d3-selection@npm:3.0.7" + checksum: 715a0c7a78732650ae70b3487b3b6432b063482c1937bcd52c8b7a201563103170fdaa1f8c0ace882062521ac009f07fefb41198c8c43c5d3c518f8368c459d6 languageName: node linkType: hard From d9a53a977beda91bb9a375da3aca23f33a6b86ca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 17:23:04 +0000 Subject: [PATCH 016/207] chore(deps): update dependency @types/d3-zoom to v3.0.5 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..73acf65140 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17192,12 +17192,12 @@ __metadata: linkType: hard "@types/d3-zoom@npm:^3.0.1": - version: 3.0.4 - resolution: "@types/d3-zoom@npm:3.0.4" + version: 3.0.5 + resolution: "@types/d3-zoom@npm:3.0.5" dependencies: "@types/d3-interpolate": "*" "@types/d3-selection": "*" - checksum: 6330b8411822b979ab0fd5a7a7755295377b4dfc61fd8f925d97e5b388e3dd604b455c0009b0eda3320c14c4ea367f740a04991a71d35befdca5f75218492a68 + checksum: acff15a30b2b81a99b46692c7aacc110c635a272e8d7e87af6aa5a01ebe9ebcafcaf475399d79ec73461a5ef037041dade49a6371d7587b759710123539b81b0 languageName: node linkType: hard From 17a0b98ab25c61e3b187ee7c2471093c375c39b8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 17:23:58 +0000 Subject: [PATCH 017/207] chore(deps): update dependency @types/dagre to v0.7.50 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..f7afb150a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17202,9 +17202,9 @@ __metadata: linkType: hard "@types/dagre@npm:^0.7.44": - version: 0.7.49 - resolution: "@types/dagre@npm:0.7.49" - checksum: cb27683074f8c89c073d0b7b549692b67ddae7225a2b6f9586d75c11598f7bd32d9246ecb184017a55592e7daaf63e4d33dcbc56ca4c3999cf34352460ddf772 + version: 0.7.50 + resolution: "@types/dagre@npm:0.7.50" + checksum: a128048b5202c501a4595bbc17288aafbef90f3535e79385ddaf0842237e69aa5998dbc12bc2867244eefe3fb6c5026d9785bfdedea46d813f006066e06e8f44 languageName: node linkType: hard From febe2680d901cb3bd7be105bc301626b00ff6825 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 17:24:51 +0000 Subject: [PATCH 018/207] chore(deps): update dependency @types/diff to v5.0.5 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..dfb88a4f34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17218,9 +17218,9 @@ __metadata: linkType: hard "@types/diff@npm:^5.0.0": - version: 5.0.4 - resolution: "@types/diff@npm:5.0.4" - checksum: 58f8c3e9c8ed40e97fc8039af95d8f12a620e9facf351273906612ad795678c3f64309e0ce29b03bce8e04a2913f0e6bc5cf2289821bdd312b99f1220025f90a + version: 5.0.5 + resolution: "@types/diff@npm:5.0.5" + checksum: 5f093341d5488cd33079400d4b2ff463dfd4f589bf0a54fbb25f7c87a7bdc16bd1e6125f252c081fa9a3ad44fc78b156c0a5f38bd8128edceb40ba084e051885 languageName: node linkType: hard From a2dbd371cb60e399dbafcaabccba1b22a9e3aa32 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 17:25:38 +0000 Subject: [PATCH 019/207] chore(deps): update dependency @types/event-source-polyfill to v1.0.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..75844e200a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17297,9 +17297,9 @@ __metadata: linkType: hard "@types/event-source-polyfill@npm:^1.0.0": - version: 1.0.1 - resolution: "@types/event-source-polyfill@npm:1.0.1" - checksum: 37f3ccc40e2fc43230047c3323f8bfc55f6ed40aee8c61af7f6b702a923be5615362cf3241f5a536f9c64932309a2184a0181bb48e105a94b968b8321cae1c60 + version: 1.0.2 + resolution: "@types/event-source-polyfill@npm:1.0.2" + checksum: f0813edfee0af768e6e0994b48f9f618df7a5d9023c383a8f35e9e805dec560222dc40fc583d5f1404977febb7353c27c1d0606c67d948a2d18634c18ae437a9 languageName: node linkType: hard From 2d8151061cd35857d9cc6af15f2d106c39d665f8 Mon Sep 17 00:00:00 2001 From: Matthew Clarke Date: Tue, 26 Sep 2023 18:40:10 -0400 Subject: [PATCH 020/207] refactor: Refactors the Kubernetes plugin in line with ADR11 (#19446) * refactor: k8s plugins Signed-off-by: Matthew Clarke * chore: move more files Signed-off-by: Matthew Clarke * chore: fix Signed-off-by: Matthew Clarke * fix: tsc Signed-off-by: Matthew Clarke * chore: changeset Signed-off-by: Matthew Clarke * chore: api report Signed-off-by: Matthew Clarke * fix: catalog Signed-off-by: Matthew Clarke * fix: types Signed-off-by: Matthew Clarke * fix: update lock Signed-off-by: Matthew Clarke --------- Signed-off-by: Matthew Clarke --- .changeset/spicy-chairs-film.md | 7 + plugins/kubernetes-common/api-report.md | 119 + plugins/kubernetes-common/package.json | 13 +- .../__fixtures__/deploy-bad.json | 0 .../__fixtures__/deploy-healthy.json | 0 .../__fixtures__/hpa-healthy.json | 0 .../__fixtures__/hpa-maxed-out.json | 0 .../__fixtures__/pod-crashing.json | 0 .../__fixtures__/pod-missing-cm.json | 0 .../error-detection}/__fixtures__/pod.json | 0 .../src/error-detection/common.ts | 0 .../src/error-detection/deployments.ts | 0 .../error-detection/error-detection.test.ts | 0 .../src/error-detection/error-detection.ts | 2 +- .../src/error-detection/hpas.ts | 0 .../src/error-detection/index.ts | 18 + .../src/error-detection/pods.ts | 0 .../src/error-detection/types.ts | 8 +- plugins/kubernetes-common/src/index.ts | 2 + plugins/kubernetes-common/src/types.ts | 19 + .../src/util}/index.ts | 3 +- .../src/util}/response.ts | 5 +- plugins/kubernetes-react/.eslintrc.js | 1 + plugins/kubernetes-react/README.md | 5 + plugins/kubernetes-react/api-report.md | 751 +++ plugins/kubernetes-react/catalog-info.yaml | 11 + plugins/kubernetes-react/package.json | 66 + .../src/__fixtures__/1-cronjobs.json | 446 ++ .../src/__fixtures__/1-deployments.json | 2911 +++++++++++ .../src/__fixtures__/1-statefulsets.json | 2912 +++++++++++ .../src/__fixtures__/2-cronjobs.json | 385 ++ .../src/__fixtures__/2-deployments.json | 4519 ++++++++++++++++ .../src/__fixtures__/2-statefulsets.json | 4521 +++++++++++++++++ .../src/api/KubernetesBackendClient.test.ts | 0 .../src/api/KubernetesBackendClient.ts | 1 + .../src/api/KubernetesProxyClient.test.ts | 0 .../src/api/KubernetesProxyClient.ts | 0 .../src/api/index.ts | 0 .../src/api/types.ts | 4 + .../src/components/Cluster/Cluster.test.tsx | 0 .../src/components/Cluster/Cluster.tsx | 14 +- .../src/components/Cluster}/index.ts | 2 +- .../CronJobsAccordions.test.tsx | 0 .../CronJobsAccordions/CronJobsAccordions.tsx | 12 +- .../CronJobsDrawer.test.tsx | 0 .../CronJobsAccordions/CronJobsDrawer.tsx | 0 .../components/CronJobsAccordions}/index.ts | 2 +- .../ArgoRollouts/Rollout.test.tsx | 0 .../CustomResources/ArgoRollouts/Rollout.tsx | 0 .../ArgoRollouts/RolloutDrawer.tsx | 0 .../ArgoRollouts/StepsProgress.test.tsx | 0 .../ArgoRollouts/StepsProgress.tsx | 0 .../__fixtures__/aborted-rollout.json | 0 .../__fixtures__/analysis-steps.ts | 0 .../__fixtures__/grouped-resources.json | 0 .../ArgoRollouts/__fixtures__/pause-steps.ts | 0 .../__fixtures__/paused-rollout.json | 0 .../ArgoRollouts/__fixtures__/rollout.json | 0 .../__fixtures__/setweight-steps.ts | 0 .../CustomResources/ArgoRollouts/index.ts | 0 .../CustomResources/ArgoRollouts/types.ts | 0 .../CustomResources/CustomResources.tsx | 12 +- .../DefaultCustomResource.test.tsx | 0 .../CustomResources/DefaultCustomResource.tsx | 0 .../DefaultCustomResourceDrawer.tsx | 0 .../__fixtures__/analysis-run.json | 0 .../src/components/CustomResources}/index.ts | 2 +- .../DeploymentDrawer.test.tsx | 0 .../DeploymentDrawer.tsx | 0 .../DeploymentsAccordions.test.tsx | 0 .../DeploymentsAccordions.tsx | 0 .../components/DeploymentsAccordions/index.ts | 0 .../components/ErrorPanel/ErrorPanel.test.tsx | 0 .../src/components/ErrorPanel/ErrorPanel.tsx | 12 +- .../src/components/ErrorPanel}/index.ts | 2 +- .../ErrorReporting/ErrorReporting.tsx | 17 +- .../src/components/ErrorReporting/index.ts | 16 + .../HorizontalPodAutoscalerDrawer.test.tsx | 0 .../HorizontalPodAutoscalerDrawer.tsx | 0 .../horizontalpodautoscalers.json | 0 .../HorizontalPodAutoscalers/index.ts | 0 .../IngressDrawer.test.tsx | 0 .../IngressesAccordions/IngressDrawer.tsx | 0 .../IngressesAccordions.test.tsx | 0 .../IngressesAccordions.tsx | 13 +- .../__fixtures__/2-ingresses.json | 0 .../components/IngressesAccordions/index.ts | 16 + .../JobsAccordions/JobsAccordions.test.tsx | 0 .../JobsAccordions/JobsAccordions.tsx | 12 +- .../JobsAccordions/JobsDrawer.test.tsx | 0 .../components/JobsAccordions/JobsDrawer.tsx | 0 .../src/components/JobsAccordions}/index.ts | 2 +- .../KubernetesDrawer/KubernetesDrawer.tsx | 21 +- ...ubernetesStructuredMetadataTableDrawer.tsx | 35 +- .../KubernetesDrawer/ManifestYaml.tsx | 10 + .../src/components/KubernetesDrawer/index.ts | 1 + .../PodExecTerminal/PodExecTerminal.test.tsx | 0 .../PodExecTerminal/PodExecTerminal.tsx | 2 +- .../PodExecTerminalAttachAddon.ts | 0 .../PodExecTerminal/PodExecTerminalDialog.tsx | 0 .../src/components/PodExecTerminal/index.ts | 0 .../PodExecTerminal/matchMedia.mock.ts | 0 .../Pods/ErrorList/ErrorList.test.tsx | 2 +- .../components/Pods/ErrorList/ErrorList.tsx | 0 .../src/components/Pods/ErrorList/index.ts | 0 .../components/Pods/Events/Events.test.tsx | 0 .../src/components/Pods/Events/Events.tsx | 0 .../src/components/Pods/Events/index.ts | 0 .../components/Pods/Events/useEvents.test.tsx | 0 .../src/components/Pods/Events/useEvents.ts | 2 +- .../Pods/FixDialog/FixDialog.test.tsx | 0 .../components/Pods/FixDialog/FixDialog.tsx | 2 +- .../src/components/Pods/FixDialog/index.ts | 0 .../Pods/PodDrawer/ContainerCard.test.tsx | 0 .../Pods/PodDrawer/ContainerCard.tsx | 0 .../Pods/PodDrawer/PendingPodContent.test.tsx | 0 .../Pods/PodDrawer/PendingPodContent.tsx | 0 .../Pods/PodDrawer/PodDrawer.test.tsx | 0 .../components/Pods/PodDrawer/PodDrawer.tsx | 2 +- .../src/components/Pods/PodDrawer/index.ts | 0 .../src/components/Pods/PodLogs/PodLogs.tsx | 0 .../components/Pods/PodLogs/PodLogsDialog.tsx | 0 .../src/components/Pods/PodLogs/index.ts | 0 .../src/components/Pods/PodLogs/types.ts | 0 .../src/components/Pods/PodLogs/usePodLogs.ts | 2 +- .../src/components/Pods/PodsTable.test.tsx | 0 .../src/components/Pods/PodsTable.tsx | 29 +- .../Pods/__fixtures__/crashing-pod.json | 0 .../components/Pods}/__fixtures__/pod.json | 0 .../src/components/Pods/index.ts | 2 +- .../src/components/Pods/types.ts | 2 +- .../ResourceUtilization.test.tsx | 0 .../ResourceUtilization.tsx | 3 +- .../components/ResourceUtilization/index.ts | 2 +- .../ServicesAccordions/ServiceDrawer.test.tsx | 0 .../ServicesAccordions/ServiceDrawer.tsx | 0 .../ServicesAccordions.test.tsx | 0 .../ServicesAccordions/ServicesAccordions.tsx | 12 +- .../__fixtures__/2-services.json | 0 .../components/ServicesAccordions/index.ts | 16 + .../StatefulSetDrawer.test.tsx | 0 .../StatefulSetDrawer.tsx | 0 .../StatefulSetsAccordions.test.tsx | 0 .../StatefulSetsAccordions.tsx | 0 .../StatefulSetsAccordions/index.ts | 0 .../src/components/index.ts | 1 - .../src/hooks/Cluster.ts | 3 + .../src/hooks/GroupedResponses.ts | 7 +- .../src/hooks/PodNamesWithErrors.ts | 3 + .../src/hooks/PodNamesWithMetrics.ts | 4 +- .../useIsPodExecTerminalSupported.ts | 0 .../src/hooks/auth.test.ts | 0 .../src/hooks/auth.ts | 4 +- .../src/hooks/index.ts | 0 .../src/hooks/test-utils.tsx | 0 .../src/hooks/types.ts | 0 .../src/hooks/useCustomResources.test.ts | 0 .../src/hooks/useCustomResources.ts | 4 +- .../useIsPodExecTerminalSupported.test.ts | 0 .../hooks/useIsPodExecTerminalSupported.ts | 3 +- .../src/hooks/useKubernetesObjects.test.ts | 0 .../src/hooks/useKubernetesObjects.ts | 12 +- .../src/hooks/useMatchingErrors.test.tsx | 6 +- .../src/hooks/useMatchingErrors.ts | 5 +- .../src/hooks/usePodMetrics.test.tsx | 0 .../src/hooks/usePodMetrics.ts | 4 +- plugins/kubernetes-react/src/index.ts | 29 + .../AksKubernetesAuthProvider.ts | 1 + .../GoogleKubernetesAuthProvider.ts | 1 + .../KubernetesAuthProviders.test.ts | 0 .../KubernetesAuthProviders.ts | 1 + .../OidcKubernetesAuthProvider.ts | 1 + .../ServerSideAuthProvider.ts | 0 .../src/kubernetes-auth-provider}/index.ts | 13 +- .../src/kubernetes-auth-provider/types.ts | 3 + plugins/kubernetes-react/src/setupTests.ts | 16 + .../src/types/index.ts | 0 plugins/kubernetes-react/src/types/types.ts | 28 + .../clusterLinks/formatClusterLink.test.ts | 0 .../utils/clusterLinks/formatClusterLink.ts | 2 + .../utils/clusterLinks/formatters/aks.test.ts | 0 .../src/utils/clusterLinks/formatters/aks.ts | 0 .../utils/clusterLinks/formatters/eks.test.ts | 0 .../src/utils/clusterLinks/formatters/eks.ts | 0 .../utils/clusterLinks/formatters/gke.test.ts | 0 .../src/utils/clusterLinks/formatters/gke.ts | 0 .../utils/clusterLinks/formatters/index.ts | 0 .../clusterLinks/formatters/openshift.test.ts | 0 .../clusterLinks/formatters/openshift.ts | 0 .../clusterLinks/formatters/rancher.test.ts | 0 .../utils/clusterLinks/formatters/rancher.ts | 0 .../clusterLinks/formatters/standard.test.ts | 0 .../utils/clusterLinks/formatters/standard.ts | 0 .../src/utils/clusterLinks/index.ts | 0 .../src/utils/crons.test.ts | 0 .../src/utils/crons.ts | 0 .../src/utils/index.ts | 0 .../src/utils/owner.test.ts | 0 .../src/utils/owner.ts | 0 .../src/utils/pod.test.tsx | 0 .../src/utils/pod.tsx | 0 .../src/utils/resources.ts | 0 plugins/kubernetes/api-report.md | 764 +-- plugins/kubernetes/package.json | 1 + .../KubernetesContent.test.tsx | 14 +- .../{components => }/KubernetesContent.tsx | 41 +- plugins/kubernetes/src/Router.tsx | 2 +- plugins/kubernetes/src/assets/emptystate.svg | 1 - .../components/IngressesAccordions/index.ts | 16 - .../components/ServicesAccordions/index.ts | 16 - plugins/kubernetes/src/index.ts | 9 +- .../src/kubernetes-auth-provider/index.ts | 21 - plugins/kubernetes/src/plugin.ts | 13 +- plugins/kubernetes/src/types/types.ts | 57 - yarn.lock | 127 +- 215 files changed, 17249 insertions(+), 992 deletions(-) create mode 100644 .changeset/spicy-chairs-film.md rename plugins/{kubernetes => kubernetes-common}/src/error-detection/__fixtures__/deploy-bad.json (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/__fixtures__/deploy-healthy.json (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/__fixtures__/hpa-healthy.json (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/__fixtures__/hpa-maxed-out.json (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/__fixtures__/pod-crashing.json (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/__fixtures__/pod-missing-cm.json (100%) rename plugins/{kubernetes/src/components/Pods => kubernetes-common/src/error-detection}/__fixtures__/pod.json (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/common.ts (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/deployments.ts (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/error-detection.test.ts (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/error-detection.ts (97%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/hpas.ts (100%) create mode 100644 plugins/kubernetes-common/src/error-detection/index.ts rename plugins/{kubernetes => kubernetes-common}/src/error-detection/pods.ts (100%) rename plugins/{kubernetes => kubernetes-common}/src/error-detection/types.ts (93%) rename plugins/{kubernetes/src/components/Cluster => kubernetes-common/src/util}/index.ts (94%) rename plugins/{kubernetes/src/utils => kubernetes-common/src/util}/response.ts (95%) create mode 100644 plugins/kubernetes-react/.eslintrc.js create mode 100644 plugins/kubernetes-react/README.md create mode 100644 plugins/kubernetes-react/api-report.md create mode 100644 plugins/kubernetes-react/catalog-info.yaml create mode 100644 plugins/kubernetes-react/package.json create mode 100644 plugins/kubernetes-react/src/__fixtures__/1-cronjobs.json create mode 100644 plugins/kubernetes-react/src/__fixtures__/1-deployments.json create mode 100644 plugins/kubernetes-react/src/__fixtures__/1-statefulsets.json create mode 100644 plugins/kubernetes-react/src/__fixtures__/2-cronjobs.json create mode 100644 plugins/kubernetes-react/src/__fixtures__/2-deployments.json create mode 100644 plugins/kubernetes-react/src/__fixtures__/2-statefulsets.json rename plugins/{kubernetes => kubernetes-react}/src/api/KubernetesBackendClient.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/api/KubernetesBackendClient.ts (99%) rename plugins/{kubernetes => kubernetes-react}/src/api/KubernetesProxyClient.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/api/KubernetesProxyClient.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/api/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/api/types.ts (97%) rename plugins/{kubernetes => kubernetes-react}/src/components/Cluster/Cluster.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Cluster/Cluster.tsx (96%) rename plugins/{kubernetes/src/components/ErrorPanel => kubernetes-react/src/components/Cluster}/index.ts (93%) rename plugins/{kubernetes => kubernetes-react}/src/components/CronJobsAccordions/CronJobsAccordions.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CronJobsAccordions/CronJobsAccordions.tsx (97%) rename plugins/{kubernetes => kubernetes-react}/src/components/CronJobsAccordions/CronJobsDrawer.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CronJobsAccordions/CronJobsDrawer.tsx (100%) rename plugins/{kubernetes/src/components/JobsAccordions => kubernetes-react/src/components/CronJobsAccordions}/index.ts (92%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/Rollout.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/Rollout.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/RolloutDrawer.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/StepsProgress.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/StepsProgress.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/__fixtures__/aborted-rollout.json (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/__fixtures__/analysis-steps.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/__fixtures__/grouped-resources.json (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/__fixtures__/pause-steps.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/__fixtures__/paused-rollout.json (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/__fixtures__/rollout.json (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/__fixtures__/setweight-steps.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/ArgoRollouts/types.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/CustomResources.tsx (95%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/DefaultCustomResource.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/DefaultCustomResource.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/DefaultCustomResourceDrawer.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/CustomResources/__fixtures__/analysis-run.json (100%) rename plugins/{kubernetes/src/components/ErrorReporting => kubernetes-react/src/components/CustomResources}/index.ts (92%) rename plugins/{kubernetes => kubernetes-react}/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/DeploymentsAccordions/DeploymentDrawer.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/DeploymentsAccordions/DeploymentsAccordions.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/DeploymentsAccordions/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/ErrorPanel/ErrorPanel.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/ErrorPanel/ErrorPanel.tsx (96%) rename plugins/{kubernetes/src/components/CustomResources => kubernetes-react/src/components/ErrorPanel}/index.ts (91%) rename plugins/{kubernetes => kubernetes-react}/src/components/ErrorReporting/ErrorReporting.tsx (92%) create mode 100644 plugins/kubernetes-react/src/components/ErrorReporting/index.ts rename plugins/{kubernetes => kubernetes-react}/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/HorizontalPodAutoscalers/__fixtures__/horizontalpodautoscalers.json (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/HorizontalPodAutoscalers/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/IngressesAccordions/IngressDrawer.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/IngressesAccordions/IngressDrawer.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/IngressesAccordions/IngressesAccordions.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/IngressesAccordions/IngressesAccordions.tsx (96%) rename plugins/{kubernetes => kubernetes-react}/src/components/IngressesAccordions/__fixtures__/2-ingresses.json (100%) create mode 100644 plugins/kubernetes-react/src/components/IngressesAccordions/index.ts rename plugins/{kubernetes => kubernetes-react}/src/components/JobsAccordions/JobsAccordions.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/JobsAccordions/JobsAccordions.tsx (97%) rename plugins/{kubernetes => kubernetes-react}/src/components/JobsAccordions/JobsDrawer.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/JobsAccordions/JobsDrawer.tsx (100%) rename plugins/{kubernetes/src/components/CronJobsAccordions => kubernetes-react/src/components/JobsAccordions}/index.ts (91%) rename plugins/{kubernetes => kubernetes-react}/src/components/KubernetesDrawer/KubernetesDrawer.tsx (93%) rename plugins/{kubernetes => kubernetes-react}/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx (95%) rename plugins/{kubernetes => kubernetes-react}/src/components/KubernetesDrawer/ManifestYaml.tsx (94%) rename plugins/{kubernetes => kubernetes-react}/src/components/KubernetesDrawer/index.ts (95%) rename plugins/{kubernetes => kubernetes-react}/src/components/PodExecTerminal/PodExecTerminal.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/PodExecTerminal/PodExecTerminal.tsx (99%) rename plugins/{kubernetes => kubernetes-react}/src/components/PodExecTerminal/PodExecTerminalAttachAddon.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/PodExecTerminal/PodExecTerminalDialog.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/PodExecTerminal/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/PodExecTerminal/matchMedia.mock.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/ErrorList/ErrorList.test.tsx (97%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/ErrorList/ErrorList.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/ErrorList/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/Events/Events.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/Events/Events.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/Events/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/Events/useEvents.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/Events/useEvents.ts (95%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/FixDialog/FixDialog.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/FixDialog/FixDialog.tsx (98%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/FixDialog/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodDrawer/ContainerCard.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodDrawer/ContainerCard.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodDrawer/PendingPodContent.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodDrawer/PendingPodContent.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodDrawer/PodDrawer.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodDrawer/PodDrawer.tsx (99%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodDrawer/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodLogs/PodLogs.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodLogs/PodLogsDialog.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodLogs/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodLogs/types.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodLogs/usePodLogs.ts (95%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodsTable.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/PodsTable.tsx (96%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/__fixtures__/crashing-pod.json (100%) rename plugins/{kubernetes/src/error-detection => kubernetes-react/src/components/Pods}/__fixtures__/pod.json (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/index.ts (94%) rename plugins/{kubernetes => kubernetes-react}/src/components/Pods/types.ts (92%) rename plugins/{kubernetes => kubernetes-react}/src/components/ResourceUtilization/ResourceUtilization.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/ResourceUtilization/ResourceUtilization.tsx (96%) rename plugins/{kubernetes => kubernetes-react}/src/components/ResourceUtilization/index.ts (90%) rename plugins/{kubernetes => kubernetes-react}/src/components/ServicesAccordions/ServiceDrawer.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/ServicesAccordions/ServiceDrawer.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/ServicesAccordions/ServicesAccordions.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/ServicesAccordions/ServicesAccordions.tsx (97%) rename plugins/{kubernetes => kubernetes-react}/src/components/ServicesAccordions/__fixtures__/2-services.json (100%) create mode 100644 plugins/kubernetes-react/src/components/ServicesAccordions/index.ts rename plugins/{kubernetes => kubernetes-react}/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/StatefulSetsAccordions/StatefulSetDrawer.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/StatefulSetsAccordions/StatefulSetsAccordions.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/StatefulSetsAccordions/StatefulSetsAccordions.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/StatefulSetsAccordions/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/components/index.ts (96%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/Cluster.ts (97%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/GroupedResponses.ts (90%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/PodNamesWithErrors.ts (97%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/PodNamesWithMetrics.ts (97%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/__mocks__/useIsPodExecTerminalSupported.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/auth.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/auth.ts (98%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/test-utils.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/types.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/useCustomResources.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/useCustomResources.ts (99%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/useIsPodExecTerminalSupported.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/useIsPodExecTerminalSupported.ts (96%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/useKubernetesObjects.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/useKubernetesObjects.ts (97%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/useMatchingErrors.test.tsx (95%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/useMatchingErrors.ts (95%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/usePodMetrics.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/hooks/usePodMetrics.ts (99%) create mode 100644 plugins/kubernetes-react/src/index.ts rename plugins/{kubernetes => kubernetes-react}/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts (98%) rename plugins/{kubernetes => kubernetes-react}/src/kubernetes-auth-provider/GoogleKubernetesAuthProvider.ts (99%) rename plugins/{kubernetes => kubernetes-react}/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/kubernetes-auth-provider/KubernetesAuthProviders.ts (99%) rename plugins/{kubernetes => kubernetes-react}/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts (99%) rename plugins/{kubernetes => kubernetes-react}/src/kubernetes-auth-provider/ServerSideAuthProvider.ts (100%) rename plugins/{kubernetes/src/error-detection => kubernetes-react/src/kubernetes-auth-provider}/index.ts (70%) rename plugins/{kubernetes => kubernetes-react}/src/kubernetes-auth-provider/types.ts (96%) create mode 100644 plugins/kubernetes-react/src/setupTests.ts rename plugins/{kubernetes => kubernetes-react}/src/types/index.ts (100%) create mode 100644 plugins/kubernetes-react/src/types/types.ts rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatClusterLink.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatClusterLink.ts (90%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/aks.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/aks.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/eks.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/eks.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/gke.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/gke.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/openshift.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/openshift.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/rancher.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/rancher.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/standard.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/formatters/standard.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/clusterLinks/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/crons.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/crons.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/index.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/owner.test.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/owner.ts (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/pod.test.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/pod.tsx (100%) rename plugins/{kubernetes => kubernetes-react}/src/utils/resources.ts (100%) rename plugins/kubernetes/src/{components => }/KubernetesContent.test.tsx (91%) rename plugins/kubernetes/src/{components => }/KubernetesContent.tsx (81%) delete mode 100644 plugins/kubernetes/src/assets/emptystate.svg delete mode 100644 plugins/kubernetes/src/components/IngressesAccordions/index.ts delete mode 100644 plugins/kubernetes/src/components/ServicesAccordions/index.ts delete mode 100644 plugins/kubernetes/src/kubernetes-auth-provider/index.ts delete mode 100644 plugins/kubernetes/src/types/types.ts diff --git a/.changeset/spicy-chairs-film.md b/.changeset/spicy-chairs-film.md new file mode 100644 index 0000000000..475d786330 --- /dev/null +++ b/.changeset/spicy-chairs-film.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-kubernetes-common': minor +'@backstage/plugin-kubernetes-react': minor +'@backstage/plugin-kubernetes': minor +--- + +Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet diff --git a/plugins/kubernetes-common/api-report.md b/plugins/kubernetes-common/api-report.md index 051293f37f..0840278394 100644 --- a/plugins/kubernetes-common/api-report.md +++ b/plugins/kubernetes-common/api-report.md @@ -5,7 +5,9 @@ ```ts import { BasicPermission } from '@backstage/plugin-permission-common'; import { Entity } from '@backstage/catalog-model'; +import { FetchResponse as FetchResponse_2 } from '@backstage/plugin-kubernetes-common'; import type { JsonObject } from '@backstage/types'; +import { ObjectsByEntityResponse as ObjectsByEntityResponse_2 } from '@backstage/plugin-kubernetes-common'; import { PodStatus } from '@kubernetes/client-node'; import { V1ConfigMap } from '@kubernetes/client-node'; import { V1CronJob } from '@kubernetes/client-node'; @@ -174,6 +176,67 @@ export interface DeploymentFetchResponse { type: 'deployments'; } +// @public (undocumented) +export interface DeploymentResources { + // (undocumented) + deployments: V1Deployment[]; + // (undocumented) + horizontalPodAutoscalers: V1HorizontalPodAutoscaler[]; + // (undocumented) + pods: V1Pod[]; + // (undocumented) + replicaSets: V1ReplicaSet[]; +} + +// @public +export interface DetectedError { + // (undocumented) + message: string; + // (undocumented) + occurrenceCount: number; + // (undocumented) + proposedFix?: ProposedFix; + // (undocumented) + severity: ErrorSeverity; + // (undocumented) + sourceRef: ResourceRef; + // (undocumented) + type: string; +} + +// @public +export type DetectedErrorsByCluster = Map; + +// @public +export const detectErrors: ( + objects: ObjectsByEntityResponse_2, +) => DetectedErrorsByCluster; + +// @public (undocumented) +export interface DocsSolution extends ProposedFixBase { + // (undocumented) + docsLink: string; + // (undocumented) + type: 'docs'; +} + +// @public (undocumented) +export interface ErrorMapper { + // (undocumented) + detectErrors: (resource: T) => DetectedError[]; +} + +// @public +export type ErrorSeverity = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; + +// @public (undocumented) +export interface EventsSolution extends ProposedFixBase { + // (undocumented) + podName: string; + // (undocumented) + type: 'events'; +} + // @public (undocumented) export type FetchResponse = | PodFetchResponse @@ -191,6 +254,29 @@ export type FetchResponse = | DaemonSetsFetchResponse | PodStatusFetchResponse; +// @public (undocumented) +export interface GroupedResponses extends DeploymentResources { + // (undocumented) + configMaps: V1ConfigMap[]; + // (undocumented) + cronJobs: V1CronJob[]; + // (undocumented) + customResources: any[]; + // (undocumented) + ingresses: V1Ingress[]; + // (undocumented) + jobs: V1Job[]; + // (undocumented) + services: V1Service[]; + // (undocumented) + statefulsets: V1StatefulSet[]; +} + +// @public (undocumented) +export const groupResponses: ( + fetchResponse: FetchResponse_2[], +) => GroupedResponses; + // @public (undocumented) export interface HorizontalPodAutoscalersFetchResponse { // (undocumented) @@ -251,6 +337,14 @@ export interface LimitRangeFetchResponse { type: 'limitranges'; } +// @public (undocumented) +export interface LogSolution extends ProposedFixBase { + // (undocumented) + container: string; + // (undocumented) + type: 'logs'; +} + // @public (undocumented) export interface ObjectsByEntityResponse { // (undocumented) @@ -273,6 +367,19 @@ export interface PodStatusFetchResponse { type: 'podstatus'; } +// @public (undocumented) +export type ProposedFix = LogSolution | DocsSolution | EventsSolution; + +// @public (undocumented) +export interface ProposedFixBase { + // (undocumented) + actions: string[]; + // (undocumented) + errorType: string; + // (undocumented) + rootCauseExplanation: string; +} + // @public (undocumented) export interface RawFetchError { // (undocumented) @@ -289,6 +396,18 @@ export interface ReplicaSetsFetchResponse { type: 'replicasets'; } +// @public +export interface ResourceRef { + // (undocumented) + apiGroup: string; + // (undocumented) + kind: string; + // (undocumented) + name: string; + // (undocumented) + namespace: string; +} + // @public (undocumented) export interface ServiceFetchResponse { // (undocumented) diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index b563cbff4e..99d38b803e 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -40,11 +40,20 @@ }, "dependencies": { "@backstage/catalog-model": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", - "@kubernetes/client-node": "0.18.1" + "@backstage/types": "workspace:^", + "@kubernetes/client-node": "0.18.1", + "kubernetes-models": "^4.3.1", + "lodash": "^4.17.21", + "luxon": "^3.0.0" }, "devDependencies": { - "@backstage/cli": "workspace:^" + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/test-utils": "workspace:^", + "msw": "^1.3.1" }, "jest": { "roots": [ diff --git a/plugins/kubernetes/src/error-detection/__fixtures__/deploy-bad.json b/plugins/kubernetes-common/src/error-detection/__fixtures__/deploy-bad.json similarity index 100% rename from plugins/kubernetes/src/error-detection/__fixtures__/deploy-bad.json rename to plugins/kubernetes-common/src/error-detection/__fixtures__/deploy-bad.json diff --git a/plugins/kubernetes/src/error-detection/__fixtures__/deploy-healthy.json b/plugins/kubernetes-common/src/error-detection/__fixtures__/deploy-healthy.json similarity index 100% rename from plugins/kubernetes/src/error-detection/__fixtures__/deploy-healthy.json rename to plugins/kubernetes-common/src/error-detection/__fixtures__/deploy-healthy.json diff --git a/plugins/kubernetes/src/error-detection/__fixtures__/hpa-healthy.json b/plugins/kubernetes-common/src/error-detection/__fixtures__/hpa-healthy.json similarity index 100% rename from plugins/kubernetes/src/error-detection/__fixtures__/hpa-healthy.json rename to plugins/kubernetes-common/src/error-detection/__fixtures__/hpa-healthy.json diff --git a/plugins/kubernetes/src/error-detection/__fixtures__/hpa-maxed-out.json b/plugins/kubernetes-common/src/error-detection/__fixtures__/hpa-maxed-out.json similarity index 100% rename from plugins/kubernetes/src/error-detection/__fixtures__/hpa-maxed-out.json rename to plugins/kubernetes-common/src/error-detection/__fixtures__/hpa-maxed-out.json diff --git a/plugins/kubernetes/src/error-detection/__fixtures__/pod-crashing.json b/plugins/kubernetes-common/src/error-detection/__fixtures__/pod-crashing.json similarity index 100% rename from plugins/kubernetes/src/error-detection/__fixtures__/pod-crashing.json rename to plugins/kubernetes-common/src/error-detection/__fixtures__/pod-crashing.json diff --git a/plugins/kubernetes/src/error-detection/__fixtures__/pod-missing-cm.json b/plugins/kubernetes-common/src/error-detection/__fixtures__/pod-missing-cm.json similarity index 100% rename from plugins/kubernetes/src/error-detection/__fixtures__/pod-missing-cm.json rename to plugins/kubernetes-common/src/error-detection/__fixtures__/pod-missing-cm.json diff --git a/plugins/kubernetes/src/components/Pods/__fixtures__/pod.json b/plugins/kubernetes-common/src/error-detection/__fixtures__/pod.json similarity index 100% rename from plugins/kubernetes/src/components/Pods/__fixtures__/pod.json rename to plugins/kubernetes-common/src/error-detection/__fixtures__/pod.json diff --git a/plugins/kubernetes/src/error-detection/common.ts b/plugins/kubernetes-common/src/error-detection/common.ts similarity index 100% rename from plugins/kubernetes/src/error-detection/common.ts rename to plugins/kubernetes-common/src/error-detection/common.ts diff --git a/plugins/kubernetes/src/error-detection/deployments.ts b/plugins/kubernetes-common/src/error-detection/deployments.ts similarity index 100% rename from plugins/kubernetes/src/error-detection/deployments.ts rename to plugins/kubernetes-common/src/error-detection/deployments.ts diff --git a/plugins/kubernetes/src/error-detection/error-detection.test.ts b/plugins/kubernetes-common/src/error-detection/error-detection.test.ts similarity index 100% rename from plugins/kubernetes/src/error-detection/error-detection.test.ts rename to plugins/kubernetes-common/src/error-detection/error-detection.test.ts diff --git a/plugins/kubernetes/src/error-detection/error-detection.ts b/plugins/kubernetes-common/src/error-detection/error-detection.ts similarity index 97% rename from plugins/kubernetes/src/error-detection/error-detection.ts rename to plugins/kubernetes-common/src/error-detection/error-detection.ts index c33de18b80..a3a4d58d9e 100644 --- a/plugins/kubernetes/src/error-detection/error-detection.ts +++ b/plugins/kubernetes-common/src/error-detection/error-detection.ts @@ -16,7 +16,7 @@ import { DetectedError, DetectedErrorsByCluster } from './types'; import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; -import { groupResponses } from '../utils/response'; +import { groupResponses } from '../util'; import { detectErrorsInPods } from './pods'; import { detectErrorsInDeployments } from './deployments'; import { detectErrorsInHpa } from './hpas'; diff --git a/plugins/kubernetes/src/error-detection/hpas.ts b/plugins/kubernetes-common/src/error-detection/hpas.ts similarity index 100% rename from plugins/kubernetes/src/error-detection/hpas.ts rename to plugins/kubernetes-common/src/error-detection/hpas.ts diff --git a/plugins/kubernetes-common/src/error-detection/index.ts b/plugins/kubernetes-common/src/error-detection/index.ts new file mode 100644 index 0000000000..0b79b023c2 --- /dev/null +++ b/plugins/kubernetes-common/src/error-detection/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 { detectErrors } from './error-detection'; diff --git a/plugins/kubernetes/src/error-detection/pods.ts b/plugins/kubernetes-common/src/error-detection/pods.ts similarity index 100% rename from plugins/kubernetes/src/error-detection/pods.ts rename to plugins/kubernetes-common/src/error-detection/pods.ts diff --git a/plugins/kubernetes/src/error-detection/types.ts b/plugins/kubernetes-common/src/error-detection/types.ts similarity index 93% rename from plugins/kubernetes/src/error-detection/types.ts rename to plugins/kubernetes-common/src/error-detection/types.ts index 4148056171..bf918bbacb 100644 --- a/plugins/kubernetes/src/error-detection/types.ts +++ b/plugins/kubernetes-common/src/error-detection/types.ts @@ -54,29 +54,35 @@ export interface DetectedError { occurrenceCount: number; } +/** @public */ export type ProposedFix = LogSolution | DocsSolution | EventsSolution; -interface ProposedFixBase { +/** @public */ +export interface ProposedFixBase { errorType: string; rootCauseExplanation: string; actions: string[]; } +/** @public */ export interface LogSolution extends ProposedFixBase { type: 'logs'; container: string; } +/** @public */ export interface DocsSolution extends ProposedFixBase { type: 'docs'; docsLink: string; } +/** @public */ export interface EventsSolution extends ProposedFixBase { type: 'events'; podName: string; } +/** @public */ export interface ErrorMapper { detectErrors: (resource: T) => DetectedError[]; } diff --git a/plugins/kubernetes-common/src/index.ts b/plugins/kubernetes-common/src/index.ts index d5cf8dcf61..6704242383 100644 --- a/plugins/kubernetes-common/src/index.ts +++ b/plugins/kubernetes-common/src/index.ts @@ -26,3 +26,5 @@ export { kubernetesProxyPermission, kubernetesPermissions, } from './permissions'; +export * from './error-detection'; +export * from './util'; diff --git a/plugins/kubernetes-common/src/types.ts b/plugins/kubernetes-common/src/types.ts index feb213d520..9648293432 100644 --- a/plugins/kubernetes-common/src/types.ts +++ b/plugins/kubernetes-common/src/types.ts @@ -262,3 +262,22 @@ export interface ClientPodStatus { memory: ClientCurrentResourceUsage; containers: ClientContainerStatus[]; } + +/** @public */ +export interface DeploymentResources { + pods: V1Pod[]; + replicaSets: V1ReplicaSet[]; + deployments: V1Deployment[]; + horizontalPodAutoscalers: V1HorizontalPodAutoscaler[]; +} + +/** @public */ +export interface GroupedResponses extends DeploymentResources { + services: V1Service[]; + configMaps: V1ConfigMap[]; + ingresses: V1Ingress[]; + jobs: V1Job[]; + cronJobs: V1CronJob[]; + customResources: any[]; + statefulsets: V1StatefulSet[]; +} diff --git a/plugins/kubernetes/src/components/Cluster/index.ts b/plugins/kubernetes-common/src/util/index.ts similarity index 94% rename from plugins/kubernetes/src/components/Cluster/index.ts rename to plugins/kubernetes-common/src/util/index.ts index dc9df63d42..1cc287df08 100644 --- a/plugins/kubernetes/src/components/Cluster/index.ts +++ b/plugins/kubernetes-common/src/util/index.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { Cluster } from './Cluster'; + +export * from './response'; diff --git a/plugins/kubernetes/src/utils/response.ts b/plugins/kubernetes-common/src/util/response.ts similarity index 95% rename from plugins/kubernetes/src/utils/response.ts rename to plugins/kubernetes-common/src/util/response.ts index 894b881f22..a86d90f780 100644 --- a/plugins/kubernetes/src/utils/response.ts +++ b/plugins/kubernetes-common/src/util/response.ts @@ -15,12 +15,13 @@ */ import { FetchResponse } from '@backstage/plugin-kubernetes-common'; -import { GroupedResponses } from '../types/types'; +import { GroupedResponses } from '../types'; -// TODO this could probably be a lodash groupBy +/** @public */ export const groupResponses = ( fetchResponse: FetchResponse[], ): GroupedResponses => { + // TODO this could probably be a lodash groupBy return fetchResponse.reduce( (prev, next) => { switch (next.type) { diff --git a/plugins/kubernetes-react/.eslintrc.js b/plugins/kubernetes-react/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/kubernetes-react/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/kubernetes-react/README.md b/plugins/kubernetes-react/README.md new file mode 100644 index 0000000000..02963c2e0a --- /dev/null +++ b/plugins/kubernetes-react/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-kubernetes-react + +Welcome to the web library package for the kubernetes-react plugin! + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/kubernetes-react/api-report.md b/plugins/kubernetes-react/api-report.md new file mode 100644 index 0000000000..e182524426 --- /dev/null +++ b/plugins/kubernetes-react/api-report.md @@ -0,0 +1,751 @@ +## API Report File for "@backstage/plugin-kubernetes-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 { AsyncState } from 'react-use/lib/useAsyncFn'; +import { ClientContainerStatus } from '@backstage/plugin-kubernetes-common'; +import { ClientPodStatus } from '@backstage/plugin-kubernetes-common'; +import { ClusterAttributes } from '@backstage/plugin-kubernetes-common'; +import { ClusterObjects } from '@backstage/plugin-kubernetes-common'; +import { CustomObjectsByEntityRequest } from '@backstage/plugin-kubernetes-common'; +import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; +import { DetectedError } from '@backstage/plugin-kubernetes-common'; +import { DetectedErrorsByCluster } from '@backstage/plugin-kubernetes-common'; +import { DiscoveryApi } from '@backstage/core-plugin-api'; +import { Entity } from '@backstage/catalog-model'; +import { Event as Event_2 } from 'kubernetes-models/v1'; +import { GroupedResponses } from '@backstage/plugin-kubernetes-common'; +import { IContainer } from 'kubernetes-models/v1'; +import { IContainerStatus } from 'kubernetes-models/v1'; +import { IdentityApi } from '@backstage/core-plugin-api'; +import { IIoK8sApimachineryPkgApisMetaV1ObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta'; +import { IObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta'; +import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; +import { OAuthApi } from '@backstage/core-plugin-api'; +import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; +import { OpenIdConnectApi } from '@backstage/core-plugin-api'; +import { Pod } from 'kubernetes-models/v1'; +import { Pod as Pod_2 } from 'kubernetes-models/v1/Pod'; +import { default as React_2 } from 'react'; +import * as React_3 from 'react'; +import { TypeMeta } from '@kubernetes-models/base'; +import { V1HorizontalPodAutoscaler } from '@kubernetes/client-node'; +import { V1Job } from '@kubernetes/client-node'; +import { V1ObjectMeta } from '@kubernetes/client-node'; +import { V1Pod } from '@kubernetes/client-node'; +import { WorkloadsByEntityRequest } from '@backstage/plugin-kubernetes-common'; + +// @public (undocumented) +export class AksKubernetesAuthProvider implements KubernetesAuthProvider { + constructor(microsoftAuthApi: OAuthApi); + // (undocumented) + decorateRequestBodyForAuth( + requestBody: KubernetesRequestBody, + ): Promise; + // (undocumented) + getCredentials(): Promise<{ + token?: string; + }>; +} + +// @public +export const Cluster: ({ + clusterObjects, + podsWithErrors, +}: ClusterProps) => React_2.JSX.Element; + +// @public (undocumented) +export const ClusterContext: React_2.Context; + +// @public +export type ClusterProps = { + clusterObjects: ClusterObjects; + podsWithErrors: Set; + children?: React_2.ReactNode; +}; + +// @public +export const ContainerCard: React_2.FC; + +// @public +export interface ContainerCardProps { + // (undocumented) + containerMetrics?: ClientContainerStatus; + // (undocumented) + containerSpec?: IContainer; + // (undocumented) + containerStatus: IContainerStatus; + // (undocumented) + podScope: PodScope; +} + +// @public +export interface ContainerScope extends PodScope { + // (undocumented) + containerName: string; +} + +// @public (undocumented) +export const CronJobsAccordions: ({}: CronJobsAccordionsProps) => React_2.JSX.Element; + +// @public (undocumented) +export type CronJobsAccordionsProps = { + children?: React_2.ReactNode; +}; + +// @public (undocumented) +export const CustomResources: ({}: CustomResourcesProps) => React_2.JSX.Element; + +// @public (undocumented) +export interface CustomResourcesProps { + // (undocumented) + children?: React_2.ReactNode; +} + +// @public +export const DetectedErrorsContext: React_2.Context; + +// @public +export const ErrorList: ({ + podAndErrors, +}: ErrorListProps) => React_2.JSX.Element; + +// @public +export interface ErrorListProps { + // (undocumented) + podAndErrors: PodAndErrors[]; +} + +// @public (undocumented) +export type ErrorMatcher = { + metadata?: IIoK8sApimachineryPkgApisMetaV1ObjectMeta; +} & TypeMeta; + +// @public (undocumented) +export const ErrorPanel: ({ + entityName, + errorMessage, + clustersWithErrors, +}: ErrorPanelProps) => React_2.JSX.Element; + +// @public (undocumented) +export type ErrorPanelProps = { + entityName: string; + errorMessage?: string; + clustersWithErrors?: ClusterObjects[]; + children?: React_2.ReactNode; +}; + +// @public (undocumented) +export const ErrorReporting: ({ + detectedErrors, +}: ErrorReportingProps) => React_3.JSX.Element; + +// @public (undocumented) +export type ErrorReportingProps = { + detectedErrors: DetectedErrorsByCluster; +}; + +// @public +export const Events: ({ + involvedObjectName, + namespace, + clusterName, + warningEventsOnly, +}: EventsProps) => React_2.JSX.Element; + +// @public +export const EventsContent: ({ + events, + warningEventsOnly, +}: EventsContentProps) => React_2.JSX.Element; + +// @public +export interface EventsContentProps { + // (undocumented) + events: Event_2[]; + // (undocumented) + warningEventsOnly?: boolean; +} + +// @public +export interface EventsOptions { + // (undocumented) + clusterName: string; + // (undocumented) + involvedObjectName: string; + // (undocumented) + namespace: string; +} + +// @public +export interface EventsProps { + // (undocumented) + clusterName: string; + // (undocumented) + involvedObjectName: string; + // (undocumented) + namespace: string; + // (undocumented) + warningEventsOnly?: boolean; +} + +// @public +export const FixDialog: React_2.FC; + +// @public +export interface FixDialogProps { + // (undocumented) + clusterName: string; + // (undocumented) + error: DetectedError; + // (undocumented) + open?: boolean; + // (undocumented) + pod: Pod_2; +} + +// @public (undocumented) +export class GoogleKubernetesAuthProvider implements KubernetesAuthProvider { + constructor(authProvider: OAuthApi); + // (undocumented) + authProvider: OAuthApi; + // (undocumented) + decorateRequestBodyForAuth( + requestBody: KubernetesRequestBody, + ): Promise; + // (undocumented) + getCredentials(): Promise<{ + token: string; + }>; +} + +// @public (undocumented) +export const GroupedResponsesContext: React_2.Context; + +// @public (undocumented) +export const HorizontalPodAutoscalerDrawer: (props: { + hpa: V1HorizontalPodAutoscaler; + expanded?: boolean; + children?: React_2.ReactNode; +}) => React_2.JSX.Element; + +// @public (undocumented) +export const IngressesAccordions: ({}: IngressesAccordionsProps) => React_2.JSX.Element; + +// @public (undocumented) +export type IngressesAccordionsProps = {}; + +// @public (undocumented) +export const JobsAccordions: ({ + jobs, +}: JobsAccordionsProps) => React_2.JSX.Element; + +// @public (undocumented) +export type JobsAccordionsProps = { + jobs: V1Job[]; + children?: React_2.ReactNode; +}; + +// @public (undocumented) +export interface KubernetesApi { + // (undocumented) + getClusters(): Promise< + { + name: string; + authProvider: string; + oidcTokenProvider?: string | undefined; + }[] + >; + // (undocumented) + getCustomObjectsByEntity( + request: CustomObjectsByEntityRequest, + ): Promise; + // (undocumented) + getObjectsByEntity( + requestBody: KubernetesRequestBody, + ): Promise; + // (undocumented) + getWorkloadsByEntity( + request: WorkloadsByEntityRequest, + ): Promise; + // (undocumented) + proxy(options: { + clusterName: string; + path: string; + init?: RequestInit; + }): Promise; +} + +// @public (undocumented) +export const kubernetesApiRef: ApiRef; + +// @public (undocumented) +export interface KubernetesAuthProvider { + // (undocumented) + decorateRequestBodyForAuth( + requestBody: KubernetesRequestBody, + ): Promise; + // (undocumented) + getCredentials(): Promise<{ + token?: string; + }>; +} + +// @public (undocumented) +export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { + constructor(options: { + microsoftAuthApi: OAuthApi; + googleAuthApi: OAuthApi; + oidcProviders?: { + [key: string]: OpenIdConnectApi; + }; + }); + // (undocumented) + decorateRequestBodyForAuth( + authProvider: string, + requestBody: KubernetesRequestBody, + ): Promise; + // (undocumented) + getCredentials(authProvider: string): Promise<{ + token?: string; + }>; +} + +// @public (undocumented) +export interface KubernetesAuthProvidersApi { + // (undocumented) + decorateRequestBodyForAuth( + authProvider: string, + requestBody: KubernetesRequestBody, + ): Promise; + // (undocumented) + getCredentials(authProvider: string): Promise<{ + token?: string; + }>; +} + +// @public (undocumented) +export const kubernetesAuthProvidersApiRef: ApiRef; + +// @public (undocumented) +export class KubernetesBackendClient implements KubernetesApi { + constructor(options: { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + kubernetesAuthProvidersApi: KubernetesAuthProvidersApi; + }); + // (undocumented) + getClusters(): Promise< + { + name: string; + authProvider: string; + }[] + >; + // (undocumented) + getCustomObjectsByEntity( + request: CustomObjectsByEntityRequest, + ): Promise; + // (undocumented) + getObjectsByEntity( + requestBody: KubernetesRequestBody, + ): Promise; + // (undocumented) + getWorkloadsByEntity( + request: WorkloadsByEntityRequest, + ): Promise; + // (undocumented) + proxy(options: { + clusterName: string; + path: string; + init?: RequestInit; + }): Promise; +} + +// @public +export const KubernetesDrawer: ({ + open, + label, + drawerContentsHeader, + kubernetesObject, + children, +}: KubernetesDrawerProps) => React_2.JSX.Element; + +// @public (undocumented) +export interface KubernetesDrawerable { + // (undocumented) + metadata?: V1ObjectMeta; +} + +// @public +export interface KubernetesDrawerProps { + // (undocumented) + children?: React_2.ReactNode; + // (undocumented) + drawerContentsHeader?: React_2.ReactNode; + // (undocumented) + kubernetesObject: KubernetesObject; + // (undocumented) + label: React_2.ReactNode; + // (undocumented) + open?: boolean; +} + +// @public +export interface KubernetesObject { + // (undocumented) + kind: string; + // (undocumented) + metadata?: IObjectMeta; +} + +// @public (undocumented) +export interface KubernetesObjects { + // (undocumented) + error?: string; + // (undocumented) + kubernetesObjects?: ObjectsByEntityResponse; + // (undocumented) + loading: boolean; +} + +// @public (undocumented) +export interface KubernetesProxyApi { + // (undocumented) + getEventsByInvolvedObjectName(request: { + clusterName: string; + involvedObjectName: string; + namespace: string; + }): Promise; + // (undocumented) + getPodLogs(request: { + podName: string; + namespace: string; + clusterName: string; + containerName: string; + previous?: boolean; + }): Promise<{ + text: string; + }>; +} + +// @public (undocumented) +export const kubernetesProxyApiRef: ApiRef; + +// @public +export class KubernetesProxyClient { + constructor(options: { kubernetesApi: KubernetesApi }); + // (undocumented) + getEventsByInvolvedObjectName({ + clusterName, + involvedObjectName, + namespace, + }: { + clusterName: string; + involvedObjectName: string; + namespace: string; + }): Promise; + // (undocumented) + getPodLogs({ + podName, + namespace, + clusterName, + containerName, + previous, + }: { + podName: string; + namespace: string; + clusterName: string; + containerName: string; + previous?: boolean; + }): Promise<{ + text: string; + }>; +} + +// @public (undocumented) +export const KubernetesStructuredMetadataTableDrawer: < + T extends KubernetesDrawerable, +>({ + object, + renderObject, + kind, + buttonVariant, + expanded, + children, +}: KubernetesStructuredMetadataTableDrawerProps) => React_2.JSX.Element; + +// @public (undocumented) +export interface KubernetesStructuredMetadataTableDrawerProps< + T extends KubernetesDrawerable, +> { + // (undocumented) + buttonVariant?: 'h5' | 'subtitle2'; + // (undocumented) + children?: React_2.ReactNode; + // (undocumented) + expanded?: boolean; + // (undocumented) + kind: string; + // (undocumented) + object: T; + // (undocumented) + renderObject: (obj: T) => object; +} + +// @public (undocumented) +export const LinkErrorPanel: ({ + cluster, + errorMessage, +}: LinkErrorPanelProps) => React_2.JSX.Element; + +// @public (undocumented) +export type LinkErrorPanelProps = { + cluster: ClusterAttributes; + errorMessage?: string; + children?: React_2.ReactNode; +}; + +// @public +export const ManifestYaml: ({ + object, +}: ManifestYamlProps) => React_2.JSX.Element; + +// @public +export interface ManifestYamlProps { + // (undocumented) + object: object; +} + +// @public (undocumented) +export class OidcKubernetesAuthProvider implements KubernetesAuthProvider { + constructor(providerName: string, authProvider: OpenIdConnectApi); + // (undocumented) + authProvider: OpenIdConnectApi; + // (undocumented) + decorateRequestBodyForAuth( + requestBody: KubernetesRequestBody, + ): Promise; + // (undocumented) + getCredentials(): Promise<{ + token: string; + }>; + // (undocumented) + providerName: string; +} + +// @public +export const PendingPodContent: ({ + pod, +}: PendingPodContentProps) => React_2.JSX.Element; + +// @public +export interface PendingPodContentProps { + // (undocumented) + pod: Pod; +} + +// @public +export interface PodAndErrors { + // (undocumented) + clusterName: string; + // (undocumented) + errors: DetectedError[]; + // (undocumented) + pod: Pod; +} + +// @public (undocumented) +export type PodColumns = 'READY' | 'RESOURCE'; + +// @public +export const PodDrawer: ({ + podAndErrors, + open, +}: PodDrawerProps) => React_2.JSX.Element; + +// @public +export interface PodDrawerProps { + // (undocumented) + open?: boolean; + // (undocumented) + podAndErrors: PodAndErrors; +} + +// @public +export const PodExecTerminal: ( + props: PodExecTerminalProps, +) => React_2.JSX.Element; + +// @public +export const PodExecTerminalDialog: ( + props: PodExecTerminalProps, +) => React_2.JSX.Element; + +// @public +export interface PodExecTerminalProps { + // (undocumented) + clusterName: string; + // (undocumented) + containerName: string; + // (undocumented) + podName: string; + // (undocumented) + podNamespace: string; +} + +// @public +export const PodLogs: React_2.FC; + +// @public +export const PodLogsDialog: ({ + containerScope, +}: PodLogsDialogProps) => React_2.JSX.Element; + +// @public +export interface PodLogsDialogProps { + // (undocumented) + containerScope: ContainerScope; +} + +// @public +export interface PodLogsOptions { + // (undocumented) + containerScope: ContainerScope; + // (undocumented) + previous?: boolean; +} + +// @public +export interface PodLogsProps { + // (undocumented) + containerScope: ContainerScope; + // (undocumented) + previous?: boolean; +} + +// @public +export const PodMetricsContext: React_2.Context>; + +// @public (undocumented) +export type PodMetricsMatcher = { + metadata?: IObjectMeta; +}; + +// @public (undocumented) +export const PodNamesWithErrorsContext: React_2.Context>; + +// @public (undocumented) +export const PodNamesWithMetricsContext: React_2.Context< + Map +>; + +// @public +export interface PodScope { + // (undocumented) + clusterName: string; + // (undocumented) + podName: string; + // (undocumented) + podNamespace: string; +} + +// @public (undocumented) +export const PodsTable: ({ + pods, + extraColumns, +}: PodsTablesProps) => React_2.JSX.Element; + +// @public (undocumented) +export type PodsTablesProps = { + pods: Pod_2 | V1Pod[]; + extraColumns?: PodColumns[]; + children?: React_2.ReactNode; +}; + +// @public (undocumented) +export const READY_COLUMNS: PodColumns; + +// @public (undocumented) +export const RESOURCE_COLUMNS: PodColumns; + +// @public +export const ResourceUtilization: ({ + compressed, + title, + usage, + total, + totalFormatted, +}: ResourceUtilizationProps) => React_2.JSX.Element; + +// @public +export interface ResourceUtilizationProps { + // (undocumented) + compressed?: boolean; + // (undocumented) + title: string; + // (undocumented) + total: number | string; + // (undocumented) + totalFormatted: string; + // (undocumented) + usage: number | string; +} + +// @public +export class ServerSideKubernetesAuthProvider + implements KubernetesAuthProvider +{ + // (undocumented) + decorateRequestBodyForAuth( + requestBody: KubernetesRequestBody, + ): Promise; + // (undocumented) + getCredentials(): Promise<{}>; +} + +// @public (undocumented) +export const ServicesAccordions: ({}: ServicesAccordionsProps) => React_2.JSX.Element; + +// @public (undocumented) +export type ServicesAccordionsProps = {}; + +// @public +export const useCustomResources: ( + entity: Entity, + customResourceMatchers: CustomResourceMatcher[], + intervalMs?: number, +) => KubernetesObjects; + +// @public +export const useEvents: ({ + involvedObjectName, + namespace, + clusterName, +}: EventsOptions) => AsyncState; + +// @public (undocumented) +export const useKubernetesObjects: ( + entity: Entity, + intervalMs?: number, +) => KubernetesObjects; + +// @public +export const useMatchingErrors: (matcher: ErrorMatcher) => DetectedError[]; + +// @public +export const usePodLogs: ({ + containerScope, + previous, +}: PodLogsOptions) => AsyncState<{ + text: string; +}>; + +// @public +export const usePodMetrics: ( + clusterName: string, + matcher: PodMetricsMatcher, +) => ClientPodStatus | undefined; +``` diff --git a/plugins/kubernetes-react/catalog-info.yaml b/plugins/kubernetes-react/catalog-info.yaml new file mode 100644 index 0000000000..a2fb40d32c --- /dev/null +++ b/plugins/kubernetes-react/catalog-info.yaml @@ -0,0 +1,11 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-kubernetes-react + title: '@backstage/plugin-kubernetes-react' + description: >- + Shared frontend utilities for Kubernetes plugins +spec: + lifecycle: experimental + type: backstage-web-library + owner: kubernetes-maintainers diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json new file mode 100644 index 0000000000..5c95b29870 --- /dev/null +++ b/plugins/kubernetes-react/package.json @@ -0,0 +1,66 @@ +{ + "name": "@backstage/plugin-kubernetes-react", + "description": "Web library for the kubernetes-react plugin", + "version": "0.0.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": "web-library" + }, + "sideEffects": false, + "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/catalog-model": "workspace:^", + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/plugin-kubernetes-common": "workspace:^", + "@backstage/types": "workspace:^", + "@kubernetes-models/apimachinery": "^1.1.0", + "@kubernetes-models/base": "^4.0.1", + "@kubernetes/client-node": "^0.19.0", + "@material-ui/core": "^4.9.13", + "@material-ui/icons": "^4.11.3", + "@material-ui/lab": "^4.0.0-alpha.61", + "@types/react": "^16.13.1 || ^17.0.0", + "cronstrue": "^2.32.0", + "js-yaml": "^4.1.0", + "kubernetes-models": "^4.3.1", + "lodash": "^4.17.21", + "luxon": "^3.0.0", + "react-use": "^17.4.0", + "xterm": "^5.3.0", + "xterm-addon-attach": "^0.9.0", + "xterm-addon-fit": "^0.8.0" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/react-hooks": "^8.0.1", + "jest-websocket-mock": "^2.5.0", + "msw": "^1.3.1" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/kubernetes-react/src/__fixtures__/1-cronjobs.json b/plugins/kubernetes-react/src/__fixtures__/1-cronjobs.json new file mode 100644 index 0000000000..1edc43710d --- /dev/null +++ b/plugins/kubernetes-react/src/__fixtures__/1-cronjobs.json @@ -0,0 +1,446 @@ +{ + "cronJobs": [ + { + "metadata": { + "name": "dice-roller-cronjob", + "namespace": "default", + "uid": "9ea073bc-7a4b-4b99-8321-0305bce85568", + "resourceVersion": "1362732552", + "creationTimestamp": "2021-07-16T22:39:58Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "annotations": {} + }, + "spec": { + "schedule": "30 5 * * *", + "startingDeadlineSeconds": 1800, + "concurrencyPolicy": "Forbid", + "suspend": false, + "jobTemplate": { + "metadata": { "creationTimestamp": null }, + "spec": { + "backoffLimit": 2, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "annotations": {} + }, + "spec": { + "containers": [ + { + "name": "busybox", + "image": "busybox", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "imagePullPolicy": "IfNotPresent", + "command": ["/bin/sh", "-c", "date; echo Rolling a die!"] + } + ], + "restartPolicy": "Never", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "securityContext": {}, + "schedulerName": "default-scheduler" + } + } + } + }, + "successfulJobsHistoryLimit": 2, + "failedJobsHistoryLimit": 2 + }, + "status": { + "active": [ + { + "kind": "Job", + "namespace": "default", + "name": "dice-roller-cronjob-1637028600", + "uid": "32be1b89-5b53-45b2-aa84-277e75214f61", + "apiVersion": "batch/v1", + "resourceVersion": "1361174163" + } + ], + "lastScheduleTime": "2021-11-16T02:10:00Z" + } + } + ], + "jobs": [ + { + "metadata": { + "name": "dice-roller-cronjob-1637025000", + "namespace": "default", + "uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "resourceVersion": "1361029181", + "creationTimestamp": "2021-11-16T01:10:24Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "ownerReferences": [ + { + "apiVersion": "batch/v1", + "kind": "CronJob", + "name": "dice-roller-cronjob", + "uid": "9ea073bc-7a4b-4b99-8321-0305bce85568", + "controller": true, + "blockOwnerDeletion": true + } + ] + }, + "spec": { + "parallelism": 1, + "completions": 1, + "backoffLimit": 2, + "selector": { + "matchLabels": { + "controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "backstage.io/kubernetes-id": "dice-roller", + "controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "job-name": "dice-roller-cronjob-1637025000" + }, + "annotations": {} + }, + "spec": { + "containers": [ + { + "command": ["/bin/sh", "-c", "date; echo Rolling a die!"], + "image": "busybox", + "imagePullPolicy": "IfNotPresent", + "name": "busybox", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "restartPolicy": "Never", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "securityContext": {}, + "schedulerName": "default-scheduler" + } + } + }, + "status": { + "conditions": [ + { + "type": "Complete", + "status": "True", + "lastProbeTime": "2021-11-16T01:11:31Z", + "lastTransitionTime": "2021-11-16T01:11:31Z" + } + ], + "startTime": "2021-11-16T01:10:24Z", + "completionTime": "2021-11-16T01:11:31Z", + "succeeded": 1 + } + }, + { + "metadata": { + "name": "dice-roller-cronjob-1637028600", + "namespace": "default", + "uid": "32be1b89-5b53-45b2-aa84-277e75214f61", + "resourceVersion": "1361174166", + "creationTimestamp": "2021-11-16T02:10:22Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "ownerReferences": [ + { + "apiVersion": "batch/v1", + "kind": "CronJob", + "name": "dice-roller-cronjob", + "uid": "9ea073bc-7a4b-4b99-8321-0305bce85568", + "controller": true, + "blockOwnerDeletion": true + } + ] + }, + "spec": { + "parallelism": 1, + "completions": 1, + "backoffLimit": 2, + "selector": { + "matchLabels": { + "controller-uid": "32be1b89-5b53-45b2-aa84-277e75214f61" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "backstage.io/kubernetes-id": "dice-roller", + "controller-uid": "32be1b89-5b53-45b2-aa84-277e75214f61", + "job-name": "dice-roller-cronjob-1637028600" + }, + "annotations": {} + }, + "spec": { + "containers": [ + { + "command": ["/bin/sh", "-c", "date; echo Rolling a die!"], + "image": "busybox", + "imagePullPolicy": "IfNotPresent", + "name": "busybox", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "restartPolicy": "Never", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "securityContext": {}, + "schedulerName": "default-scheduler" + } + } + }, + "status": { "startTime": "2021-11-16T02:10:22Z", "active": 1 } + } + ], + "pods": [ + { + "metadata": { + "name": "dice-roller-cronjob-1637025000-gstc4", + "generateName": "dice-roller-cronjob-1637025000-", + "namespace": "default", + "uid": "3b0f2b65-5ae2-441a-beda-bdc92bcafaf0", + "resourceVersion": "1361029179", + "creationTimestamp": "2021-11-16T01:10:24Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller", + "controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "job-name": "dice-roller-cronjob-1637025000" + }, + "annotations": {}, + "ownerReferences": [ + { + "apiVersion": "batch/v1", + "kind": "Job", + "name": "dice-roller-cronjob-1637025000", + "uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "controller": true, + "blockOwnerDeletion": true + } + ] + }, + "spec": { + "volumes": [], + "containers": [ + { + "command": ["/bin/sh", "-c", "date; echo Rolling a die!"], + "image": "busybox", + "imagePullPolicy": "IfNotPresent", + "name": "busybox", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "restartPolicy": "Never", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "serviceAccountName": "default", + "serviceAccount": "default", + "nodeName": "minikube", + "securityContext": {}, + "schedulerName": "default-scheduler", + "tolerations": [ + { + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + }, + { + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + } + ], + "priority": 0, + "enableServiceLinks": true + }, + "status": { + "phase": "Succeeded", + "conditions": [ + { + "type": "Initialized", + "status": "True", + "lastProbeTime": null, + "lastTransitionTime": "2021-11-16T01:10:27Z", + "reason": "PodCompleted" + }, + { + "type": "Ready", + "status": "False", + "lastProbeTime": null, + "lastTransitionTime": "2021-11-16T01:11:31Z", + "reason": "PodCompleted" + }, + { + "type": "ContainersReady", + "status": "False", + "lastProbeTime": null, + "lastTransitionTime": "2021-11-16T01:11:31Z", + "reason": "PodCompleted" + }, + { + "type": "PodScheduled", + "status": "True", + "lastProbeTime": null, + "lastTransitionTime": "2021-11-16T01:10:24Z" + } + ], + "hostIP": "192.168.49.2", + "podIP": "172.17.0.25", + "podIPs": [{ "ip": "172.17.0.25" }], + "startTime": "2021-11-16T01:10:24Z", + "containerStatuses": [ + { + "name": "busybox", + "state": { + "terminated": { + "exitCode": 0, + "reason": "Completed", + "startedAt": "2021-11-16T01:10:31Z", + "finishedAt": "2021-11-16T01:11:30Z", + "containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615" + } + }, + "lastState": {}, + "ready": false, + "restartCount": 0, + "image": "busybox:latest/node", + "imageID": "docker-pullable://busybox@sha256:e7157b6d7ebbe2cce5eaa8cfe8aa4fa82d173999b9f90a9ec42e57323546c353", + "containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615", + "started": false + } + ], + "qosClass": "Burstable" + } + }, + { + "metadata": { + "name": "dice-roller-cronjob-1637028600-p4mlc", + "generateName": "dice-roller-cronjob-1637028600-", + "namespace": "default", + "uid": "acddd5d2-ac7f-473b-a9d8-17a89f99ac39", + "resourceVersion": "1361174579", + "creationTimestamp": "2021-11-16T02:10:22Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller", + "controller-uid": "32be1b89-5b53-45b2-aa84-277e75214f61", + "job-name": "dice-roller-cronjob-1637028600" + }, + "annotations": {}, + "ownerReferences": [ + { + "apiVersion": "batch/v1", + "kind": "Job", + "name": "dice-roller-cronjob-1637028600", + "uid": "32be1b89-5b53-45b2-aa84-277e75214f61", + "controller": true, + "blockOwnerDeletion": true + } + ] + }, + "spec": { + "volumes": [], + "containers": [ + { + "command": ["/bin/sh", "-c", "date; echo Rolling a die!"], + "image": "busybox", + "imagePullPolicy": "IfNotPresent", + "name": "busybox", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "restartPolicy": "Never", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "serviceAccountName": "default", + "serviceAccount": "default", + "nodeName": "minikube", + "securityContext": {}, + "schedulerName": "default-scheduler", + "tolerations": [ + { + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + }, + { + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + } + ], + "priority": 0, + "enableServiceLinks": true + }, + "status": { + "phase": "Running", + "conditions": [ + { + "type": "Initialized", + "status": "True", + "lastProbeTime": null, + "lastTransitionTime": "2021-11-16T02:10:25Z" + }, + { + "type": "Ready", + "status": "True", + "lastProbeTime": null, + "lastTransitionTime": "2021-11-16T02:10:35Z" + }, + { + "type": "ContainersReady", + "status": "True", + "lastProbeTime": null, + "lastTransitionTime": "2021-11-16T02:10:35Z" + }, + { + "type": "PodScheduled", + "status": "True", + "lastProbeTime": null, + "lastTransitionTime": "2021-11-16T02:10:22Z" + } + ], + "hostIP": "192.168.49.2", + "podIP": "172.17.0.25", + "podIPs": [{ "ip": "172.17.0.25" }], + "startTime": "2021-11-16T02:10:22Z", + "containerStatuses": [ + { + "name": "busybox", + "state": { + "running": { "startedAt": "2021-11-16T02:10:31Z" } + }, + "lastState": {}, + "ready": true, + "restartCount": 0, + "image": "busybox:latest", + "imageID": "docker-pullable://busybox@sha256:e7157b6d7ebbe2cce5eaa8cfe8aa4fa82d173999b9f90a9ec42e57323546c353", + "containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615", + "started": true + } + ], + "qosClass": "Burstable" + } + } + ] +} diff --git a/plugins/kubernetes-react/src/__fixtures__/1-deployments.json b/plugins/kubernetes-react/src/__fixtures__/1-deployments.json new file mode 100644 index 0000000000..5ad847dc49 --- /dev/null +++ b/plugins/kubernetes-react/src/__fixtures__/1-deployments.json @@ -0,0 +1,2911 @@ +{ + "pods": [ + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.11\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-2m5hv", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593216", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-2m5hv", + "uid": "aadb71c0-36fa-43e3-b38a-162f134d4359" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://aa4489297c34c48bb33c18474a8d2b33854a82ed42155680b259f635f556ce70", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.11", + "podIPs": [ + { + "ip": "172.17.0.11" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.7\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-4v6s8", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593221", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-4v6s8", + "uid": "32e56490-6f20-4757-991f-a0c7fb407358" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://d91cc76c41249b8d3dfcf538d180b471b2a7966aae0d17a818307c8a9b4af897", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.7", + "podIPs": [ + { + "ip": "172.17.0.7" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-24T11:39:26.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-24T11:39:26.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.6\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-24T11:39:27.000Z" + } + ], + "name": "dice-roller-6c8646bfd-b9zt5", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "503886", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-b9zt5", + "uid": "8b6601b6-469e-4e89-8fd0-abb2f1a567e4" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:26.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:26.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://c50e0d0fa96f09a2ed5df7dd5a7f7de88e6b7c7addb8f002f299d6afc52d82ce", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-24T11:39:27.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.6", + "podIPs": [ + { + "ip": "172.17.0.6" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-24T11:39:26.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.13\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-cfxqc", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593211", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-cfxqc", + "uid": "e87e1776-0ca7-41fb-aeea-e1f648387545" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:51.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://c1641d986aae424429b7c2c1117baeb17d3794f73206bd57292cdf8264f929b2", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.13", + "podIPs": [ + { + "ip": "172.17.0.13" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:51.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.15\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:54.000Z" + } + ], + "name": "dice-roller-6c8646bfd-dtv5z", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593190", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-dtv5z", + "uid": "1638a41b-e47e-4c17-a1f7-7b447df248b6" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:51.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://e62c32db58dbfe0a74b2d2cba0e0a97b7f222693c68e930037ac8738c4758ca3", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.15", + "podIPs": [ + { + "ip": "172.17.0.15" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:51.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.12\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:53.000Z" + } + ], + "name": "dice-roller-6c8646bfd-hhts2", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593186", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-hhts2", + "uid": "ea0b147a-c56a-46e6-9445-7a0b1b0ed3c0" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://bcdbc153630f90556d57ff0d62f04d847ca63a5f0a7e5d9230683623d33d4b8d", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.12", + "podIPs": [ + { + "ip": "172.17.0.12" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.14\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-j68lm", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593226", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-j68lm", + "uid": "b230ff1d-7a13-479b-9c7b-77c26bd79f62" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://30fa8a3429f86ab8e9a4cec472b79d74266609082703f48950f4aae021e9d6a2", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.14", + "podIPs": [ + { + "ip": "172.17.0.14" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.9\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:53.000Z" + } + ], + "name": "dice-roller-6c8646bfd-m6f9w", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593181", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-m6f9w", + "uid": "9b0079f6-ff29-4619-bf6e-71cc10199ac5" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://f78767ee90eedffe46ff64bfe76d7f69426800dd89f3df012daf0baf3a9c5bdd", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.9", + "podIPs": [ + { + "ip": "172.17.0.9" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-24T11:39:27.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-24T11:39:27.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.4\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-24T11:39:28.000Z" + } + ], + "name": "dice-roller-6c8646bfd-nv9pk", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "503918", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-nv9pk", + "uid": "acf7f77f-78c6-4d4b-bc73-637211770ffc" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:28.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:28.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://63dec9b32942c4b09ae43d09d6978261f674a3ee623823b8f1d20da8044c12ac", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-24T11:39:28.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.4", + "podIPs": [ + { + "ip": "172.17.0.4" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-24T11:39:27.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.10\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-pjhfj", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593205", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-pjhfj", + "uid": "78775c3a-7af2-4ebe-a676-bc2e5dfa2bcc" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://cbb83dda250db74285dcbe0b81bd0896acf402bac9710af090311f7360f824aa", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.10", + "podIPs": [ + { + "ip": "172.17.0.10" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + } + ], + "replicaSets": [ + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "10", + "deployment.kubernetes.io/max-replicas": "13", + "deployment.kubernetes.io/revision": "2" + }, + "creationTimestamp": "2020-09-24T11:39:26.000Z", + "generation": 3, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"7551e949-42d1-4061-83c5-9da107186e47\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:availableReplicas": {}, + "f:fullyLabeledReplicas": {}, + "f:observedGeneration": {}, + "f:readyReplicas": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller", + "uid": "7551e949-42d1-4061-83c5-9da107186e47" + } + ], + "resourceVersion": "593228", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + }, + "spec": { + "replicas": 10, + "selector": { + "matchLabels": { + "app": "dice-roller", + "pod-template-hash": "6c8646bfd" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "availableReplicas": 10, + "fullyLabeledReplicas": 10, + "observedGeneration": 3, + "readyReplicas": 10, + "replicas": 10 + } + } + ], + "deployments": [ + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/revision": "2", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"replicas\":10,\"selector\":{\"matchLabels\":{\"app\":\"dice-roller\"}},\"template\":{\"metadata\":{\"labels\":{\"app\":\"dice-roller\",\"backstage.io/kubernetes-id\":\"dice-roller\"}},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]}]}}}}\n" + }, + "creationTimestamp": "2020-09-23T12:00:55.000Z", + "generation": 3, + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:progressDeadlineSeconds": {}, + "f:replicas": {}, + "f:revisionHistoryLimit": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {} + } + }, + "f:strategy": { + "f:rollingUpdate": { + ".": {}, + "f:maxSurge": {}, + "f:maxUnavailable": {} + }, + "f:type": {} + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + } + }, + "manager": "kubectl", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:deployment.kubernetes.io/revision": {} + } + }, + "f:status": { + "f:availableReplicas": {}, + "f:conditions": { + ".": {}, + "k:{\"type\":\"Available\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Progressing\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:observedGeneration": {}, + "f:readyReplicas": {}, + "f:replicas": {}, + "f:updatedReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller", + "namespace": "default", + "resourceVersion": "593230", + "selfLink": "/apis/apps/v1/namespaces/default/deployments/dice-roller", + "uid": "7551e949-42d1-4061-83c5-9da107186e47" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 10, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "dice-roller" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "availableReplicas": 10, + "conditions": [ + { + "lastTransitionTime": "2020-09-23T12:00:55.000Z", + "lastUpdateTime": "2020-09-24T11:39:28.000Z", + "message": "ReplicaSet \"dice-roller-6c8646bfd\" has successfully progressed.", + "reason": "NewReplicaSetAvailable", + "status": "True", + "type": "Progressing" + }, + { + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "lastUpdateTime": "2020-09-25T09:58:55.000Z", + "message": "Deployment has minimum availability.", + "reason": "MinimumReplicasAvailable", + "status": "True", + "type": "Available" + } + ], + "observedGeneration": 3, + "readyReplicas": 10, + "replicas": 10, + "updatedReplicas": 10 + } + } + ], + "horizontalPodAutoscalers": [ + { + "apiVersion": "autoscaling/v1", + "kind": "HorizontalPodAutoscaler", + "metadata": { + "annotations": { + "autoscaling.alpha.kubernetes.io/conditions": "[{\"type\":\"AbleToScale\",\"status\":\"True\",\"lastTransitionTime\":\"2021-01-05T10:26:04Z\",\"reason\":\"SucceededGetScale\",\"message\":\"the HPA controller was able to get the target's current scale\"},{\"type\":\"ScalingActive\",\"status\":\"False\",\"lastTransitionTime\":\"2021-01-05T10:26:04Z\",\"reason\":\"FailedGetResourceMetric\",\"message\":\"the HPA was unable to compute the replica count: unable to get metrics for resource cpu: no metrics returned from resource metrics API\"}]", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"autoscaling/v1\",\"kind\":\"HorizontalPodAutoscaler\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"maxReplicas\":15,\"minReplicas\":10,\"scaleTargetRef\":{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"name\":\"dice-roller\"},\"targetCPUUtilizationPercentage\":50}}\n" + }, + "creationTimestamp": "2021-01-05T10:25:48Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "autoscaling/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:maxReplicas": {}, + "f:minReplicas": {}, + "f:scaleTargetRef": { + "f:apiVersion": {}, + "f:kind": {}, + "f:name": {} + }, + "f:targetCPUUtilizationPercentage": {} + } + }, + "manager": "kubectl-client-side-apply", + "operation": "Update", + "time": "2021-01-05T10:25:48Z" + }, + { + "apiVersion": "autoscaling/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:autoscaling.alpha.kubernetes.io/conditions": {} + } + }, + "f:status": { + "f:currentReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2021-01-05T10:26:04Z" + } + ], + "name": "dice-roller", + "namespace": "default", + "resourceVersion": "598", + "selfLink": "/apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/dice-roller", + "uid": "dd7c5329-567c-43c2-b159-756808d90a8e" + }, + "spec": { + "maxReplicas": 15, + "minReplicas": 10, + "scaleTargetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "dice-roller" + }, + "targetCPUUtilizationPercentage": 50 + }, + "status": { + "currentReplicas": 10, + "desiredReplicas": 0, + "currentCPUUtilizationPercentage": 30 + } + } + ] +} diff --git a/plugins/kubernetes-react/src/__fixtures__/1-statefulsets.json b/plugins/kubernetes-react/src/__fixtures__/1-statefulsets.json new file mode 100644 index 0000000000..6c04774ff1 --- /dev/null +++ b/plugins/kubernetes-react/src/__fixtures__/1-statefulsets.json @@ -0,0 +1,2912 @@ +{ + "pods": [ + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.11\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-2m5hv", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593216", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-2m5hv", + "uid": "aadb71c0-36fa-43e3-b38a-162f134d4359" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://aa4489297c34c48bb33c18474a8d2b33854a82ed42155680b259f635f556ce70", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.11", + "podIPs": [ + { + "ip": "172.17.0.11" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.7\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-4v6s8", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593221", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-4v6s8", + "uid": "32e56490-6f20-4757-991f-a0c7fb407358" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://d91cc76c41249b8d3dfcf538d180b471b2a7966aae0d17a818307c8a9b4af897", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.7", + "podIPs": [ + { + "ip": "172.17.0.7" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-24T11:39:26.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-24T11:39:26.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.6\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-24T11:39:27.000Z" + } + ], + "name": "dice-roller-6c8646bfd-b9zt5", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "503886", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-b9zt5", + "uid": "8b6601b6-469e-4e89-8fd0-abb2f1a567e4" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:26.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:26.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://c50e0d0fa96f09a2ed5df7dd5a7f7de88e6b7c7addb8f002f299d6afc52d82ce", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-24T11:39:27.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.6", + "podIPs": [ + { + "ip": "172.17.0.6" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-24T11:39:26.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.13\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-cfxqc", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593211", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-cfxqc", + "uid": "e87e1776-0ca7-41fb-aeea-e1f648387545" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:51.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://c1641d986aae424429b7c2c1117baeb17d3794f73206bd57292cdf8264f929b2", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.13", + "podIPs": [ + { + "ip": "172.17.0.13" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:51.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.15\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:54.000Z" + } + ], + "name": "dice-roller-6c8646bfd-dtv5z", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593190", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-dtv5z", + "uid": "1638a41b-e47e-4c17-a1f7-7b447df248b6" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:51.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://e62c32db58dbfe0a74b2d2cba0e0a97b7f222693c68e930037ac8738c4758ca3", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.15", + "podIPs": [ + { + "ip": "172.17.0.15" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:51.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.12\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:53.000Z" + } + ], + "name": "dice-roller-6c8646bfd-hhts2", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593186", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-hhts2", + "uid": "ea0b147a-c56a-46e6-9445-7a0b1b0ed3c0" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://bcdbc153630f90556d57ff0d62f04d847ca63a5f0a7e5d9230683623d33d4b8d", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.12", + "podIPs": [ + { + "ip": "172.17.0.12" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.14\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-j68lm", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593226", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-j68lm", + "uid": "b230ff1d-7a13-479b-9c7b-77c26bd79f62" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://30fa8a3429f86ab8e9a4cec472b79d74266609082703f48950f4aae021e9d6a2", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.14", + "podIPs": [ + { + "ip": "172.17.0.14" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.9\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:53.000Z" + } + ], + "name": "dice-roller-6c8646bfd-m6f9w", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593181", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-m6f9w", + "uid": "9b0079f6-ff29-4619-bf6e-71cc10199ac5" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://f78767ee90eedffe46ff64bfe76d7f69426800dd89f3df012daf0baf3a9c5bdd", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.9", + "podIPs": [ + { + "ip": "172.17.0.9" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-24T11:39:27.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-24T11:39:27.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.4\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-24T11:39:28.000Z" + } + ], + "name": "dice-roller-6c8646bfd-nv9pk", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "503918", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-nv9pk", + "uid": "acf7f77f-78c6-4d4b-bc73-637211770ffc" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:28.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:28.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://63dec9b32942c4b09ae43d09d6978261f674a3ee623823b8f1d20da8044c12ac", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-24T11:39:28.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.4", + "podIPs": [ + { + "ip": "172.17.0.4" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-24T11:39:27.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.10\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-pjhfj", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593205", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-pjhfj", + "uid": "78775c3a-7af2-4ebe-a676-bc2e5dfa2bcc" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://cbb83dda250db74285dcbe0b81bd0896acf402bac9710af090311f7360f824aa", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.10", + "podIPs": [ + { + "ip": "172.17.0.10" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + } + ], + "replicaSets": [ + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "10", + "deployment.kubernetes.io/max-replicas": "13", + "deployment.kubernetes.io/revision": "2" + }, + "creationTimestamp": "2020-09-24T11:39:26.000Z", + "generation": 3, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"7551e949-42d1-4061-83c5-9da107186e47\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:availableReplicas": {}, + "f:fullyLabeledReplicas": {}, + "f:observedGeneration": {}, + "f:readyReplicas": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller", + "uid": "7551e949-42d1-4061-83c5-9da107186e47" + } + ], + "resourceVersion": "593228", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + }, + "spec": { + "replicas": 10, + "selector": { + "matchLabels": { + "app": "dice-roller", + "pod-template-hash": "6c8646bfd" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "availableReplicas": 10, + "fullyLabeledReplicas": 10, + "observedGeneration": 3, + "readyReplicas": 10, + "replicas": 10 + } + } + ], + "statefulsets": [ + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/revision": "2", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"StatefulSet\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"replicas\":10,\"selector\":{\"matchLabels\":{\"app\":\"dice-roller\"}},\"template\":{\"metadata\":{\"labels\":{\"app\":\"dice-roller\",\"backstage.io/kubernetes-id\":\"dice-roller\"}},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]}]}}}}\n" + }, + "creationTimestamp": "2020-09-23T12:00:55.000Z", + "generation": 3, + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:progressDeadlineSeconds": {}, + "f:replicas": {}, + "f:revisionHistoryLimit": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {} + } + }, + "f:strategy": { + "f:rollingUpdate": { + ".": {}, + "f:maxSurge": {}, + "f:maxUnavailable": {} + }, + "f:type": {} + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + } + }, + "manager": "kubectl", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:deployment.kubernetes.io/revision": {} + } + }, + "f:status": { + "f:availableReplicas": {}, + "f:conditions": { + ".": {}, + "k:{\"type\":\"Available\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Progressing\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:observedGeneration": {}, + "f:readyReplicas": {}, + "f:replicas": {}, + "f:updatedReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller", + "namespace": "default", + "resourceVersion": "593230", + "selfLink": "/apis/apps/v1/namespaces/default/deployments/dice-roller", + "uid": "7551e949-42d1-4061-83c5-9da107186e47" + }, + "spec": { + "replicas": 10, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "dice-roller" + } + }, + "updateStrategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "podManagementPolicy": "Parallel", + "serviceName": "dice-roller", + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "availableReplicas": 10, + "conditions": [ + { + "lastTransitionTime": "2020-09-23T12:00:55.000Z", + "lastUpdateTime": "2020-09-24T11:39:28.000Z", + "message": "ReplicaSet \"dice-roller-6c8646bfd\" has successfully progressed.", + "reason": "NewReplicaSetAvailable", + "status": "True", + "type": "Progressing" + }, + { + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "lastUpdateTime": "2020-09-25T09:58:55.000Z", + "message": "Deployment has minimum availability.", + "reason": "MinimumReplicasAvailable", + "status": "True", + "type": "Available" + } + ], + "observedGeneration": 3, + "readyReplicas": 10, + "replicas": 10, + "updatedReplicas": 10 + } + } + ], + "horizontalPodAutoscalers": [ + { + "apiVersion": "autoscaling/v1", + "kind": "HorizontalPodAutoscaler", + "metadata": { + "annotations": { + "autoscaling.alpha.kubernetes.io/conditions": "[{\"type\":\"AbleToScale\",\"status\":\"True\",\"lastTransitionTime\":\"2021-01-05T10:26:04Z\",\"reason\":\"SucceededGetScale\",\"message\":\"the HPA controller was able to get the target's current scale\"},{\"type\":\"ScalingActive\",\"status\":\"False\",\"lastTransitionTime\":\"2021-01-05T10:26:04Z\",\"reason\":\"FailedGetResourceMetric\",\"message\":\"the HPA was unable to compute the replica count: unable to get metrics for resource cpu: no metrics returned from resource metrics API\"}]", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"autoscaling/v1\",\"kind\":\"HorizontalPodAutoscaler\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"maxReplicas\":15,\"minReplicas\":10,\"scaleTargetRef\":{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"name\":\"dice-roller\"},\"targetCPUUtilizationPercentage\":50}}\n" + }, + "creationTimestamp": "2021-01-05T10:25:48Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "autoscaling/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:maxReplicas": {}, + "f:minReplicas": {}, + "f:scaleTargetRef": { + "f:apiVersion": {}, + "f:kind": {}, + "f:name": {} + }, + "f:targetCPUUtilizationPercentage": {} + } + }, + "manager": "kubectl-client-side-apply", + "operation": "Update", + "time": "2021-01-05T10:25:48Z" + }, + { + "apiVersion": "autoscaling/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:autoscaling.alpha.kubernetes.io/conditions": {} + } + }, + "f:status": { + "f:currentReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2021-01-05T10:26:04Z" + } + ], + "name": "dice-roller", + "namespace": "default", + "resourceVersion": "598", + "selfLink": "/apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/dice-roller", + "uid": "dd7c5329-567c-43c2-b159-756808d90a8e" + }, + "spec": { + "maxReplicas": 15, + "minReplicas": 10, + "scaleTargetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "dice-roller" + }, + "targetCPUUtilizationPercentage": 50 + }, + "status": { + "currentReplicas": 10, + "desiredReplicas": 0, + "currentCPUUtilizationPercentage": 30 + } + } + ] +} diff --git a/plugins/kubernetes-react/src/__fixtures__/2-cronjobs.json b/plugins/kubernetes-react/src/__fixtures__/2-cronjobs.json new file mode 100644 index 0000000000..6c087023b7 --- /dev/null +++ b/plugins/kubernetes-react/src/__fixtures__/2-cronjobs.json @@ -0,0 +1,385 @@ +{ + "cronJobs": [ + { + "metadata": { + "name": "dice-roller-cronjob", + "namespace": "default", + "uid": "9ea073bc-7a4b-4b99-8321-0305bce85568", + "resourceVersion": "1362732552", + "creationTimestamp": "2021-07-16T22:39:58Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "annotations": {} + }, + "spec": { + "schedule": "* */2 * * *", + "startingDeadlineSeconds": 1800, + "concurrencyPolicy": "Forbid", + "suspend": true, + "jobTemplate": { + "metadata": { "creationTimestamp": null }, + "spec": { + "backoffLimit": 2, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "annotations": {} + }, + "spec": { + "containers": [ + { + "name": "busybox", + "image": "busybox", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "imagePullPolicy": "IfNotPresent", + "command": ["/bin/sh", "-c", "date; echo Rolling a die!"] + } + ], + "restartPolicy": "Never", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "securityContext": {}, + "schedulerName": "default-scheduler" + } + } + } + }, + "successfulJobsHistoryLimit": 2, + "failedJobsHistoryLimit": 2 + }, + "status": { + "lastScheduleTime": "2021-11-16T02:10:00Z" + } + } + ], + "jobs": [ + { + "metadata": { + "name": "dice-roller-cronjob-1637025000", + "namespace": "default", + "uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "resourceVersion": "1361029181", + "creationTimestamp": "2021-11-16T01:10:24Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "ownerReferences": [ + { + "apiVersion": "batch/v1", + "kind": "CronJob", + "name": "dice-roller-cronjob", + "uid": "9ea073bc-7a4b-4b99-8321-0305bce85568", + "controller": true, + "blockOwnerDeletion": true + } + ] + }, + "spec": { + "parallelism": 1, + "completions": 1, + "backoffLimit": 2, + "selector": { + "matchLabels": { + "controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "backstage.io/kubernetes-id": "dice-roller", + "controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "job-name": "dice-roller-cronjob-1637025000" + }, + "annotations": {} + }, + "spec": { + "containers": [ + { + "command": ["/bin/sh", "-c", "date; echo Rolling a die!"], + "image": "busybox", + "imagePullPolicy": "IfNotPresent", + "name": "busybox", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "restartPolicy": "Never", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "securityContext": {}, + "schedulerName": "default-scheduler" + } + } + }, + "status": { + "conditions": [ + { + "type": "Failed", + "status": "True", + "reason": "BackoffLimitExceeded", + "lastProbeTime": "2021-11-16T01:11:31Z", + "lastTransitionTime": "2021-11-16T01:11:31Z" + } + ], + "startTime": "2021-11-16T01:10:24Z", + "failed": 2 + } + } + ], + "pods": [ + { + "metadata": { + "name": "dice-roller-cronjob-1637025000-gstc4", + "generateName": "dice-roller-cronjob-1637025000-", + "namespace": "default", + "uid": "3b0f2b65-5ae2-441a-beda-bdc92bcafaf0", + "resourceVersion": "1361029179", + "creationTimestamp": "2021-11-16T01:10:24Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller", + "controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "job-name": "dice-roller-cronjob-1637025000" + }, + "annotations": {}, + "ownerReferences": [ + { + "apiVersion": "batch/v1", + "kind": "Job", + "name": "dice-roller-cronjob-1637025000", + "uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "controller": true, + "blockOwnerDeletion": true + } + ] + }, + "spec": { + "volumes": [], + "containers": [ + { + "command": ["/bin/sh", "-c", "date; echo Rolling a die!"], + "image": "busybox", + "imagePullPolicy": "IfNotPresent", + "name": "busybox", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "restartPolicy": "Never", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "serviceAccountName": "default", + "serviceAccount": "default", + "nodeName": "minikube", + "securityContext": {}, + "schedulerName": "default-scheduler", + "tolerations": [ + { + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + }, + { + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + } + ], + "priority": 0, + "enableServiceLinks": true + }, + "status": { + "phase": "Failed", + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2021-11-18T19:10:13Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2021-11-18T19:11:02Z", + "message": "containers with unready status: [busybox]", + "reason": "ContainersNotReady", + "status": "False", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2021-11-18T19:11:02Z", + "message": "containers with unready status: [busybox]", + "reason": "ContainersNotReady", + "status": "False", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2021-11-18T19:10:08Z", + "status": "True", + "type": "PodScheduled" + } + ], + "hostIP": "192.168.49.2", + "podIP": "172.17.0.25", + "podIPs": [{ "ip": "172.17.0.25" }], + "startTime": "2021-11-18T19:10:08Z", + "containerStatuses": [ + { + "name": "busybox", + "state": { + "terminated": { + "exitCode": 1, + "finishedAt": "2021-11-18T19:11:01Z", + "reason": "Error", + "startedAt": "2021-11-18T19:10:17Z", + "containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615" + } + }, + "lastState": {}, + "ready": false, + "restartCount": 0, + "image": "busybox:latest", + "imageID": "docker-pullable://busybox@sha256:e7157b6d7ebbe2cce5eaa8cfe8aa4fa82d173999b9f90a9ec42e57323546c353", + "containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615", + "started": false + } + ], + "qosClass": "Burstable" + } + }, + { + "metadata": { + "name": "dice-roller-cronjob-1637025000-p4mlc", + "generateName": "dice-roller-cronjob-1637025000-", + "namespace": "default", + "uid": "acddd5d2-ac7f-473b-a9d8-17a89f99ac39", + "resourceVersion": "1361174579", + "creationTimestamp": "2021-11-16T02:10:22Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller", + "controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "job-name": "dice-roller-cronjob-1637025000" + }, + "annotations": {}, + "ownerReferences": [ + { + "apiVersion": "batch/v1", + "kind": "Job", + "name": "dice-roller-cronjob-1637025000", + "uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a", + "controller": true, + "blockOwnerDeletion": true + } + ] + }, + "spec": { + "volumes": [], + "containers": [ + { + "command": ["/bin/sh", "-c", "date; echo Rolling a die!"], + "image": "busybox", + "imagePullPolicy": "IfNotPresent", + "name": "busybox", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "restartPolicy": "Never", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "serviceAccountName": "default", + "serviceAccount": "default", + "nodeName": "minikube", + "securityContext": {}, + "schedulerName": "default-scheduler", + "tolerations": [ + { + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + }, + { + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + } + ], + "priority": 0, + "enableServiceLinks": true + }, + "status": { + "phase": "Failed", + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2021-11-18T19:10:13Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2021-11-18T19:11:02Z", + "message": "containers with unready status: [busybox]", + "reason": "ContainersNotReady", + "status": "False", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2021-11-18T19:11:02Z", + "message": "containers with unready status: [busybox]", + "reason": "ContainersNotReady", + "status": "False", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2021-11-18T19:10:08Z", + "status": "True", + "type": "PodScheduled" + } + ], + "hostIP": "192.168.49.2", + "podIP": "172.17.0.25", + "podIPs": [{ "ip": "172.17.0.25" }], + "startTime": "2021-11-16T02:10:22Z", + "containerStatuses": [ + { + "name": "busybox", + "state": { + "terminated": { + "exitCode": 1, + "finishedAt": "2021-11-18T19:11:01Z", + "reason": "Error", + "startedAt": "2021-11-18T19:10:17Z", + "containerID": "docker://2659c4d0f8a68f2b49863c18738322f1686d5b87275428e5e641fd9fd9e06739" + } + }, + "lastState": {}, + "ready": true, + "restartCount": 0, + "image": "busybox:latest", + "imageID": "docker-pullable://busybox@sha256:e7157b6d7ebbe2cce5eaa8cfe8aa4fa82d173999b9f90a9ec42e57323546c353", + "containerID": "docker://2659c4d0f8a68f2b49863c18738322f1686d5b87275428e5e641fd9fd9e06739", + "started": true + } + ], + "qosClass": "Burstable" + } + } + ] +} diff --git a/plugins/kubernetes-react/src/__fixtures__/2-deployments.json b/plugins/kubernetes-react/src/__fixtures__/2-deployments.json new file mode 100644 index 0000000000..f5efdbf1cb --- /dev/null +++ b/plugins/kubernetes-react/src/__fixtures__/2-deployments.json @@ -0,0 +1,4519 @@ +{ + "pods": [ + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.11\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-2m5hv", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593216", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-2m5hv", + "uid": "aadb71c0-36fa-43e3-b38a-162f134d4359" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://aa4489297c34c48bb33c18474a8d2b33854a82ed42155680b259f635f556ce70", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.11", + "podIPs": [ + { + "ip": "172.17.0.11" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.7\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-4v6s8", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593221", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-4v6s8", + "uid": "32e56490-6f20-4757-991f-a0c7fb407358" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://d91cc76c41249b8d3dfcf538d180b471b2a7966aae0d17a818307c8a9b4af897", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.7", + "podIPs": [ + { + "ip": "172.17.0.7" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-24T11:39:26.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-24T11:39:26.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.6\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-24T11:39:27.000Z" + } + ], + "name": "dice-roller-6c8646bfd-b9zt5", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "503886", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-b9zt5", + "uid": "8b6601b6-469e-4e89-8fd0-abb2f1a567e4" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:26.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:26.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://c50e0d0fa96f09a2ed5df7dd5a7f7de88e6b7c7addb8f002f299d6afc52d82ce", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-24T11:39:27.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.6", + "podIPs": [ + { + "ip": "172.17.0.6" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-24T11:39:26.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.13\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-cfxqc", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593211", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-cfxqc", + "uid": "e87e1776-0ca7-41fb-aeea-e1f648387545" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:51.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://c1641d986aae424429b7c2c1117baeb17d3794f73206bd57292cdf8264f929b2", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.13", + "podIPs": [ + { + "ip": "172.17.0.13" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:51.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.15\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:54.000Z" + } + ], + "name": "dice-roller-6c8646bfd-dtv5z", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593190", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-dtv5z", + "uid": "1638a41b-e47e-4c17-a1f7-7b447df248b6" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:51.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://e62c32db58dbfe0a74b2d2cba0e0a97b7f222693c68e930037ac8738c4758ca3", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.15", + "podIPs": [ + { + "ip": "172.17.0.15" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:51.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.12\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:53.000Z" + } + ], + "name": "dice-roller-6c8646bfd-hhts2", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593186", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-hhts2", + "uid": "ea0b147a-c56a-46e6-9445-7a0b1b0ed3c0" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://bcdbc153630f90556d57ff0d62f04d847ca63a5f0a7e5d9230683623d33d4b8d", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.12", + "podIPs": [ + { + "ip": "172.17.0.12" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.14\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-j68lm", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593226", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-j68lm", + "uid": "b230ff1d-7a13-479b-9c7b-77c26bd79f62" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://30fa8a3429f86ab8e9a4cec472b79d74266609082703f48950f4aae021e9d6a2", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.14", + "podIPs": [ + { + "ip": "172.17.0.14" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.9\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:53.000Z" + } + ], + "name": "dice-roller-6c8646bfd-m6f9w", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593181", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-m6f9w", + "uid": "9b0079f6-ff29-4619-bf6e-71cc10199ac5" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://f78767ee90eedffe46ff64bfe76d7f69426800dd89f3df012daf0baf3a9c5bdd", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.9", + "podIPs": [ + { + "ip": "172.17.0.9" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-24T11:39:27.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-24T11:39:27.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.4\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-24T11:39:28.000Z" + } + ], + "name": "dice-roller-6c8646bfd-nv9pk", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "503918", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-nv9pk", + "uid": "acf7f77f-78c6-4d4b-bc73-637211770ffc" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:28.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:28.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://63dec9b32942c4b09ae43d09d6978261f674a3ee623823b8f1d20da8044c12ac", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-24T11:39:28.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.4", + "podIPs": [ + { + "ip": "172.17.0.4" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-24T11:39:27.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.10\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-pjhfj", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593205", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-pjhfj", + "uid": "78775c3a-7af2-4ebe-a676-bc2e5dfa2bcc" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://cbb83dda250db74285dcbe0b81bd0896acf402bac9710af090311f7360f824aa", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.10", + "podIPs": [ + { + "ip": "172.17.0.10" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T10:34:01.000Z", + "generateName": "dice-roller-canary-7d64cd756c-", + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "7d64cd756c" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"9208395b-a9a7-4e46-b881-6a189f7fbdb0\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"other-side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":82,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T10:34:01.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.16\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T14:18:54.000Z" + } + ], + "name": "dice-roller-canary-7d64cd756c-55rfq", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-canary-7d64cd756c", + "uid": "9208395b-a9a7-4e46-b881-6a189f7fbdb0" + } + ], + "resourceVersion": "620452", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-canary-7d64cd756c-55rfq", + "uid": "65ad28e3-5d51-4b4b-9bf8-4cb069803034" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "other-side-car", + "ports": [ + { + "containerPort": 82, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T10:34:01.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T14:18:53.000Z", + "message": "containers with unready status: [side-car other-side-car]", + "reason": "ContainersNotReady", + "status": "False", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T14:18:53.000Z", + "message": "containers with unready status: [side-car other-side-car]", + "reason": "ContainersNotReady", + "status": "False", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T10:34:01.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://6ce15178d114a85f3d2e832de45c3355ab5b71ed5f4d4d225ee1c83bf07f69d9", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T10:34:01.000Z" + } + } + }, + { + "containerID": "docker://b3ce93d7f90bfe22558c61d2505b8473580574accdebb5fa4e51c0729c3511f4", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": { + "terminated": { + "containerID": "docker://b3ce93d7f90bfe22558c61d2505b8473580574accdebb5fa4e51c0729c3511f4", + "exitCode": 1, + "finishedAt": "2020-09-25T14:18:52.000Z", + "reason": "Error", + "startedAt": "2020-09-25T14:18:50.000Z" + } + }, + "name": "other-side-car", + "ready": false, + "restartCount": 38, + "started": false, + "state": { + "waiting": { + "message": "back-off 5m0s restarting failed container=other-side-car pod=dice-roller-canary-7d64cd756c-55rfq_default(65ad28e3-5d51-4b4b-9bf8-4cb069803034)", + "reason": "CrashLoopBackOff" + } + } + }, + { + "containerID": "docker://b7f0e65a2b8ab48c5f234616cfe8286aa96b55c3ef09c5cfbc4cdbe67a96f8cb", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": { + "terminated": { + "containerID": "docker://b7f0e65a2b8ab48c5f234616cfe8286aa96b55c3ef09c5cfbc4cdbe67a96f8cb", + "exitCode": 1, + "finishedAt": "2020-09-25T14:18:52.000Z", + "reason": "Error", + "startedAt": "2020-09-25T14:18:50.000Z" + } + }, + "name": "side-car", + "ready": false, + "restartCount": 38, + "started": false, + "state": { + "waiting": { + "message": "back-off 5m0s restarting failed container=side-car pod=dice-roller-canary-7d64cd756c-55rfq_default(65ad28e3-5d51-4b4b-9bf8-4cb069803034)", + "reason": "CrashLoopBackOff" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.16", + "podIPs": [ + { + "ip": "172.17.0.16" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T10:34:01.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T10:34:02.000Z", + "generateName": "dice-roller-canary-7d64cd756c-", + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "7d64cd756c" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"9208395b-a9a7-4e46-b881-6a189f7fbdb0\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"other-side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":82,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T10:34:02.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.5\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T14:19:05.000Z" + } + ], + "name": "dice-roller-canary-7d64cd756c-vtbdx", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-canary-7d64cd756c", + "uid": "9208395b-a9a7-4e46-b881-6a189f7fbdb0" + } + ], + "resourceVersion": "620481", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-canary-7d64cd756c-vtbdx", + "uid": "0b8d9d79-b43d-4339-be57-ad5c63add77e" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "other-side-car", + "ports": [ + { + "containerPort": 82, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T10:34:02.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T14:19:04.000Z", + "message": "containers with unready status: [side-car other-side-car]", + "reason": "ContainersNotReady", + "status": "False", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T14:19:04.000Z", + "message": "containers with unready status: [side-car other-side-car]", + "reason": "ContainersNotReady", + "status": "False", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T10:34:02.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://3f9cadc6f135247eb2df9aaca8f25ea05dcf42be86d58fb833c8acf192da0d66", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T10:34:03.000Z" + } + } + }, + { + "containerID": "docker://5e3a9f9129e5ce74fea249c013afcc056ee95a940fed24495ef9b58df67771f3", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": { + "terminated": { + "containerID": "docker://5e3a9f9129e5ce74fea249c013afcc056ee95a940fed24495ef9b58df67771f3", + "exitCode": 1, + "finishedAt": "2020-09-25T14:19:03.000Z", + "reason": "Error", + "startedAt": "2020-09-25T14:19:01.000Z" + } + }, + "name": "other-side-car", + "ready": false, + "restartCount": 38, + "started": false, + "state": { + "waiting": { + "message": "back-off 5m0s restarting failed container=other-side-car pod=dice-roller-canary-7d64cd756c-vtbdx_default(0b8d9d79-b43d-4339-be57-ad5c63add77e)", + "reason": "CrashLoopBackOff" + } + } + }, + { + "containerID": "docker://21b42cae298c0ed7f90373974d8c88b0941d17733f35398144a17ece32e03210", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": { + "terminated": { + "containerID": "docker://21b42cae298c0ed7f90373974d8c88b0941d17733f35398144a17ece32e03210", + "exitCode": 1, + "finishedAt": "2020-09-25T14:19:03.000Z", + "reason": "Error", + "startedAt": "2020-09-25T14:19:01.000Z" + } + }, + "name": "side-car", + "ready": false, + "restartCount": 38, + "started": false, + "state": { + "waiting": { + "message": "back-off 5m0s restarting failed container=side-car pod=dice-roller-canary-7d64cd756c-vtbdx_default(0b8d9d79-b43d-4339-be57-ad5c63add77e)", + "reason": "CrashLoopBackOff" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.5", + "podIPs": [ + { + "ip": "172.17.0.5" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T10:34:02.000Z" + } + } + ], + "replicaSets": [ + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "10", + "deployment.kubernetes.io/max-replicas": "13", + "deployment.kubernetes.io/revision": "2" + }, + "creationTimestamp": "2020-09-24T11:39:26.000Z", + "generation": 3, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"7551e949-42d1-4061-83c5-9da107186e47\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:availableReplicas": {}, + "f:fullyLabeledReplicas": {}, + "f:observedGeneration": {}, + "f:readyReplicas": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller", + "uid": "7551e949-42d1-4061-83c5-9da107186e47" + } + ], + "resourceVersion": "593228", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + }, + "spec": { + "replicas": 10, + "selector": { + "matchLabels": { + "app": "dice-roller", + "pod-template-hash": "6c8646bfd" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "availableReplicas": 10, + "fullyLabeledReplicas": 10, + "observedGeneration": 3, + "readyReplicas": 10, + "replicas": 10 + } + }, + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "2", + "deployment.kubernetes.io/max-replicas": "3", + "deployment.kubernetes.io/revision": "3" + }, + "creationTimestamp": "2020-09-25T10:34:01.000Z", + "generation": 2, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "7d64cd756c" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"0b6ae80f-999b-40e9-b116-ea925f0ed07b\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"other-side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":82,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:fullyLabeledReplicas": {}, + "f:observedGeneration": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T14:19:01.000Z" + } + ], + "name": "dice-roller-canary-7d64cd756c", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller-canary", + "uid": "0b6ae80f-999b-40e9-b116-ea925f0ed07b" + } + ], + "resourceVersion": "620479", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-canary-7d64cd756c", + "uid": "9208395b-a9a7-4e46-b881-6a189f7fbdb0" + }, + "spec": { + "replicas": 2, + "selector": { + "matchLabels": { + "app": "dice-roller-canary", + "pod-template-hash": "7d64cd756c" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "7d64cd756c" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "other-side-car", + "ports": [ + { + "containerPort": 82, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "fullyLabeledReplicas": 2, + "observedGeneration": 2, + "replicas": 2 + } + }, + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "2", + "deployment.kubernetes.io/max-replicas": "3", + "deployment.kubernetes.io/revision": "2" + }, + "creationTimestamp": "2020-09-25T09:25:16.000Z", + "generation": 4, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "bcb8d54dd" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"0b6ae80f-999b-40e9-b116-ea925f0ed07b\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:observedGeneration": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T10:34:04.000Z" + } + ], + "name": "dice-roller-canary-bcb8d54dd", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller-canary", + "uid": "0b6ae80f-999b-40e9-b116-ea925f0ed07b" + } + ], + "resourceVersion": "598025", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-canary-bcb8d54dd", + "uid": "51942585-d599-42aa-bf23-9cf1acad4006" + }, + "spec": { + "replicas": 0, + "selector": { + "matchLabels": { + "app": "dice-roller-canary", + "pod-template-hash": "bcb8d54dd" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "bcb8d54dd" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "observedGeneration": 4, + "replicas": 0 + } + }, + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "2", + "deployment.kubernetes.io/max-replicas": "3", + "deployment.kubernetes.io/revision": "1" + }, + "creationTimestamp": "2020-09-25T09:02:53.000Z", + "generation": 3, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "c866fbf67" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"0b6ae80f-999b-40e9-b116-ea925f0ed07b\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:observedGeneration": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:25:20.000Z" + } + ], + "name": "dice-roller-canary-c866fbf67", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller-canary", + "uid": "0b6ae80f-999b-40e9-b116-ea925f0ed07b" + } + ], + "resourceVersion": "588501", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-canary-c866fbf67", + "uid": "4d2dfe13-978f-4504-9036-ca585acdea6c" + }, + "spec": { + "replicas": 0, + "selector": { + "matchLabels": { + "app": "dice-roller-canary", + "pod-template-hash": "c866fbf67" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "c866fbf67" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "observedGeneration": 3, + "replicas": 0 + } + } + ], + "deployments": [ + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/revision": "2", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"replicas\":10,\"selector\":{\"matchLabels\":{\"app\":\"dice-roller\"}},\"template\":{\"metadata\":{\"labels\":{\"app\":\"dice-roller\",\"backstage.io/kubernetes-id\":\"dice-roller\"}},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]}]}}}}\n" + }, + "creationTimestamp": "2020-09-23T12:00:55.000Z", + "generation": 3, + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:progressDeadlineSeconds": {}, + "f:replicas": {}, + "f:revisionHistoryLimit": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {} + } + }, + "f:strategy": { + "f:rollingUpdate": { + ".": {}, + "f:maxSurge": {}, + "f:maxUnavailable": {} + }, + "f:type": {} + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + } + }, + "manager": "kubectl", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:deployment.kubernetes.io/revision": {} + } + }, + "f:status": { + "f:availableReplicas": {}, + "f:conditions": { + ".": {}, + "k:{\"type\":\"Available\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Progressing\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:observedGeneration": {}, + "f:readyReplicas": {}, + "f:replicas": {}, + "f:updatedReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller", + "namespace": "default", + "resourceVersion": "593230", + "selfLink": "/apis/apps/v1/namespaces/default/deployments/dice-roller", + "uid": "7551e949-42d1-4061-83c5-9da107186e47" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 10, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "dice-roller" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "availableReplicas": 10, + "conditions": [ + { + "lastTransitionTime": "2020-09-23T12:00:55.000Z", + "lastUpdateTime": "2020-09-24T11:39:28.000Z", + "message": "ReplicaSet \"dice-roller-6c8646bfd\" has successfully progressed.", + "reason": "NewReplicaSetAvailable", + "status": "True", + "type": "Progressing" + }, + { + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "lastUpdateTime": "2020-09-25T09:58:55.000Z", + "message": "Deployment has minimum availability.", + "reason": "MinimumReplicasAvailable", + "status": "True", + "type": "Available" + } + ], + "observedGeneration": 3, + "readyReplicas": 10, + "replicas": 10, + "updatedReplicas": 10 + } + }, + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/revision": "3", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller-canary\",\"namespace\":\"default\"},\"spec\":{\"replicas\":2,\"selector\":{\"matchLabels\":{\"app\":\"dice-roller-canary\"}},\"template\":{\"metadata\":{\"labels\":{\"app\":\"dice-roller-canary\",\"backstage.io/kubernetes-id\":\"dice-roller\"}},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]},{\"image\":\"nginx:1.14.2\",\"name\":\"side-car\",\"ports\":[{\"containerPort\":81}]},{\"image\":\"nginx:1.14.2\",\"name\":\"other-side-car\",\"ports\":[{\"containerPort\":82}]}]}}}}\n" + }, + "creationTimestamp": "2020-09-25T09:02:53.000Z", + "generation": 3, + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:progressDeadlineSeconds": {}, + "f:replicas": {}, + "f:revisionHistoryLimit": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {} + } + }, + "f:strategy": { + "f:rollingUpdate": { + ".": {}, + "f:maxSurge": {}, + "f:maxUnavailable": {} + }, + "f:type": {} + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"other-side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":82,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + } + }, + "manager": "kubectl", + "operation": "Update", + "time": "2020-09-25T10:34:01.000Z" + }, + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:deployment.kubernetes.io/revision": {} + } + }, + "f:status": { + "f:conditions": { + ".": {}, + "k:{\"type\":\"Available\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Progressing\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:observedGeneration": {}, + "f:replicas": {}, + "f:unavailableReplicas": {}, + "f:updatedReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T14:19:04.000Z" + } + ], + "name": "dice-roller-canary", + "namespace": "default", + "resourceVersion": "620480", + "selfLink": "/apis/apps/v1/namespaces/default/deployments/dice-roller-canary", + "uid": "0b6ae80f-999b-40e9-b116-ea925f0ed07b" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 2, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "dice-roller-canary" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "other-side-car", + "ports": [ + { + "containerPort": 82, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "conditions": [ + { + "lastTransitionTime": "2020-09-25T09:02:53.000Z", + "lastUpdateTime": "2020-09-25T10:34:04.000Z", + "message": "ReplicaSet \"dice-roller-canary-7d64cd756c\" has successfully progressed.", + "reason": "NewReplicaSetAvailable", + "status": "True", + "type": "Progressing" + }, + { + "lastTransitionTime": "2020-09-25T13:48:06.000Z", + "lastUpdateTime": "2020-09-25T13:48:06.000Z", + "message": "Deployment does not have minimum availability.", + "reason": "MinimumReplicasUnavailable", + "status": "False", + "type": "Available" + } + ], + "observedGeneration": 3, + "replicas": 2, + "unavailableReplicas": 2, + "updatedReplicas": 2 + } + } + ], + "horizontalPodAutoscalers": [ + { + "apiVersion": "autoscaling/v1", + "kind": "HorizontalPodAutoscaler", + "metadata": { + "annotations": { + "autoscaling.alpha.kubernetes.io/conditions": "[{\"type\":\"AbleToScale\",\"status\":\"True\",\"lastTransitionTime\":\"2021-01-05T10:26:04Z\",\"reason\":\"SucceededGetScale\",\"message\":\"the HPA controller was able to get the target's current scale\"},{\"type\":\"ScalingActive\",\"status\":\"False\",\"lastTransitionTime\":\"2021-01-05T10:26:04Z\",\"reason\":\"FailedGetResourceMetric\",\"message\":\"the HPA was unable to compute the replica count: unable to get metrics for resource cpu: no metrics returned from resource metrics API\"}]", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"autoscaling/v1\",\"kind\":\"HorizontalPodAutoscaler\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"maxReplicas\":15,\"minReplicas\":10,\"scaleTargetRef\":{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"name\":\"dice-roller\"},\"targetCPUUtilizationPercentage\":50}}\n" + }, + "creationTimestamp": "2021-01-05T10:25:48Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "autoscaling/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:maxReplicas": {}, + "f:minReplicas": {}, + "f:scaleTargetRef": { + "f:apiVersion": {}, + "f:kind": {}, + "f:name": {} + }, + "f:targetCPUUtilizationPercentage": {} + } + }, + "manager": "kubectl-client-side-apply", + "operation": "Update", + "time": "2021-01-05T10:25:48Z" + }, + { + "apiVersion": "autoscaling/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:autoscaling.alpha.kubernetes.io/conditions": {} + } + }, + "f:status": { + "f:currentReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2021-01-05T10:26:04Z" + } + ], + "name": "dice-roller", + "namespace": "default", + "resourceVersion": "598", + "selfLink": "/apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/dice-roller", + "uid": "dd7c5329-567c-43c2-b159-756808d90a8e" + }, + "spec": { + "maxReplicas": 15, + "minReplicas": 10, + "scaleTargetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "dice-roller" + }, + "targetCPUUtilizationPercentage": 50 + }, + "status": { + "currentReplicas": 10, + "desiredReplicas": 0, + "currentCPUUtilizationPercentage": 30 + } + } + ] +} diff --git a/plugins/kubernetes-react/src/__fixtures__/2-statefulsets.json b/plugins/kubernetes-react/src/__fixtures__/2-statefulsets.json new file mode 100644 index 0000000000..0a8c26c198 --- /dev/null +++ b/plugins/kubernetes-react/src/__fixtures__/2-statefulsets.json @@ -0,0 +1,4521 @@ +{ + "pods": [ + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.11\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-2m5hv", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "StatefulSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593216", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-2m5hv", + "uid": "aadb71c0-36fa-43e3-b38a-162f134d4359" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://aa4489297c34c48bb33c18474a8d2b33854a82ed42155680b259f635f556ce70", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.11", + "podIPs": [ + { + "ip": "172.17.0.11" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.7\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-4v6s8", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593221", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-4v6s8", + "uid": "32e56490-6f20-4757-991f-a0c7fb407358" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://d91cc76c41249b8d3dfcf538d180b471b2a7966aae0d17a818307c8a9b4af897", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.7", + "podIPs": [ + { + "ip": "172.17.0.7" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-24T11:39:26.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-24T11:39:26.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.6\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-24T11:39:27.000Z" + } + ], + "name": "dice-roller-6c8646bfd-b9zt5", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "503886", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-b9zt5", + "uid": "8b6601b6-469e-4e89-8fd0-abb2f1a567e4" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:26.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:26.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://c50e0d0fa96f09a2ed5df7dd5a7f7de88e6b7c7addb8f002f299d6afc52d82ce", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-24T11:39:27.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.6", + "podIPs": [ + { + "ip": "172.17.0.6" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-24T11:39:26.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.13\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-cfxqc", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593211", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-cfxqc", + "uid": "e87e1776-0ca7-41fb-aeea-e1f648387545" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:51.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://c1641d986aae424429b7c2c1117baeb17d3794f73206bd57292cdf8264f929b2", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.13", + "podIPs": [ + { + "ip": "172.17.0.13" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:51.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.15\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:54.000Z" + } + ], + "name": "dice-roller-6c8646bfd-dtv5z", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593190", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-dtv5z", + "uid": "1638a41b-e47e-4c17-a1f7-7b447df248b6" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:51.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://e62c32db58dbfe0a74b2d2cba0e0a97b7f222693c68e930037ac8738c4758ca3", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.15", + "podIPs": [ + { + "ip": "172.17.0.15" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:51.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.12\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:53.000Z" + } + ], + "name": "dice-roller-6c8646bfd-hhts2", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593186", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-hhts2", + "uid": "ea0b147a-c56a-46e6-9445-7a0b1b0ed3c0" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://bcdbc153630f90556d57ff0d62f04d847ca63a5f0a7e5d9230683623d33d4b8d", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.12", + "podIPs": [ + { + "ip": "172.17.0.12" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.14\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-j68lm", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593226", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-j68lm", + "uid": "b230ff1d-7a13-479b-9c7b-77c26bd79f62" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://30fa8a3429f86ab8e9a4cec472b79d74266609082703f48950f4aae021e9d6a2", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.14", + "podIPs": [ + { + "ip": "172.17.0.14" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.9\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:53.000Z" + } + ], + "name": "dice-roller-6c8646bfd-m6f9w", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593181", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-m6f9w", + "uid": "9b0079f6-ff29-4619-bf6e-71cc10199ac5" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:53.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://f78767ee90eedffe46ff64bfe76d7f69426800dd89f3df012daf0baf3a9c5bdd", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.9", + "podIPs": [ + { + "ip": "172.17.0.9" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-24T11:39:27.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-24T11:39:27.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.4\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-24T11:39:28.000Z" + } + ], + "name": "dice-roller-6c8646bfd-nv9pk", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "503918", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-nv9pk", + "uid": "acf7f77f-78c6-4d4b-bc73-637211770ffc" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:28.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:28.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-24T11:39:27.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://63dec9b32942c4b09ae43d09d6978261f674a3ee623823b8f1d20da8044c12ac", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-24T11:39:28.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.4", + "podIPs": [ + { + "ip": "172.17.0.4" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-24T11:39:27.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T09:58:50.000Z", + "generateName": "dice-roller-6c8646bfd-", + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"5126c354-4310-4e23-a9e4-c9b87cb69792\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.10\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd-pjhfj", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + } + ], + "resourceVersion": "593205", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-6c8646bfd-pjhfj", + "uid": "78775c3a-7af2-4ebe-a676-bc2e5dfa2bcc" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T09:58:50.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://cbb83dda250db74285dcbe0b81bd0896acf402bac9710af090311f7360f824aa", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T09:58:53.000Z" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.10", + "podIPs": [ + { + "ip": "172.17.0.10" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T09:58:50.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T10:34:01.000Z", + "generateName": "dice-roller-canary-7d64cd756c-", + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "7d64cd756c" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"9208395b-a9a7-4e46-b881-6a189f7fbdb0\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"other-side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":82,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T10:34:01.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.16\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T14:18:54.000Z" + } + ], + "name": "dice-roller-canary-7d64cd756c-55rfq", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-canary-7d64cd756c", + "uid": "9208395b-a9a7-4e46-b881-6a189f7fbdb0" + } + ], + "resourceVersion": "620452", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-canary-7d64cd756c-55rfq", + "uid": "65ad28e3-5d51-4b4b-9bf8-4cb069803034" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "other-side-car", + "ports": [ + { + "containerPort": 82, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T10:34:01.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T14:18:53.000Z", + "message": "containers with unready status: [side-car other-side-car]", + "reason": "ContainersNotReady", + "status": "False", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T14:18:53.000Z", + "message": "containers with unready status: [side-car other-side-car]", + "reason": "ContainersNotReady", + "status": "False", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T10:34:01.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://6ce15178d114a85f3d2e832de45c3355ab5b71ed5f4d4d225ee1c83bf07f69d9", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T10:34:01.000Z" + } + } + }, + { + "containerID": "docker://b3ce93d7f90bfe22558c61d2505b8473580574accdebb5fa4e51c0729c3511f4", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": { + "terminated": { + "containerID": "docker://b3ce93d7f90bfe22558c61d2505b8473580574accdebb5fa4e51c0729c3511f4", + "exitCode": 1, + "finishedAt": "2020-09-25T14:18:52.000Z", + "reason": "Error", + "startedAt": "2020-09-25T14:18:50.000Z" + } + }, + "name": "other-side-car", + "ready": false, + "restartCount": 38, + "started": false, + "state": { + "waiting": { + "message": "back-off 5m0s restarting failed container=other-side-car pod=dice-roller-canary-7d64cd756c-55rfq_default(65ad28e3-5d51-4b4b-9bf8-4cb069803034)", + "reason": "CrashLoopBackOff" + } + } + }, + { + "containerID": "docker://b7f0e65a2b8ab48c5f234616cfe8286aa96b55c3ef09c5cfbc4cdbe67a96f8cb", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": { + "terminated": { + "containerID": "docker://b7f0e65a2b8ab48c5f234616cfe8286aa96b55c3ef09c5cfbc4cdbe67a96f8cb", + "exitCode": 1, + "finishedAt": "2020-09-25T14:18:52.000Z", + "reason": "Error", + "startedAt": "2020-09-25T14:18:50.000Z" + } + }, + "name": "side-car", + "ready": false, + "restartCount": 38, + "started": false, + "state": { + "waiting": { + "message": "back-off 5m0s restarting failed container=side-car pod=dice-roller-canary-7d64cd756c-55rfq_default(65ad28e3-5d51-4b4b-9bf8-4cb069803034)", + "reason": "CrashLoopBackOff" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.16", + "podIPs": [ + { + "ip": "172.17.0.16" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T10:34:01.000Z" + } + }, + { + "metadata": { + "creationTimestamp": "2020-09-25T10:34:02.000Z", + "generateName": "dice-roller-canary-7d64cd756c-", + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "7d64cd756c" + }, + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:generateName": {}, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"9208395b-a9a7-4e46-b881-6a189f7fbdb0\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"other-side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":82,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:enableServiceLinks": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T10:34:02.000Z" + }, + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:status": { + "f:conditions": { + "k:{\"type\":\"ContainersReady\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Initialized\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Ready\"}": { + ".": {}, + "f:lastProbeTime": {}, + "f:lastTransitionTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:containerStatuses": {}, + "f:hostIP": {}, + "f:phase": {}, + "f:podIP": {}, + "f:podIPs": { + ".": {}, + "k:{\"ip\":\"172.17.0.5\"}": { + ".": {}, + "f:ip": {} + } + }, + "f:startTime": {} + } + }, + "manager": "kubelet", + "operation": "Update", + "time": "2020-09-25T14:19:05.000Z" + } + ], + "name": "dice-roller-canary-7d64cd756c-vtbdx", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "dice-roller-canary-7d64cd756c", + "uid": "9208395b-a9a7-4e46-b881-6a189f7fbdb0" + } + ], + "resourceVersion": "620481", + "selfLink": "/api/v1/namespaces/default/pods/dice-roller-canary-7d64cd756c-vtbdx", + "uid": "0b8d9d79-b43d-4339-be57-ad5c63add77e" + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "other-side-car", + "ports": [ + { + "containerPort": 82, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "default-token-5gctn", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "minikube", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "default-token-5gctn", + "secret": { + "defaultMode": 420, + "secretName": "default-token-5gctn" + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T10:34:02.000Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T14:19:04.000Z", + "message": "containers with unready status: [side-car other-side-car]", + "reason": "ContainersNotReady", + "status": "False", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T14:19:04.000Z", + "message": "containers with unready status: [side-car other-side-car]", + "reason": "ContainersNotReady", + "status": "False", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2020-09-25T10:34:02.000Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "docker://3f9cadc6f135247eb2df9aaca8f25ea05dcf42be86d58fb833c8acf192da0d66", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": {}, + "name": "nginx", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2020-09-25T10:34:03.000Z" + } + } + }, + { + "containerID": "docker://5e3a9f9129e5ce74fea249c013afcc056ee95a940fed24495ef9b58df67771f3", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": { + "terminated": { + "containerID": "docker://5e3a9f9129e5ce74fea249c013afcc056ee95a940fed24495ef9b58df67771f3", + "exitCode": 1, + "finishedAt": "2020-09-25T14:19:03.000Z", + "reason": "Error", + "startedAt": "2020-09-25T14:19:01.000Z" + } + }, + "name": "other-side-car", + "ready": false, + "restartCount": 38, + "started": false, + "state": { + "waiting": { + "message": "back-off 5m0s restarting failed container=other-side-car pod=dice-roller-canary-7d64cd756c-vtbdx_default(0b8d9d79-b43d-4339-be57-ad5c63add77e)", + "reason": "CrashLoopBackOff" + } + } + }, + { + "containerID": "docker://21b42cae298c0ed7f90373974d8c88b0941d17733f35398144a17ece32e03210", + "image": "nginx:1.14.2", + "imageID": "docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d", + "lastState": { + "terminated": { + "containerID": "docker://21b42cae298c0ed7f90373974d8c88b0941d17733f35398144a17ece32e03210", + "exitCode": 1, + "finishedAt": "2020-09-25T14:19:03.000Z", + "reason": "Error", + "startedAt": "2020-09-25T14:19:01.000Z" + } + }, + "name": "side-car", + "ready": false, + "restartCount": 38, + "started": false, + "state": { + "waiting": { + "message": "back-off 5m0s restarting failed container=side-car pod=dice-roller-canary-7d64cd756c-vtbdx_default(0b8d9d79-b43d-4339-be57-ad5c63add77e)", + "reason": "CrashLoopBackOff" + } + } + } + ], + "hostIP": "192.168.64.2", + "phase": "Running", + "podIP": "172.17.0.5", + "podIPs": [ + { + "ip": "172.17.0.5" + } + ], + "qosClass": "BestEffort", + "startTime": "2020-09-25T10:34:02.000Z" + } + } + ], + "replicaSets": [ + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "10", + "deployment.kubernetes.io/max-replicas": "13", + "deployment.kubernetes.io/revision": "2" + }, + "creationTimestamp": "2020-09-24T11:39:26.000Z", + "generation": 3, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"7551e949-42d1-4061-83c5-9da107186e47\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:availableReplicas": {}, + "f:fullyLabeledReplicas": {}, + "f:observedGeneration": {}, + "f:readyReplicas": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller-6c8646bfd", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller", + "uid": "7551e949-42d1-4061-83c5-9da107186e47" + } + ], + "resourceVersion": "593228", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-6c8646bfd", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + }, + "spec": { + "replicas": 10, + "selector": { + "matchLabels": { + "app": "dice-roller", + "pod-template-hash": "6c8646bfd" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "6c8646bfd" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "availableReplicas": 10, + "fullyLabeledReplicas": 10, + "observedGeneration": 3, + "readyReplicas": 10, + "replicas": 10 + } + }, + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "2", + "deployment.kubernetes.io/max-replicas": "3", + "deployment.kubernetes.io/revision": "3" + }, + "creationTimestamp": "2020-09-25T10:34:01.000Z", + "generation": 2, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "7d64cd756c" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"0b6ae80f-999b-40e9-b116-ea925f0ed07b\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"other-side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":82,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:fullyLabeledReplicas": {}, + "f:observedGeneration": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T14:19:01.000Z" + } + ], + "name": "dice-roller-canary-7d64cd756c", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller-canary", + "uid": "0b6ae80f-999b-40e9-b116-ea925f0ed07b" + } + ], + "resourceVersion": "620479", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-canary-7d64cd756c", + "uid": "9208395b-a9a7-4e46-b881-6a189f7fbdb0" + }, + "spec": { + "replicas": 2, + "selector": { + "matchLabels": { + "app": "dice-roller-canary", + "pod-template-hash": "7d64cd756c" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "7d64cd756c" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "other-side-car", + "ports": [ + { + "containerPort": 82, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "fullyLabeledReplicas": 2, + "observedGeneration": 2, + "replicas": 2 + } + }, + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "2", + "deployment.kubernetes.io/max-replicas": "3", + "deployment.kubernetes.io/revision": "2" + }, + "creationTimestamp": "2020-09-25T09:25:16.000Z", + "generation": 4, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "bcb8d54dd" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"0b6ae80f-999b-40e9-b116-ea925f0ed07b\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:observedGeneration": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T10:34:04.000Z" + } + ], + "name": "dice-roller-canary-bcb8d54dd", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller-canary", + "uid": "0b6ae80f-999b-40e9-b116-ea925f0ed07b" + } + ], + "resourceVersion": "598025", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-canary-bcb8d54dd", + "uid": "51942585-d599-42aa-bf23-9cf1acad4006" + }, + "spec": { + "replicas": 0, + "selector": { + "matchLabels": { + "app": "dice-roller-canary", + "pod-template-hash": "bcb8d54dd" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "bcb8d54dd" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "observedGeneration": 4, + "replicas": 0 + } + }, + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/desired-replicas": "2", + "deployment.kubernetes.io/max-replicas": "3", + "deployment.kubernetes.io/revision": "1" + }, + "creationTimestamp": "2020-09-25T09:02:53.000Z", + "generation": 3, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "c866fbf67" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:deployment.kubernetes.io/desired-replicas": {}, + "f:deployment.kubernetes.io/max-replicas": {}, + "f:deployment.kubernetes.io/revision": {} + }, + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + }, + "f:ownerReferences": { + ".": {}, + "k:{\"uid\":\"0b6ae80f-999b-40e9-b116-ea925f0ed07b\"}": { + ".": {}, + "f:apiVersion": {}, + "f:blockOwnerDeletion": {}, + "f:controller": {}, + "f:kind": {}, + "f:name": {}, + "f:uid": {} + } + } + }, + "f:spec": { + "f:replicas": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {}, + "f:pod-template-hash": {} + } + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {}, + "f:pod-template-hash": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + }, + "f:status": { + "f:observedGeneration": {}, + "f:replicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:25:20.000Z" + } + ], + "name": "dice-roller-canary-c866fbf67", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Deployment", + "name": "dice-roller-canary", + "uid": "0b6ae80f-999b-40e9-b116-ea925f0ed07b" + } + ], + "resourceVersion": "588501", + "selfLink": "/apis/apps/v1/namespaces/default/replicasets/dice-roller-canary-c866fbf67", + "uid": "4d2dfe13-978f-4504-9036-ca585acdea6c" + }, + "spec": { + "replicas": 0, + "selector": { + "matchLabels": { + "app": "dice-roller-canary", + "pod-template-hash": "c866fbf67" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller", + "pod-template-hash": "c866fbf67" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "observedGeneration": 3, + "replicas": 0 + } + } + ], + "statefulsets": [ + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/revision": "2", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"StatefulSet\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"replicas\":10,\"selector\":{\"matchLabels\":{\"app\":\"dice-roller\"}},\"template\":{\"metadata\":{\"labels\":{\"app\":\"dice-roller\",\"backstage.io/kubernetes-id\":\"dice-roller\"}},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]}]}}}}\n" + }, + "creationTimestamp": "2020-09-23T12:00:55.000Z", + "generation": 3, + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:progressDeadlineSeconds": {}, + "f:replicas": {}, + "f:revisionHistoryLimit": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {} + } + }, + "f:strategy": { + "f:rollingUpdate": { + ".": {}, + "f:maxSurge": {}, + "f:maxUnavailable": {} + }, + "f:type": {} + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + } + }, + "manager": "kubectl", + "operation": "Update", + "time": "2020-09-25T09:58:50.000Z" + }, + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:deployment.kubernetes.io/revision": {} + } + }, + "f:status": { + "f:availableReplicas": {}, + "f:conditions": { + ".": {}, + "k:{\"type\":\"Available\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Progressing\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:observedGeneration": {}, + "f:readyReplicas": {}, + "f:replicas": {}, + "f:updatedReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T09:58:55.000Z" + } + ], + "name": "dice-roller", + "namespace": "default", + "resourceVersion": "593230", + "selfLink": "/apis/apps/v1/namespaces/default/statefulsets/dice-roller", + "uid": "5126c354-4310-4e23-a9e4-c9b87cb69792" + }, + "spec": { + "replicas": 10, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "dice-roller" + } + }, + "updateStrategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "podManagementPolicy": "Parallel", + "serviceName": "dice-roller", + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller", + "backstage.io/kubernetes-id": "dice-roller" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "availableReplicas": 10, + "conditions": [ + { + "lastTransitionTime": "2020-09-23T12:00:55.000Z", + "lastUpdateTime": "2020-09-24T11:39:28.000Z", + "message": "ReplicaSet \"dice-roller-6c8646bfd\" has successfully progressed.", + "reason": "NewReplicaSetAvailable", + "status": "True", + "type": "Progressing" + }, + { + "lastTransitionTime": "2020-09-25T09:58:55.000Z", + "lastUpdateTime": "2020-09-25T09:58:55.000Z", + "message": "Deployment has minimum availability.", + "reason": "MinimumReplicasAvailable", + "status": "True", + "type": "Available" + } + ], + "observedGeneration": 3, + "readyReplicas": 10, + "replicas": 10, + "updatedReplicas": 10 + } + }, + { + "metadata": { + "annotations": { + "deployment.kubernetes.io/revision": "3", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"StatefulSet\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller-canary\",\"namespace\":\"default\"},\"spec\":{\"replicas\":2,\"selector\":{\"matchLabels\":{\"app\":\"dice-roller-canary\"}},\"template\":{\"metadata\":{\"labels\":{\"app\":\"dice-roller-canary\",\"backstage.io/kubernetes-id\":\"dice-roller\"}},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]},{\"image\":\"nginx:1.14.2\",\"name\":\"side-car\",\"ports\":[{\"containerPort\":81}]},{\"image\":\"nginx:1.14.2\",\"name\":\"other-side-car\",\"ports\":[{\"containerPort\":82}]}]}}}}\n" + }, + "creationTimestamp": "2020-09-25T09:02:53.000Z", + "generation": 3, + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:progressDeadlineSeconds": {}, + "f:replicas": {}, + "f:revisionHistoryLimit": {}, + "f:selector": { + "f:matchLabels": { + ".": {}, + "f:app": {} + } + }, + "f:strategy": { + "f:rollingUpdate": { + ".": {}, + "f:maxSurge": {}, + "f:maxUnavailable": {} + }, + "f:type": {} + }, + "f:template": { + "f:metadata": { + "f:labels": { + ".": {}, + "f:app": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:containers": { + "k:{\"name\":\"nginx\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"other-side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":82,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + }, + "k:{\"name\":\"side-car\"}": { + ".": {}, + "f:image": {}, + "f:imagePullPolicy": {}, + "f:name": {}, + "f:ports": { + ".": {}, + "k:{\"containerPort\":81,\"protocol\":\"TCP\"}": { + ".": {}, + "f:containerPort": {}, + "f:protocol": {} + } + }, + "f:resources": {}, + "f:terminationMessagePath": {}, + "f:terminationMessagePolicy": {} + } + }, + "f:dnsPolicy": {}, + "f:restartPolicy": {}, + "f:schedulerName": {}, + "f:securityContext": {}, + "f:terminationGracePeriodSeconds": {} + } + } + } + }, + "manager": "kubectl", + "operation": "Update", + "time": "2020-09-25T10:34:01.000Z" + }, + { + "apiVersion": "apps/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:deployment.kubernetes.io/revision": {} + } + }, + "f:status": { + "f:conditions": { + ".": {}, + "k:{\"type\":\"Available\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + }, + "k:{\"type\":\"Progressing\"}": { + ".": {}, + "f:lastTransitionTime": {}, + "f:lastUpdateTime": {}, + "f:message": {}, + "f:reason": {}, + "f:status": {}, + "f:type": {} + } + }, + "f:observedGeneration": {}, + "f:replicas": {}, + "f:unavailableReplicas": {}, + "f:updatedReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2020-09-25T14:19:04.000Z" + } + ], + "name": "dice-roller-canary", + "namespace": "default", + "resourceVersion": "620480", + "selfLink": "/apis/apps/v1/namespaces/default/statefulsets/dice-roller-canary", + "uid": "9208395b-a9a7-4e46-b881-6a189f7fbdb0" + }, + "spec": { + "replicas": 2, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "dice-roller-canary" + } + }, + "updateStrategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "podManagementPolicy": "Parallel", + "serviceName": "dice-roller", + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app": "dice-roller-canary", + "backstage.io/kubernetes-id": "dice-roller" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "side-car", + "ports": [ + { + "containerPort": 81, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + }, + { + "image": "nginx:1.14.2", + "imagePullPolicy": "IfNotPresent", + "name": "other-side-car", + "ports": [ + { + "containerPort": 82, + "protocol": "TCP" + } + ], + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + }, + "status": { + "conditions": [ + { + "lastTransitionTime": "2020-09-25T09:02:53.000Z", + "lastUpdateTime": "2020-09-25T10:34:04.000Z", + "message": "ReplicaSet \"dice-roller-canary-7d64cd756c\" has successfully progressed.", + "reason": "NewReplicaSetAvailable", + "status": "True", + "type": "Progressing" + }, + { + "lastTransitionTime": "2020-09-25T13:48:06.000Z", + "lastUpdateTime": "2020-09-25T13:48:06.000Z", + "message": "Deployment does not have minimum availability.", + "reason": "MinimumReplicasUnavailable", + "status": "False", + "type": "Available" + } + ], + "observedGeneration": 3, + "replicas": 2, + "unavailableReplicas": 2, + "updatedReplicas": 2 + } + } + ], + "horizontalPodAutoscalers": [ + { + "apiVersion": "autoscaling/v1", + "kind": "HorizontalPodAutoscaler", + "metadata": { + "annotations": { + "autoscaling.alpha.kubernetes.io/conditions": "[{\"type\":\"AbleToScale\",\"status\":\"True\",\"lastTransitionTime\":\"2021-01-05T10:26:04Z\",\"reason\":\"SucceededGetScale\",\"message\":\"the HPA controller was able to get the target's current scale\"},{\"type\":\"ScalingActive\",\"status\":\"False\",\"lastTransitionTime\":\"2021-01-05T10:26:04Z\",\"reason\":\"FailedGetResourceMetric\",\"message\":\"the HPA was unable to compute the replica count: unable to get metrics for resource cpu: no metrics returned from resource metrics API\"}]", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"autoscaling/v1\",\"kind\":\"HorizontalPodAutoscaler\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"maxReplicas\":15,\"minReplicas\":10,\"scaleTargetRef\":{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"name\":\"dice-roller\"},\"targetCPUUtilizationPercentage\":50}}\n" + }, + "creationTimestamp": "2021-01-05T10:25:48Z", + "labels": { + "backstage.io/kubernetes-id": "dice-roller" + }, + "managedFields": [ + { + "apiVersion": "autoscaling/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + }, + "f:labels": { + ".": {}, + "f:backstage.io/kubernetes-id": {} + } + }, + "f:spec": { + "f:maxReplicas": {}, + "f:minReplicas": {}, + "f:scaleTargetRef": { + "f:apiVersion": {}, + "f:kind": {}, + "f:name": {} + }, + "f:targetCPUUtilizationPercentage": {} + } + }, + "manager": "kubectl-client-side-apply", + "operation": "Update", + "time": "2021-01-05T10:25:48Z" + }, + { + "apiVersion": "autoscaling/v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:metadata": { + "f:annotations": { + "f:autoscaling.alpha.kubernetes.io/conditions": {} + } + }, + "f:status": { + "f:currentReplicas": {} + } + }, + "manager": "kube-controller-manager", + "operation": "Update", + "time": "2021-01-05T10:26:04Z" + } + ], + "name": "dice-roller", + "namespace": "default", + "resourceVersion": "598", + "selfLink": "/apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/dice-roller", + "uid": "dd7c5329-567c-43c2-b159-756808d90a8e" + }, + "spec": { + "maxReplicas": 15, + "minReplicas": 10, + "scaleTargetRef": { + "apiVersion": "apps/v1", + "kind": "Deployment", + "name": "dice-roller" + }, + "targetCPUUtilizationPercentage": 50 + }, + "status": { + "currentReplicas": 10, + "desiredReplicas": 0, + "currentCPUUtilizationPercentage": 30 + } + } + ] +} diff --git a/plugins/kubernetes/src/api/KubernetesBackendClient.test.ts b/plugins/kubernetes-react/src/api/KubernetesBackendClient.test.ts similarity index 100% rename from plugins/kubernetes/src/api/KubernetesBackendClient.test.ts rename to plugins/kubernetes-react/src/api/KubernetesBackendClient.test.ts diff --git a/plugins/kubernetes/src/api/KubernetesBackendClient.ts b/plugins/kubernetes-react/src/api/KubernetesBackendClient.ts similarity index 99% rename from plugins/kubernetes/src/api/KubernetesBackendClient.ts rename to plugins/kubernetes-react/src/api/KubernetesBackendClient.ts index 681daa0ac0..b483c267d8 100644 --- a/plugins/kubernetes/src/api/KubernetesBackendClient.ts +++ b/plugins/kubernetes-react/src/api/KubernetesBackendClient.ts @@ -26,6 +26,7 @@ import { stringifyEntityRef } from '@backstage/catalog-model'; import { KubernetesAuthProvidersApi } from '../kubernetes-auth-provider'; import { NotFoundError } from '@backstage/errors'; +/** @public */ export class KubernetesBackendClient implements KubernetesApi { private readonly discoveryApi: DiscoveryApi; private readonly identityApi: IdentityApi; diff --git a/plugins/kubernetes/src/api/KubernetesProxyClient.test.ts b/plugins/kubernetes-react/src/api/KubernetesProxyClient.test.ts similarity index 100% rename from plugins/kubernetes/src/api/KubernetesProxyClient.test.ts rename to plugins/kubernetes-react/src/api/KubernetesProxyClient.test.ts diff --git a/plugins/kubernetes/src/api/KubernetesProxyClient.ts b/plugins/kubernetes-react/src/api/KubernetesProxyClient.ts similarity index 100% rename from plugins/kubernetes/src/api/KubernetesProxyClient.ts rename to plugins/kubernetes-react/src/api/KubernetesProxyClient.ts diff --git a/plugins/kubernetes/src/api/index.ts b/plugins/kubernetes-react/src/api/index.ts similarity index 100% rename from plugins/kubernetes/src/api/index.ts rename to plugins/kubernetes-react/src/api/index.ts diff --git a/plugins/kubernetes/src/api/types.ts b/plugins/kubernetes-react/src/api/types.ts similarity index 97% rename from plugins/kubernetes/src/api/types.ts rename to plugins/kubernetes-react/src/api/types.ts index 6065e47169..c0f97ffd41 100644 --- a/plugins/kubernetes/src/api/types.ts +++ b/plugins/kubernetes-react/src/api/types.ts @@ -23,14 +23,17 @@ import { import { createApiRef } from '@backstage/core-plugin-api'; import { Event } from 'kubernetes-models/v1'; +/** @public */ export const kubernetesApiRef = createApiRef({ id: 'plugin.kubernetes.service', }); +/** @public */ export const kubernetesProxyApiRef = createApiRef({ id: 'plugin.kubernetes.proxy-service', }); +/** @public */ export interface KubernetesApi { getObjectsByEntity( requestBody: KubernetesRequestBody, @@ -55,6 +58,7 @@ export interface KubernetesApi { }): Promise; } +/** @public */ export interface KubernetesProxyApi { getPodLogs(request: { podName: string; diff --git a/plugins/kubernetes/src/components/Cluster/Cluster.test.tsx b/plugins/kubernetes-react/src/components/Cluster/Cluster.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/Cluster/Cluster.test.tsx rename to plugins/kubernetes-react/src/components/Cluster/Cluster.test.tsx diff --git a/plugins/kubernetes/src/components/Cluster/Cluster.tsx b/plugins/kubernetes-react/src/components/Cluster/Cluster.tsx similarity index 96% rename from plugins/kubernetes/src/components/Cluster/Cluster.tsx rename to plugins/kubernetes-react/src/components/Cluster/Cluster.tsx index bea7a46d37..42f1aca3a0 100644 --- a/plugins/kubernetes/src/components/Cluster/Cluster.tsx +++ b/plugins/kubernetes-react/src/components/Cluster/Cluster.tsx @@ -25,11 +25,11 @@ import { import { ClientPodStatus, ClusterObjects, + groupResponses, } from '@backstage/plugin-kubernetes-common'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { DeploymentsAccordions } from '../DeploymentsAccordions'; import { StatefulSetsAccordions } from '../StatefulSetsAccordions'; -import { groupResponses } from '../../utils/response'; import { IngressesAccordions } from '../IngressesAccordions'; import { ServicesAccordions } from '../ServicesAccordions'; import { CronJobsAccordions } from '../CronJobsAccordions'; @@ -103,12 +103,22 @@ const ClusterSummary = ({ ); }; -type ClusterProps = { +/** + * Props for Cluster + * + * @public + */ +export type ClusterProps = { clusterObjects: ClusterObjects; podsWithErrors: Set; children?: React.ReactNode; }; +/** + * Component for rendering Kubernetes resources in a cluster + * + * @public + */ export const Cluster = ({ clusterObjects, podsWithErrors }: ClusterProps) => { const groupedResponses = groupResponses(clusterObjects.resources); diff --git a/plugins/kubernetes/src/components/ErrorPanel/index.ts b/plugins/kubernetes-react/src/components/Cluster/index.ts similarity index 93% rename from plugins/kubernetes/src/components/ErrorPanel/index.ts rename to plugins/kubernetes-react/src/components/Cluster/index.ts index 2d3778e2c2..eac1e358b6 100644 --- a/plugins/kubernetes/src/components/ErrorPanel/index.ts +++ b/plugins/kubernetes-react/src/components/Cluster/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { ErrorPanel } from './ErrorPanel'; +export * from './Cluster'; diff --git a/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsAccordions.test.tsx b/plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsAccordions.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/CronJobsAccordions/CronJobsAccordions.test.tsx rename to plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsAccordions.test.tsx diff --git a/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsAccordions.tsx b/plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsAccordions.tsx similarity index 97% rename from plugins/kubernetes/src/components/CronJobsAccordions/CronJobsAccordions.tsx rename to plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsAccordions.tsx index c5babe67fc..e724c14fdf 100644 --- a/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsAccordions.tsx +++ b/plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsAccordions.tsx @@ -30,7 +30,12 @@ import { GroupedResponsesContext } from '../../hooks'; import { StatusError, StatusOK } from '@backstage/core-components'; import { humanizeCron } from '../../utils/crons'; -type CronJobsAccordionsProps = { +/** + * + * + * @public + */ +export type CronJobsAccordionsProps = { children?: React.ReactNode; }; @@ -101,6 +106,11 @@ const CronJobAccordion = ({ cronJob, ownedJobs }: CronJobAccordionProps) => { ); }; +/** + * + * + * @public + */ export const CronJobsAccordions = ({}: CronJobsAccordionsProps) => { const groupedResponses = useContext(GroupedResponsesContext); diff --git a/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsDrawer.test.tsx b/plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsDrawer.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/CronJobsAccordions/CronJobsDrawer.test.tsx rename to plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsDrawer.test.tsx diff --git a/plugins/kubernetes/src/components/CronJobsAccordions/CronJobsDrawer.tsx b/plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsDrawer.tsx similarity index 100% rename from plugins/kubernetes/src/components/CronJobsAccordions/CronJobsDrawer.tsx rename to plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsDrawer.tsx diff --git a/plugins/kubernetes/src/components/JobsAccordions/index.ts b/plugins/kubernetes-react/src/components/CronJobsAccordions/index.ts similarity index 92% rename from plugins/kubernetes/src/components/JobsAccordions/index.ts rename to plugins/kubernetes-react/src/components/CronJobsAccordions/index.ts index 392309de79..ecc7172523 100644 --- a/plugins/kubernetes/src/components/JobsAccordions/index.ts +++ b/plugins/kubernetes-react/src/components/CronJobsAccordions/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { JobsAccordions } from './JobsAccordions'; +export * from './CronJobsAccordions'; diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/Rollout.test.tsx b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/Rollout.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/Rollout.test.tsx rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/Rollout.test.tsx diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/Rollout.tsx b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/Rollout.tsx similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/Rollout.tsx rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/Rollout.tsx diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/RolloutDrawer.tsx b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/RolloutDrawer.tsx similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/RolloutDrawer.tsx rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/RolloutDrawer.tsx diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/StepsProgress.test.tsx b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/StepsProgress.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/StepsProgress.test.tsx rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/StepsProgress.test.tsx diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/StepsProgress.tsx b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/StepsProgress.tsx similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/StepsProgress.tsx rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/StepsProgress.tsx diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/aborted-rollout.json b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/aborted-rollout.json similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/aborted-rollout.json rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/aborted-rollout.json diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/analysis-steps.ts b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/analysis-steps.ts similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/analysis-steps.ts rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/analysis-steps.ts diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/grouped-resources.json b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/grouped-resources.json similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/grouped-resources.json rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/grouped-resources.json diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/pause-steps.ts b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/pause-steps.ts similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/pause-steps.ts rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/pause-steps.ts diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/paused-rollout.json b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/paused-rollout.json similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/paused-rollout.json rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/paused-rollout.json diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/rollout.json b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/rollout.json similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/rollout.json rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/rollout.json diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/setweight-steps.ts b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/setweight-steps.ts similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/__fixtures__/setweight-steps.ts rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/__fixtures__/setweight-steps.ts diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/index.ts b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/index.ts similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/index.ts rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/index.ts diff --git a/plugins/kubernetes/src/components/CustomResources/ArgoRollouts/types.ts b/plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/types.ts similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/ArgoRollouts/types.ts rename to plugins/kubernetes-react/src/components/CustomResources/ArgoRollouts/types.ts diff --git a/plugins/kubernetes/src/components/CustomResources/CustomResources.tsx b/plugins/kubernetes-react/src/components/CustomResources/CustomResources.tsx similarity index 95% rename from plugins/kubernetes/src/components/CustomResources/CustomResources.tsx rename to plugins/kubernetes-react/src/components/CustomResources/CustomResources.tsx index 436e97fce8..f204f5fdd1 100644 --- a/plugins/kubernetes/src/components/CustomResources/CustomResources.tsx +++ b/plugins/kubernetes-react/src/components/CustomResources/CustomResources.tsx @@ -20,7 +20,12 @@ import { RolloutAccordions } from './ArgoRollouts'; import { DefaultCustomResourceAccordions } from './DefaultCustomResource'; import { GroupedResponsesContext } from '../../hooks'; -interface CustomResourcesProps { +/** + * + * + * @public + */ +export interface CustomResourcesProps { children?: React.ReactNode; } @@ -30,6 +35,11 @@ const kindToResource = (customResources: any[]): Dictionary => { }); }; +/** + * + * + * @public + */ export const CustomResources = ({}: CustomResourcesProps) => { const groupedResponses = useContext(GroupedResponsesContext); const kindToResourceMap = kindToResource(groupedResponses.customResources); diff --git a/plugins/kubernetes/src/components/CustomResources/DefaultCustomResource.test.tsx b/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/DefaultCustomResource.test.tsx rename to plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.test.tsx diff --git a/plugins/kubernetes/src/components/CustomResources/DefaultCustomResource.tsx b/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/DefaultCustomResource.tsx rename to plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx diff --git a/plugins/kubernetes/src/components/CustomResources/DefaultCustomResourceDrawer.tsx b/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResourceDrawer.tsx similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/DefaultCustomResourceDrawer.tsx rename to plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResourceDrawer.tsx diff --git a/plugins/kubernetes/src/components/CustomResources/__fixtures__/analysis-run.json b/plugins/kubernetes-react/src/components/CustomResources/__fixtures__/analysis-run.json similarity index 100% rename from plugins/kubernetes/src/components/CustomResources/__fixtures__/analysis-run.json rename to plugins/kubernetes-react/src/components/CustomResources/__fixtures__/analysis-run.json diff --git a/plugins/kubernetes/src/components/ErrorReporting/index.ts b/plugins/kubernetes-react/src/components/CustomResources/index.ts similarity index 92% rename from plugins/kubernetes/src/components/ErrorReporting/index.ts rename to plugins/kubernetes-react/src/components/CustomResources/index.ts index 451d08ec76..0c5e0ce7a0 100644 --- a/plugins/kubernetes/src/components/ErrorReporting/index.ts +++ b/plugins/kubernetes-react/src/components/CustomResources/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { ErrorReporting } from './ErrorReporting'; +export * from './CustomResources'; diff --git a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx rename to plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx diff --git a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.tsx b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.tsx similarity index 100% rename from plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.tsx rename to plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.tsx diff --git a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.test.tsx b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentsAccordions.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.test.tsx rename to plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentsAccordions.test.tsx diff --git a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx similarity index 100% rename from plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx rename to plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentsAccordions.tsx diff --git a/plugins/kubernetes/src/components/DeploymentsAccordions/index.ts b/plugins/kubernetes-react/src/components/DeploymentsAccordions/index.ts similarity index 100% rename from plugins/kubernetes/src/components/DeploymentsAccordions/index.ts rename to plugins/kubernetes-react/src/components/DeploymentsAccordions/index.ts diff --git a/plugins/kubernetes/src/components/ErrorPanel/ErrorPanel.test.tsx b/plugins/kubernetes-react/src/components/ErrorPanel/ErrorPanel.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/ErrorPanel/ErrorPanel.test.tsx rename to plugins/kubernetes-react/src/components/ErrorPanel/ErrorPanel.test.tsx diff --git a/plugins/kubernetes/src/components/ErrorPanel/ErrorPanel.tsx b/plugins/kubernetes-react/src/components/ErrorPanel/ErrorPanel.tsx similarity index 96% rename from plugins/kubernetes/src/components/ErrorPanel/ErrorPanel.tsx rename to plugins/kubernetes-react/src/components/ErrorPanel/ErrorPanel.tsx index d2cb88b9ca..b02f4c18dc 100644 --- a/plugins/kubernetes/src/components/ErrorPanel/ErrorPanel.tsx +++ b/plugins/kubernetes-react/src/components/ErrorPanel/ErrorPanel.tsx @@ -41,13 +41,23 @@ const clustersWithErrorsToErrorMessage = ( }); }; -type ErrorPanelProps = { +/** + * + * + * @public + */ +export type ErrorPanelProps = { entityName: string; errorMessage?: string; clustersWithErrors?: ClusterObjects[]; children?: React.ReactNode; }; +/** + * + * + * @public + */ export const ErrorPanel = ({ entityName, errorMessage, diff --git a/plugins/kubernetes/src/components/CustomResources/index.ts b/plugins/kubernetes-react/src/components/ErrorPanel/index.ts similarity index 91% rename from plugins/kubernetes/src/components/CustomResources/index.ts rename to plugins/kubernetes-react/src/components/ErrorPanel/index.ts index 9297fd8ac1..94d6e5b028 100644 --- a/plugins/kubernetes/src/components/CustomResources/index.ts +++ b/plugins/kubernetes-react/src/components/ErrorPanel/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { CustomResources } from './CustomResources'; +export * from './ErrorPanel'; diff --git a/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx b/plugins/kubernetes-react/src/components/ErrorReporting/ErrorReporting.tsx similarity index 92% rename from plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx rename to plugins/kubernetes-react/src/components/ErrorReporting/ErrorReporting.tsx index 367e791067..64345662ed 100644 --- a/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx +++ b/plugins/kubernetes-react/src/components/ErrorReporting/ErrorReporting.tsx @@ -14,10 +14,18 @@ * limitations under the License. */ import * as React from 'react'; -import { DetectedError, DetectedErrorsByCluster } from '../../error-detection'; +import { + DetectedError, + DetectedErrorsByCluster, +} from '@backstage/plugin-kubernetes-common'; import { Table, TableColumn } from '@backstage/core-components'; -type ErrorReportingProps = { +/** + * + * + * @public + */ +export type ErrorReportingProps = { detectedErrors: DetectedErrorsByCluster; }; @@ -65,6 +73,11 @@ const sortBySeverity = (a: Row, b: Row) => { return 0; }; +/** + * + * + * @public + */ export const ErrorReporting = ({ detectedErrors }: ErrorReportingProps) => { const errors = Array.from(detectedErrors.entries()) .flatMap(([clusterName, resourceErrors]) => { diff --git a/plugins/kubernetes-react/src/components/ErrorReporting/index.ts b/plugins/kubernetes-react/src/components/ErrorReporting/index.ts new file mode 100644 index 0000000000..3382849229 --- /dev/null +++ b/plugins/kubernetes-react/src/components/ErrorReporting/index.ts @@ -0,0 +1,16 @@ +/* + * 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 './ErrorReporting'; diff --git a/plugins/kubernetes/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.test.tsx b/plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.test.tsx rename to plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.test.tsx diff --git a/plugins/kubernetes/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.tsx b/plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.tsx similarity index 100% rename from plugins/kubernetes/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.tsx rename to plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.tsx diff --git a/plugins/kubernetes/src/components/HorizontalPodAutoscalers/__fixtures__/horizontalpodautoscalers.json b/plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/__fixtures__/horizontalpodautoscalers.json similarity index 100% rename from plugins/kubernetes/src/components/HorizontalPodAutoscalers/__fixtures__/horizontalpodautoscalers.json rename to plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/__fixtures__/horizontalpodautoscalers.json diff --git a/plugins/kubernetes/src/components/HorizontalPodAutoscalers/index.ts b/plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/index.ts similarity index 100% rename from plugins/kubernetes/src/components/HorizontalPodAutoscalers/index.ts rename to plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/index.ts diff --git a/plugins/kubernetes/src/components/IngressesAccordions/IngressDrawer.test.tsx b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/IngressesAccordions/IngressDrawer.test.tsx rename to plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx diff --git a/plugins/kubernetes/src/components/IngressesAccordions/IngressDrawer.tsx b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.tsx similarity index 100% rename from plugins/kubernetes/src/components/IngressesAccordions/IngressDrawer.tsx rename to plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.tsx diff --git a/plugins/kubernetes/src/components/IngressesAccordions/IngressesAccordions.test.tsx b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/IngressesAccordions/IngressesAccordions.test.tsx rename to plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.test.tsx diff --git a/plugins/kubernetes/src/components/IngressesAccordions/IngressesAccordions.tsx b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx similarity index 96% rename from plugins/kubernetes/src/components/IngressesAccordions/IngressesAccordions.tsx rename to plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx index 6e12c033ba..28aa5d42e4 100644 --- a/plugins/kubernetes/src/components/IngressesAccordions/IngressesAccordions.tsx +++ b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx @@ -27,7 +27,12 @@ import { IngressDrawer } from './IngressDrawer'; import { GroupedResponsesContext } from '../../hooks'; import { StructuredMetadataTable } from '@backstage/core-components'; -type IngressesAccordionsProps = {}; +/** + * + * + * @public + */ +export type IngressesAccordionsProps = {}; type IngressAccordionProps = { ingress: V1Ingress; @@ -78,6 +83,12 @@ const IngressAccordion = ({ ingress }: IngressAccordionProps) => { ); }; + +/** + * + * + * @public + */ export const IngressesAccordions = ({}: IngressesAccordionsProps) => { const groupedResponses = useContext(GroupedResponsesContext); return ( diff --git a/plugins/kubernetes/src/components/IngressesAccordions/__fixtures__/2-ingresses.json b/plugins/kubernetes-react/src/components/IngressesAccordions/__fixtures__/2-ingresses.json similarity index 100% rename from plugins/kubernetes/src/components/IngressesAccordions/__fixtures__/2-ingresses.json rename to plugins/kubernetes-react/src/components/IngressesAccordions/__fixtures__/2-ingresses.json diff --git a/plugins/kubernetes-react/src/components/IngressesAccordions/index.ts b/plugins/kubernetes-react/src/components/IngressesAccordions/index.ts new file mode 100644 index 0000000000..ece35ab17a --- /dev/null +++ b/plugins/kubernetes-react/src/components/IngressesAccordions/index.ts @@ -0,0 +1,16 @@ +/* + * 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 './IngressesAccordions'; diff --git a/plugins/kubernetes/src/components/JobsAccordions/JobsAccordions.test.tsx b/plugins/kubernetes-react/src/components/JobsAccordions/JobsAccordions.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/JobsAccordions/JobsAccordions.test.tsx rename to plugins/kubernetes-react/src/components/JobsAccordions/JobsAccordions.test.tsx diff --git a/plugins/kubernetes/src/components/JobsAccordions/JobsAccordions.tsx b/plugins/kubernetes-react/src/components/JobsAccordions/JobsAccordions.tsx similarity index 97% rename from plugins/kubernetes/src/components/JobsAccordions/JobsAccordions.tsx rename to plugins/kubernetes-react/src/components/JobsAccordions/JobsAccordions.tsx index e805e3664b..460d0b80c0 100644 --- a/plugins/kubernetes/src/components/JobsAccordions/JobsAccordions.tsx +++ b/plugins/kubernetes-react/src/components/JobsAccordions/JobsAccordions.tsx @@ -32,7 +32,12 @@ import { StatusPending, } from '@backstage/core-components'; -type JobsAccordionsProps = { +/** + * + * + * @public + */ +export type JobsAccordionsProps = { jobs: V1Job[]; children?: React.ReactNode; }; @@ -98,6 +103,11 @@ const JobAccordion = ({ job, ownedPods }: JobAccordionProps) => { ); }; +/** + * + * + * @public + */ export const JobsAccordions = ({ jobs }: JobsAccordionsProps) => { const groupedResponses = useContext(GroupedResponsesContext); diff --git a/plugins/kubernetes/src/components/JobsAccordions/JobsDrawer.test.tsx b/plugins/kubernetes-react/src/components/JobsAccordions/JobsDrawer.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/JobsAccordions/JobsDrawer.test.tsx rename to plugins/kubernetes-react/src/components/JobsAccordions/JobsDrawer.test.tsx diff --git a/plugins/kubernetes/src/components/JobsAccordions/JobsDrawer.tsx b/plugins/kubernetes-react/src/components/JobsAccordions/JobsDrawer.tsx similarity index 100% rename from plugins/kubernetes/src/components/JobsAccordions/JobsDrawer.tsx rename to plugins/kubernetes-react/src/components/JobsAccordions/JobsDrawer.tsx diff --git a/plugins/kubernetes/src/components/CronJobsAccordions/index.ts b/plugins/kubernetes-react/src/components/JobsAccordions/index.ts similarity index 91% rename from plugins/kubernetes/src/components/CronJobsAccordions/index.ts rename to plugins/kubernetes-react/src/components/JobsAccordions/index.ts index e72e3f7e6d..c69c493dc8 100644 --- a/plugins/kubernetes/src/components/CronJobsAccordions/index.ts +++ b/plugins/kubernetes-react/src/components/JobsAccordions/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { CronJobsAccordions } from './CronJobsAccordions'; +export * from './JobsAccordions'; diff --git a/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesDrawer.tsx similarity index 93% rename from plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx rename to plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesDrawer.tsx index 18ef5d9505..598dac4fe8 100644 --- a/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx +++ b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesDrawer.tsx @@ -48,7 +48,12 @@ const useDrawerContentStyles = makeStyles((_theme: Theme) => }), ); -interface KubernetesObject { +/** + * The type of object that can be represented by the Drawer + * + * @public + */ +export interface KubernetesObject { kind: string; metadata?: IObjectMeta; } @@ -60,7 +65,7 @@ interface KubernetesDrawerContentProps { children?: React.ReactNode; } -export const KubernetesDrawerContent = ({ +const KubernetesDrawerContent = ({ children, header, kubernetesObject, @@ -115,7 +120,12 @@ export const KubernetesDrawerContent = ({ ); }; -interface KubernetesDrawerProps { +/** + * Props of KubernetesDrawer + * + * @public + */ +export interface KubernetesDrawerProps { open?: boolean; kubernetesObject: KubernetesObject; label: React.ReactNode; @@ -142,6 +152,11 @@ const DrawerButton = withStyles({ }, })(Button); +/** + * Button/Drawer component for Kubernetes Objects + * + * @public + */ export const KubernetesDrawer = ({ open, label, diff --git a/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx similarity index 95% rename from plugins/kubernetes/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx rename to plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx index 8f28549f83..65001c658e 100644 --- a/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx +++ b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx @@ -86,13 +86,26 @@ const PodDrawerButton = withStyles({ }, })(Button); -type ErrorPanelProps = { +/** + * + * + * @public + */ +export type LinkErrorPanelProps = { cluster: ClusterAttributes; errorMessage?: string; children?: React.ReactNode; }; -export const LinkErrorPanel = ({ cluster, errorMessage }: ErrorPanelProps) => ( +/** + * + * + * @public + */ +export const LinkErrorPanel = ({ + cluster, + errorMessage, +}: LinkErrorPanelProps) => ( ( ); -interface KubernetesDrawerable { +/** + * + * + * @public + */ +export interface KubernetesDrawerable { metadata?: V1ObjectMeta; } @@ -234,7 +252,12 @@ const KubernetesStructuredMetadataTableDrawerContent = < ); }; -interface KubernetesStructuredMetadataTableDrawerProps< + +/** + * + * @public + */ +export interface KubernetesStructuredMetadataTableDrawerProps< T extends KubernetesDrawerable, > { object: T; @@ -245,6 +268,10 @@ interface KubernetesStructuredMetadataTableDrawerProps< children?: React.ReactNode; } +/** + * + * @public + */ export const KubernetesStructuredMetadataTableDrawer = < T extends KubernetesDrawerable, >({ diff --git a/plugins/kubernetes/src/components/KubernetesDrawer/ManifestYaml.tsx b/plugins/kubernetes-react/src/components/KubernetesDrawer/ManifestYaml.tsx similarity index 94% rename from plugins/kubernetes/src/components/KubernetesDrawer/ManifestYaml.tsx rename to plugins/kubernetes-react/src/components/KubernetesDrawer/ManifestYaml.tsx index 8f0c38afde..246477b53b 100644 --- a/plugins/kubernetes/src/components/KubernetesDrawer/ManifestYaml.tsx +++ b/plugins/kubernetes-react/src/components/KubernetesDrawer/ManifestYaml.tsx @@ -18,10 +18,20 @@ import { FormControlLabel, Switch } from '@material-ui/core'; import jsyaml from 'js-yaml'; import React, { useState } from 'react'; +/** + * Props of ManifestYaml + * + * @public + */ export interface ManifestYamlProps { object: object; } +/** + * Renders a Kubernetes object as a YAML code snippet + * + * @public + */ export const ManifestYaml = ({ object }: ManifestYamlProps) => { // Toggle whether the Kubernetes resource managed fields should be shown in // the YAML display. This toggle is only available when the YAML is being diff --git a/plugins/kubernetes/src/components/KubernetesDrawer/index.ts b/plugins/kubernetes-react/src/components/KubernetesDrawer/index.ts similarity index 95% rename from plugins/kubernetes/src/components/KubernetesDrawer/index.ts rename to plugins/kubernetes-react/src/components/KubernetesDrawer/index.ts index a0108cbda6..cc5337544b 100644 --- a/plugins/kubernetes/src/components/KubernetesDrawer/index.ts +++ b/plugins/kubernetes-react/src/components/KubernetesDrawer/index.ts @@ -16,3 +16,4 @@ export * from './KubernetesStructuredMetadataTableDrawer'; export * from './KubernetesDrawer'; +export * from './ManifestYaml'; diff --git a/plugins/kubernetes/src/components/PodExecTerminal/PodExecTerminal.test.tsx b/plugins/kubernetes-react/src/components/PodExecTerminal/PodExecTerminal.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/PodExecTerminal/PodExecTerminal.test.tsx rename to plugins/kubernetes-react/src/components/PodExecTerminal/PodExecTerminal.test.tsx diff --git a/plugins/kubernetes/src/components/PodExecTerminal/PodExecTerminal.tsx b/plugins/kubernetes-react/src/components/PodExecTerminal/PodExecTerminal.tsx similarity index 99% rename from plugins/kubernetes/src/components/PodExecTerminal/PodExecTerminal.tsx rename to plugins/kubernetes-react/src/components/PodExecTerminal/PodExecTerminal.tsx index a741f4e189..f8106bd011 100644 --- a/plugins/kubernetes/src/components/PodExecTerminal/PodExecTerminal.tsx +++ b/plugins/kubernetes-react/src/components/PodExecTerminal/PodExecTerminal.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import 'xterm/css/xterm.css'; +import 'xterm'; import { discoveryApiRef, useApi } from '@backstage/core-plugin-api'; import React, { useEffect, useMemo, useState } from 'react'; diff --git a/plugins/kubernetes/src/components/PodExecTerminal/PodExecTerminalAttachAddon.ts b/plugins/kubernetes-react/src/components/PodExecTerminal/PodExecTerminalAttachAddon.ts similarity index 100% rename from plugins/kubernetes/src/components/PodExecTerminal/PodExecTerminalAttachAddon.ts rename to plugins/kubernetes-react/src/components/PodExecTerminal/PodExecTerminalAttachAddon.ts diff --git a/plugins/kubernetes/src/components/PodExecTerminal/PodExecTerminalDialog.tsx b/plugins/kubernetes-react/src/components/PodExecTerminal/PodExecTerminalDialog.tsx similarity index 100% rename from plugins/kubernetes/src/components/PodExecTerminal/PodExecTerminalDialog.tsx rename to plugins/kubernetes-react/src/components/PodExecTerminal/PodExecTerminalDialog.tsx diff --git a/plugins/kubernetes/src/components/PodExecTerminal/index.ts b/plugins/kubernetes-react/src/components/PodExecTerminal/index.ts similarity index 100% rename from plugins/kubernetes/src/components/PodExecTerminal/index.ts rename to plugins/kubernetes-react/src/components/PodExecTerminal/index.ts diff --git a/plugins/kubernetes/src/components/PodExecTerminal/matchMedia.mock.ts b/plugins/kubernetes-react/src/components/PodExecTerminal/matchMedia.mock.ts similarity index 100% rename from plugins/kubernetes/src/components/PodExecTerminal/matchMedia.mock.ts rename to plugins/kubernetes-react/src/components/PodExecTerminal/matchMedia.mock.ts diff --git a/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.test.tsx b/plugins/kubernetes-react/src/components/Pods/ErrorList/ErrorList.test.tsx similarity index 97% rename from plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.test.tsx rename to plugins/kubernetes-react/src/components/Pods/ErrorList/ErrorList.test.tsx index b05b4d2d9e..2423654cc3 100644 --- a/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.test.tsx +++ b/plugins/kubernetes-react/src/components/Pods/ErrorList/ErrorList.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { render } from '@testing-library/react'; import { ErrorList } from './ErrorList'; -import { Pod } from 'kubernetes-models/v1/Pod'; +import { Pod } from 'kubernetes-models/v1'; describe('ErrorList', () => { it('error highlight should render', () => { diff --git a/plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.tsx b/plugins/kubernetes-react/src/components/Pods/ErrorList/ErrorList.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/ErrorList/ErrorList.tsx rename to plugins/kubernetes-react/src/components/Pods/ErrorList/ErrorList.tsx diff --git a/plugins/kubernetes/src/components/Pods/ErrorList/index.ts b/plugins/kubernetes-react/src/components/Pods/ErrorList/index.ts similarity index 100% rename from plugins/kubernetes/src/components/Pods/ErrorList/index.ts rename to plugins/kubernetes-react/src/components/Pods/ErrorList/index.ts diff --git a/plugins/kubernetes/src/components/Pods/Events/Events.test.tsx b/plugins/kubernetes-react/src/components/Pods/Events/Events.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/Events/Events.test.tsx rename to plugins/kubernetes-react/src/components/Pods/Events/Events.test.tsx diff --git a/plugins/kubernetes/src/components/Pods/Events/Events.tsx b/plugins/kubernetes-react/src/components/Pods/Events/Events.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/Events/Events.tsx rename to plugins/kubernetes-react/src/components/Pods/Events/Events.tsx diff --git a/plugins/kubernetes/src/components/Pods/Events/index.ts b/plugins/kubernetes-react/src/components/Pods/Events/index.ts similarity index 100% rename from plugins/kubernetes/src/components/Pods/Events/index.ts rename to plugins/kubernetes-react/src/components/Pods/Events/index.ts diff --git a/plugins/kubernetes/src/components/Pods/Events/useEvents.test.tsx b/plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/Events/useEvents.test.tsx rename to plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx diff --git a/plugins/kubernetes/src/components/Pods/Events/useEvents.ts b/plugins/kubernetes-react/src/components/Pods/Events/useEvents.ts similarity index 95% rename from plugins/kubernetes/src/components/Pods/Events/useEvents.ts rename to plugins/kubernetes-react/src/components/Pods/Events/useEvents.ts index 441937507d..e31a4ee859 100644 --- a/plugins/kubernetes/src/components/Pods/Events/useEvents.ts +++ b/plugins/kubernetes-react/src/components/Pods/Events/useEvents.ts @@ -15,7 +15,7 @@ */ import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; -import { kubernetesProxyApiRef } from '../../../api'; +import { kubernetesProxyApiRef } from '../../../api/types'; /** * Arguments for useEvents diff --git a/plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.test.tsx b/plugins/kubernetes-react/src/components/Pods/FixDialog/FixDialog.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.test.tsx rename to plugins/kubernetes-react/src/components/Pods/FixDialog/FixDialog.test.tsx diff --git a/plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.tsx b/plugins/kubernetes-react/src/components/Pods/FixDialog/FixDialog.tsx similarity index 98% rename from plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.tsx rename to plugins/kubernetes-react/src/components/Pods/FixDialog/FixDialog.tsx index 63ce4af03b..c691cc67fd 100644 --- a/plugins/kubernetes/src/components/Pods/FixDialog/FixDialog.tsx +++ b/plugins/kubernetes-react/src/components/Pods/FixDialog/FixDialog.tsx @@ -28,7 +28,7 @@ import HelpIcon from '@material-ui/icons/Help'; import OpenInNewIcon from '@material-ui/icons/OpenInNew'; import { Pod } from 'kubernetes-models/v1/Pod'; -import { DetectedError } from '../../../error-detection'; +import { DetectedError } from '@backstage/plugin-kubernetes-common'; import { PodLogs } from '../PodLogs'; import { Events } from '../Events'; import { LinkButton } from '@backstage/core-components'; diff --git a/plugins/kubernetes/src/components/Pods/FixDialog/index.ts b/plugins/kubernetes-react/src/components/Pods/FixDialog/index.ts similarity index 100% rename from plugins/kubernetes/src/components/Pods/FixDialog/index.ts rename to plugins/kubernetes-react/src/components/Pods/FixDialog/index.ts diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/ContainerCard.test.tsx b/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodDrawer/ContainerCard.test.tsx rename to plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.test.tsx diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/ContainerCard.tsx b/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodDrawer/ContainerCard.tsx rename to plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/PendingPodContent.test.tsx b/plugins/kubernetes-react/src/components/Pods/PodDrawer/PendingPodContent.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodDrawer/PendingPodContent.test.tsx rename to plugins/kubernetes-react/src/components/Pods/PodDrawer/PendingPodContent.test.tsx diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/PendingPodContent.tsx b/plugins/kubernetes-react/src/components/Pods/PodDrawer/PendingPodContent.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodDrawer/PendingPodContent.tsx rename to plugins/kubernetes-react/src/components/Pods/PodDrawer/PendingPodContent.tsx diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.test.tsx b/plugins/kubernetes-react/src/components/Pods/PodDrawer/PodDrawer.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.test.tsx rename to plugins/kubernetes-react/src/components/Pods/PodDrawer/PodDrawer.test.tsx diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.tsx b/plugins/kubernetes-react/src/components/Pods/PodDrawer/PodDrawer.tsx similarity index 99% rename from plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.tsx rename to plugins/kubernetes-react/src/components/Pods/PodDrawer/PodDrawer.tsx index 30588cd347..1b98237d5a 100644 --- a/plugins/kubernetes/src/components/Pods/PodDrawer/PodDrawer.tsx +++ b/plugins/kubernetes-react/src/components/Pods/PodDrawer/PodDrawer.tsx @@ -67,7 +67,7 @@ function getContainerSpecByName(pod: Pod, containerName: string) { * * @public */ -interface PodDrawerProps { +export interface PodDrawerProps { open?: boolean; podAndErrors: PodAndErrors; } diff --git a/plugins/kubernetes/src/components/Pods/PodDrawer/index.ts b/plugins/kubernetes-react/src/components/Pods/PodDrawer/index.ts similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodDrawer/index.ts rename to plugins/kubernetes-react/src/components/Pods/PodDrawer/index.ts diff --git a/plugins/kubernetes/src/components/Pods/PodLogs/PodLogs.tsx b/plugins/kubernetes-react/src/components/Pods/PodLogs/PodLogs.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodLogs/PodLogs.tsx rename to plugins/kubernetes-react/src/components/Pods/PodLogs/PodLogs.tsx diff --git a/plugins/kubernetes/src/components/Pods/PodLogs/PodLogsDialog.tsx b/plugins/kubernetes-react/src/components/Pods/PodLogs/PodLogsDialog.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodLogs/PodLogsDialog.tsx rename to plugins/kubernetes-react/src/components/Pods/PodLogs/PodLogsDialog.tsx diff --git a/plugins/kubernetes/src/components/Pods/PodLogs/index.ts b/plugins/kubernetes-react/src/components/Pods/PodLogs/index.ts similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodLogs/index.ts rename to plugins/kubernetes-react/src/components/Pods/PodLogs/index.ts diff --git a/plugins/kubernetes/src/components/Pods/PodLogs/types.ts b/plugins/kubernetes-react/src/components/Pods/PodLogs/types.ts similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodLogs/types.ts rename to plugins/kubernetes-react/src/components/Pods/PodLogs/types.ts diff --git a/plugins/kubernetes/src/components/Pods/PodLogs/usePodLogs.ts b/plugins/kubernetes-react/src/components/Pods/PodLogs/usePodLogs.ts similarity index 95% rename from plugins/kubernetes/src/components/Pods/PodLogs/usePodLogs.ts rename to plugins/kubernetes-react/src/components/Pods/PodLogs/usePodLogs.ts index 495bb1dc71..26764fc64c 100644 --- a/plugins/kubernetes/src/components/Pods/PodLogs/usePodLogs.ts +++ b/plugins/kubernetes-react/src/components/Pods/PodLogs/usePodLogs.ts @@ -17,7 +17,7 @@ import useAsync from 'react-use/lib/useAsync'; import { ContainerScope } from './types'; import { useApi } from '@backstage/core-plugin-api'; -import { kubernetesProxyApiRef } from '../../../api'; +import { kubernetesProxyApiRef } from '../../../api/types'; /** * Arguments for usePodLogs diff --git a/plugins/kubernetes/src/components/Pods/PodsTable.test.tsx b/plugins/kubernetes-react/src/components/Pods/PodsTable.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/Pods/PodsTable.test.tsx rename to plugins/kubernetes-react/src/components/Pods/PodsTable.test.tsx diff --git a/plugins/kubernetes/src/components/Pods/PodsTable.tsx b/plugins/kubernetes-react/src/components/Pods/PodsTable.tsx similarity index 96% rename from plugins/kubernetes/src/components/Pods/PodsTable.tsx rename to plugins/kubernetes-react/src/components/Pods/PodsTable.tsx index bebfbd0b5d..f7c2660c84 100644 --- a/plugins/kubernetes/src/components/Pods/PodsTable.tsx +++ b/plugins/kubernetes-react/src/components/Pods/PodsTable.tsx @@ -31,11 +31,33 @@ import { V1Pod } from '@kubernetes/client-node'; import { usePodMetrics } from '../../hooks/usePodMetrics'; import { Typography } from '@material-ui/core'; +/** + * + * + * @public + */ export const READY_COLUMNS: PodColumns = 'READY'; + +/** + * + * + * @public + */ export const RESOURCE_COLUMNS: PodColumns = 'RESOURCE'; + +/** + * + * + * @public + */ export type PodColumns = 'READY' | 'RESOURCE'; -type PodsTablesProps = { +/** + * + * + * @public + */ +export type PodsTablesProps = { pods: Pod | V1Pod[]; extraColumns?: PodColumns[]; children?: React.ReactNode; @@ -95,6 +117,11 @@ const Memory = ({ clusterName, pod }: { clusterName: string; pod: Pod }) => { return <>{podStatusToMemoryUtil(metrics)}; }; +/** + * + * + * @public + */ export const PodsTable = ({ pods, extraColumns = [] }: PodsTablesProps) => { const cluster = useContext(ClusterContext); const defaultColumns: TableColumn[] = [ diff --git a/plugins/kubernetes/src/components/Pods/__fixtures__/crashing-pod.json b/plugins/kubernetes-react/src/components/Pods/__fixtures__/crashing-pod.json similarity index 100% rename from plugins/kubernetes/src/components/Pods/__fixtures__/crashing-pod.json rename to plugins/kubernetes-react/src/components/Pods/__fixtures__/crashing-pod.json diff --git a/plugins/kubernetes/src/error-detection/__fixtures__/pod.json b/plugins/kubernetes-react/src/components/Pods/__fixtures__/pod.json similarity index 100% rename from plugins/kubernetes/src/error-detection/__fixtures__/pod.json rename to plugins/kubernetes-react/src/components/Pods/__fixtures__/pod.json diff --git a/plugins/kubernetes/src/components/Pods/index.ts b/plugins/kubernetes-react/src/components/Pods/index.ts similarity index 94% rename from plugins/kubernetes/src/components/Pods/index.ts rename to plugins/kubernetes-react/src/components/Pods/index.ts index c4282de53a..6297a0abce 100644 --- a/plugins/kubernetes/src/components/Pods/index.ts +++ b/plugins/kubernetes-react/src/components/Pods/index.ts @@ -18,5 +18,5 @@ export * from './PodLogs'; export * from './FixDialog'; export * from './Events'; export * from './ErrorList'; -export { PodsTable } from './PodsTable'; +export * from './PodsTable'; export * from './types'; diff --git a/plugins/kubernetes/src/components/Pods/types.ts b/plugins/kubernetes-react/src/components/Pods/types.ts similarity index 92% rename from plugins/kubernetes/src/components/Pods/types.ts rename to plugins/kubernetes-react/src/components/Pods/types.ts index 877df39c24..847e6d63bc 100644 --- a/plugins/kubernetes/src/components/Pods/types.ts +++ b/plugins/kubernetes-react/src/components/Pods/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { Pod } from 'kubernetes-models/v1'; -import { DetectedError } from '../../error-detection'; +import { DetectedError } from '@backstage/plugin-kubernetes-common'; /** * Wraps a pod with the associated detected errors and cluster name diff --git a/plugins/kubernetes/src/components/ResourceUtilization/ResourceUtilization.test.tsx b/plugins/kubernetes-react/src/components/ResourceUtilization/ResourceUtilization.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/ResourceUtilization/ResourceUtilization.test.tsx rename to plugins/kubernetes-react/src/components/ResourceUtilization/ResourceUtilization.test.tsx diff --git a/plugins/kubernetes/src/components/ResourceUtilization/ResourceUtilization.tsx b/plugins/kubernetes-react/src/components/ResourceUtilization/ResourceUtilization.tsx similarity index 96% rename from plugins/kubernetes/src/components/ResourceUtilization/ResourceUtilization.tsx rename to plugins/kubernetes-react/src/components/ResourceUtilization/ResourceUtilization.tsx index 75927958e6..15f906e469 100644 --- a/plugins/kubernetes/src/components/ResourceUtilization/ResourceUtilization.tsx +++ b/plugins/kubernetes-react/src/components/ResourceUtilization/ResourceUtilization.tsx @@ -32,8 +32,7 @@ export interface ResourceUtilizationProps { totalFormatted: string; } -// Visible for testing -export const getProgressColor: GaugePropsGetColor = ({ +const getProgressColor: GaugePropsGetColor = ({ palette, value, inverse, diff --git a/plugins/kubernetes/src/components/ResourceUtilization/index.ts b/plugins/kubernetes-react/src/components/ResourceUtilization/index.ts similarity index 90% rename from plugins/kubernetes/src/components/ResourceUtilization/index.ts rename to plugins/kubernetes-react/src/components/ResourceUtilization/index.ts index 33d232cbf4..088d78a40b 100644 --- a/plugins/kubernetes/src/components/ResourceUtilization/index.ts +++ b/plugins/kubernetes-react/src/components/ResourceUtilization/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { ResourceUtilization } from './ResourceUtilization'; +export * from './ResourceUtilization'; diff --git a/plugins/kubernetes/src/components/ServicesAccordions/ServiceDrawer.test.tsx b/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/ServicesAccordions/ServiceDrawer.test.tsx rename to plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx diff --git a/plugins/kubernetes/src/components/ServicesAccordions/ServiceDrawer.tsx b/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.tsx similarity index 100% rename from plugins/kubernetes/src/components/ServicesAccordions/ServiceDrawer.tsx rename to plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.tsx diff --git a/plugins/kubernetes/src/components/ServicesAccordions/ServicesAccordions.test.tsx b/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/ServicesAccordions/ServicesAccordions.test.tsx rename to plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.test.tsx diff --git a/plugins/kubernetes/src/components/ServicesAccordions/ServicesAccordions.tsx b/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx similarity index 97% rename from plugins/kubernetes/src/components/ServicesAccordions/ServicesAccordions.tsx rename to plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx index f0cb99ec9c..50d6ec6f3e 100644 --- a/plugins/kubernetes/src/components/ServicesAccordions/ServicesAccordions.tsx +++ b/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx @@ -83,7 +83,12 @@ const ServiceCard = ({ service }: ServiceCardProps) => { ); }; -type ServicesAccordionsProps = {}; +/** + * + * + * @public + */ +export type ServicesAccordionsProps = {}; type ServiceAccordionProps = { service: V1Service; @@ -102,6 +107,11 @@ const ServiceAccordion = ({ service }: ServiceAccordionProps) => { ); }; +/** + * + * + * @public + */ export const ServicesAccordions = ({}: ServicesAccordionsProps) => { const groupedResponses = useContext(GroupedResponsesContext); return ( diff --git a/plugins/kubernetes/src/components/ServicesAccordions/__fixtures__/2-services.json b/plugins/kubernetes-react/src/components/ServicesAccordions/__fixtures__/2-services.json similarity index 100% rename from plugins/kubernetes/src/components/ServicesAccordions/__fixtures__/2-services.json rename to plugins/kubernetes-react/src/components/ServicesAccordions/__fixtures__/2-services.json diff --git a/plugins/kubernetes-react/src/components/ServicesAccordions/index.ts b/plugins/kubernetes-react/src/components/ServicesAccordions/index.ts new file mode 100644 index 0000000000..db37d34b5f --- /dev/null +++ b/plugins/kubernetes-react/src/components/ServicesAccordions/index.ts @@ -0,0 +1,16 @@ +/* + * 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 './ServicesAccordions'; diff --git a/plugins/kubernetes/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx rename to plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx diff --git a/plugins/kubernetes/src/components/StatefulSetsAccordions/StatefulSetDrawer.tsx b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.tsx similarity index 100% rename from plugins/kubernetes/src/components/StatefulSetsAccordions/StatefulSetDrawer.tsx rename to plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.tsx diff --git a/plugins/kubernetes/src/components/StatefulSetsAccordions/StatefulSetsAccordions.test.tsx b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetsAccordions.test.tsx similarity index 100% rename from plugins/kubernetes/src/components/StatefulSetsAccordions/StatefulSetsAccordions.test.tsx rename to plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetsAccordions.test.tsx diff --git a/plugins/kubernetes/src/components/StatefulSetsAccordions/StatefulSetsAccordions.tsx b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetsAccordions.tsx similarity index 100% rename from plugins/kubernetes/src/components/StatefulSetsAccordions/StatefulSetsAccordions.tsx rename to plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetsAccordions.tsx diff --git a/plugins/kubernetes/src/components/StatefulSetsAccordions/index.ts b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/index.ts similarity index 100% rename from plugins/kubernetes/src/components/StatefulSetsAccordions/index.ts rename to plugins/kubernetes-react/src/components/StatefulSetsAccordions/index.ts diff --git a/plugins/kubernetes/src/components/index.ts b/plugins/kubernetes-react/src/components/index.ts similarity index 96% rename from plugins/kubernetes/src/components/index.ts rename to plugins/kubernetes-react/src/components/index.ts index 18b75247e5..d9cebe35a3 100644 --- a/plugins/kubernetes/src/components/index.ts +++ b/plugins/kubernetes-react/src/components/index.ts @@ -25,6 +25,5 @@ export * from './JobsAccordions'; export * from './KubernetesDrawer'; export * from './Pods'; export * from './ServicesAccordions'; -export * from './KubernetesContent'; export * from './ResourceUtilization'; export * from './PodExecTerminal'; diff --git a/plugins/kubernetes/src/hooks/Cluster.ts b/plugins/kubernetes-react/src/hooks/Cluster.ts similarity index 97% rename from plugins/kubernetes/src/hooks/Cluster.ts rename to plugins/kubernetes-react/src/hooks/Cluster.ts index e8d01c462c..ee950b7f4d 100644 --- a/plugins/kubernetes/src/hooks/Cluster.ts +++ b/plugins/kubernetes-react/src/hooks/Cluster.ts @@ -16,6 +16,9 @@ import React from 'react'; import { ClusterAttributes } from '@backstage/plugin-kubernetes-common'; +/** + * @public + */ export const ClusterContext = React.createContext({ name: '', }); diff --git a/plugins/kubernetes/src/hooks/GroupedResponses.ts b/plugins/kubernetes-react/src/hooks/GroupedResponses.ts similarity index 90% rename from plugins/kubernetes/src/hooks/GroupedResponses.ts rename to plugins/kubernetes-react/src/hooks/GroupedResponses.ts index 8383c9e1d9..7a81a74337 100644 --- a/plugins/kubernetes/src/hooks/GroupedResponses.ts +++ b/plugins/kubernetes-react/src/hooks/GroupedResponses.ts @@ -14,8 +14,13 @@ * limitations under the License. */ import React from 'react'; -import { GroupedResponses } from '../types/types'; +import { GroupedResponses } from '@backstage/plugin-kubernetes-common'; +/** + * + * + * @public + */ export const GroupedResponsesContext = React.createContext({ pods: [], replicaSets: [], diff --git a/plugins/kubernetes/src/hooks/PodNamesWithErrors.ts b/plugins/kubernetes-react/src/hooks/PodNamesWithErrors.ts similarity index 97% rename from plugins/kubernetes/src/hooks/PodNamesWithErrors.ts rename to plugins/kubernetes-react/src/hooks/PodNamesWithErrors.ts index 7505da3fd2..001a40805f 100644 --- a/plugins/kubernetes/src/hooks/PodNamesWithErrors.ts +++ b/plugins/kubernetes-react/src/hooks/PodNamesWithErrors.ts @@ -15,6 +15,9 @@ */ import React from 'react'; +/** + * @public + */ export const PodNamesWithErrorsContext = React.createContext>( new Set(), ); diff --git a/plugins/kubernetes/src/hooks/PodNamesWithMetrics.ts b/plugins/kubernetes-react/src/hooks/PodNamesWithMetrics.ts similarity index 97% rename from plugins/kubernetes/src/hooks/PodNamesWithMetrics.ts rename to plugins/kubernetes-react/src/hooks/PodNamesWithMetrics.ts index 0df42a8ab0..12da138cfb 100644 --- a/plugins/kubernetes/src/hooks/PodNamesWithMetrics.ts +++ b/plugins/kubernetes-react/src/hooks/PodNamesWithMetrics.ts @@ -16,8 +16,8 @@ import React from 'react'; import { ClientPodStatus } from '@backstage/plugin-kubernetes-common'; -/* - * @deprecated +/** + * @public */ export const PodNamesWithMetricsContext = React.createContext< Map diff --git a/plugins/kubernetes/src/hooks/__mocks__/useIsPodExecTerminalSupported.ts b/plugins/kubernetes-react/src/hooks/__mocks__/useIsPodExecTerminalSupported.ts similarity index 100% rename from plugins/kubernetes/src/hooks/__mocks__/useIsPodExecTerminalSupported.ts rename to plugins/kubernetes-react/src/hooks/__mocks__/useIsPodExecTerminalSupported.ts diff --git a/plugins/kubernetes/src/hooks/auth.test.ts b/plugins/kubernetes-react/src/hooks/auth.test.ts similarity index 100% rename from plugins/kubernetes/src/hooks/auth.test.ts rename to plugins/kubernetes-react/src/hooks/auth.test.ts diff --git a/plugins/kubernetes/src/hooks/auth.ts b/plugins/kubernetes-react/src/hooks/auth.ts similarity index 98% rename from plugins/kubernetes/src/hooks/auth.ts rename to plugins/kubernetes-react/src/hooks/auth.ts index cce0bc27d6..76e08f2783 100644 --- a/plugins/kubernetes/src/hooks/auth.ts +++ b/plugins/kubernetes-react/src/hooks/auth.ts @@ -15,9 +15,9 @@ */ import { Entity } from '@backstage/catalog-model'; -import { KubernetesApi } from '../api/types'; -import { KubernetesAuthProvidersApi } from '../kubernetes-auth-provider/types'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; +import { KubernetesAuthProvidersApi } from '../kubernetes-auth-provider'; +import { KubernetesApi } from '../api/types'; export const generateAuth = async ( entity: Entity, diff --git a/plugins/kubernetes/src/hooks/index.ts b/plugins/kubernetes-react/src/hooks/index.ts similarity index 100% rename from plugins/kubernetes/src/hooks/index.ts rename to plugins/kubernetes-react/src/hooks/index.ts diff --git a/plugins/kubernetes/src/hooks/test-utils.tsx b/plugins/kubernetes-react/src/hooks/test-utils.tsx similarity index 100% rename from plugins/kubernetes/src/hooks/test-utils.tsx rename to plugins/kubernetes-react/src/hooks/test-utils.tsx diff --git a/plugins/kubernetes/src/hooks/types.ts b/plugins/kubernetes-react/src/hooks/types.ts similarity index 100% rename from plugins/kubernetes/src/hooks/types.ts rename to plugins/kubernetes-react/src/hooks/types.ts diff --git a/plugins/kubernetes/src/hooks/useCustomResources.test.ts b/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts similarity index 100% rename from plugins/kubernetes/src/hooks/useCustomResources.test.ts rename to plugins/kubernetes-react/src/hooks/useCustomResources.test.ts diff --git a/plugins/kubernetes/src/hooks/useCustomResources.ts b/plugins/kubernetes-react/src/hooks/useCustomResources.ts similarity index 99% rename from plugins/kubernetes/src/hooks/useCustomResources.ts rename to plugins/kubernetes-react/src/hooks/useCustomResources.ts index c53e00d81c..4faeb48894 100644 --- a/plugins/kubernetes/src/hooks/useCustomResources.ts +++ b/plugins/kubernetes-react/src/hooks/useCustomResources.ts @@ -15,8 +15,6 @@ */ import { Entity } from '@backstage/catalog-model'; -import { kubernetesApiRef } from '../api/types'; -import { kubernetesAuthProvidersApiRef } from '../kubernetes-auth-provider/types'; import { useCallback } from 'react'; import useInterval from 'react-use/lib/useInterval'; import { @@ -27,6 +25,8 @@ import { useApi } from '@backstage/core-plugin-api'; import { KubernetesObjects } from './useKubernetesObjects'; import { generateAuth } from './auth'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; +import { kubernetesAuthProvidersApiRef } from '../kubernetes-auth-provider'; +import { kubernetesApiRef } from '../api/types'; /** * Retrieves the provided custom resources related to the provided entity, refreshes at an interval. diff --git a/plugins/kubernetes/src/hooks/useIsPodExecTerminalSupported.test.ts b/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts similarity index 100% rename from plugins/kubernetes/src/hooks/useIsPodExecTerminalSupported.test.ts rename to plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts diff --git a/plugins/kubernetes/src/hooks/useIsPodExecTerminalSupported.ts b/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.ts similarity index 96% rename from plugins/kubernetes/src/hooks/useIsPodExecTerminalSupported.ts rename to plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.ts index 17f64bf0dd..e881951059 100644 --- a/plugins/kubernetes/src/hooks/useIsPodExecTerminalSupported.ts +++ b/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.ts @@ -15,8 +15,7 @@ */ import { useApi } from '@backstage/core-plugin-api'; import useAsync, { AsyncState } from 'react-use/lib/useAsync'; - -import { kubernetesApiRef } from '../api'; +import { kubernetesApiRef } from '../api/types'; /** * Check if conditions for a pod exec call through the proxy endpoint are met diff --git a/plugins/kubernetes/src/hooks/useKubernetesObjects.test.ts b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts similarity index 100% rename from plugins/kubernetes/src/hooks/useKubernetesObjects.test.ts rename to plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts diff --git a/plugins/kubernetes/src/hooks/useKubernetesObjects.ts b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.ts similarity index 97% rename from plugins/kubernetes/src/hooks/useKubernetesObjects.ts rename to plugins/kubernetes-react/src/hooks/useKubernetesObjects.ts index aad2f48fd3..f2b8de3cc6 100644 --- a/plugins/kubernetes/src/hooks/useKubernetesObjects.ts +++ b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.ts @@ -15,21 +15,29 @@ */ import { Entity } from '@backstage/catalog-model'; -import { kubernetesApiRef } from '../api/types'; -import { kubernetesAuthProvidersApiRef } from '../kubernetes-auth-provider/types'; import { useCallback } from 'react'; import useInterval from 'react-use/lib/useInterval'; import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; import { useApi } from '@backstage/core-plugin-api'; import { generateAuth } from './auth'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; +import { kubernetesAuthProvidersApiRef } from '../kubernetes-auth-provider'; +import { kubernetesApiRef } from '../api/types'; +/** + * + * @public + */ export interface KubernetesObjects { kubernetesObjects?: ObjectsByEntityResponse; loading: boolean; error?: string; } +/** + * + * @public + */ export const useKubernetesObjects = ( entity: Entity, intervalMs: number = 10000, diff --git a/plugins/kubernetes/src/hooks/useMatchingErrors.test.tsx b/plugins/kubernetes-react/src/hooks/useMatchingErrors.test.tsx similarity index 95% rename from plugins/kubernetes/src/hooks/useMatchingErrors.test.tsx rename to plugins/kubernetes-react/src/hooks/useMatchingErrors.test.tsx index 4ed4dbd73c..4d817e838d 100644 --- a/plugins/kubernetes/src/hooks/useMatchingErrors.test.tsx +++ b/plugins/kubernetes-react/src/hooks/useMatchingErrors.test.tsx @@ -16,8 +16,10 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; import { DetectedErrorsContext, useMatchingErrors } from './useMatchingErrors'; -import { DetectedError } from '../error-detection'; -import { ResourceRef } from '../error-detection/types'; +import { + DetectedError, + ResourceRef, +} from '@backstage/plugin-kubernetes-common'; const genericErrorWithRef = (resourceRef: ResourceRef): DetectedError => { return { diff --git a/plugins/kubernetes/src/hooks/useMatchingErrors.ts b/plugins/kubernetes-react/src/hooks/useMatchingErrors.ts similarity index 95% rename from plugins/kubernetes/src/hooks/useMatchingErrors.ts rename to plugins/kubernetes-react/src/hooks/useMatchingErrors.ts index aa90d52cbb..1975065b7b 100644 --- a/plugins/kubernetes/src/hooks/useMatchingErrors.ts +++ b/plugins/kubernetes-react/src/hooks/useMatchingErrors.ts @@ -14,7 +14,10 @@ * limitations under the License. */ import React, { useContext } from 'react'; -import { DetectedError, ResourceRef } from '../error-detection/types'; +import { + DetectedError, + ResourceRef, +} from '@backstage/plugin-kubernetes-common'; import { TypeMeta } from '@kubernetes-models/base'; import { IIoK8sApimachineryPkgApisMetaV1ObjectMeta as V1ObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta'; diff --git a/plugins/kubernetes/src/hooks/usePodMetrics.test.tsx b/plugins/kubernetes-react/src/hooks/usePodMetrics.test.tsx similarity index 100% rename from plugins/kubernetes/src/hooks/usePodMetrics.test.tsx rename to plugins/kubernetes-react/src/hooks/usePodMetrics.test.tsx diff --git a/plugins/kubernetes/src/hooks/usePodMetrics.ts b/plugins/kubernetes-react/src/hooks/usePodMetrics.ts similarity index 99% rename from plugins/kubernetes/src/hooks/usePodMetrics.ts rename to plugins/kubernetes-react/src/hooks/usePodMetrics.ts index 4392487cac..6d3c52690f 100644 --- a/plugins/kubernetes/src/hooks/usePodMetrics.ts +++ b/plugins/kubernetes-react/src/hooks/usePodMetrics.ts @@ -26,8 +26,8 @@ export const PodMetricsContext = React.createContext< Map >(new Map()); -/* - * @alpha +/** + * @public */ export type PodMetricsMatcher = { metadata?: IObjectMeta; diff --git a/plugins/kubernetes-react/src/index.ts b/plugins/kubernetes-react/src/index.ts new file mode 100644 index 0000000000..e5c84eab79 --- /dev/null +++ b/plugins/kubernetes-react/src/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +/** + * Web library for the kubernetes-react plugin. + * + * @packageDocumentation + */ + +// In this package you might for example export components or hooks +// that are useful to other plugins or modules. + +export * from './hooks'; +export * from './api'; +export * from './kubernetes-auth-provider'; +export * from './components'; diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts b/plugins/kubernetes-react/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts similarity index 98% rename from plugins/kubernetes/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts rename to plugins/kubernetes-react/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts index 401fc1e127..34a83dfed3 100644 --- a/plugins/kubernetes/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts +++ b/plugins/kubernetes-react/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts @@ -17,6 +17,7 @@ import { OAuthApi } from '@backstage/core-plugin-api'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { KubernetesAuthProvider } from './types'; +/** @public */ export class AksKubernetesAuthProvider implements KubernetesAuthProvider { constructor(private readonly microsoftAuthApi: OAuthApi) {} diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/GoogleKubernetesAuthProvider.ts b/plugins/kubernetes-react/src/kubernetes-auth-provider/GoogleKubernetesAuthProvider.ts similarity index 99% rename from plugins/kubernetes/src/kubernetes-auth-provider/GoogleKubernetesAuthProvider.ts rename to plugins/kubernetes-react/src/kubernetes-auth-provider/GoogleKubernetesAuthProvider.ts index fbce644a89..9d7259b70e 100644 --- a/plugins/kubernetes/src/kubernetes-auth-provider/GoogleKubernetesAuthProvider.ts +++ b/plugins/kubernetes-react/src/kubernetes-auth-provider/GoogleKubernetesAuthProvider.ts @@ -18,6 +18,7 @@ import { KubernetesAuthProvider } from './types'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { OAuthApi } from '@backstage/core-plugin-api'; +/** @public */ export class GoogleKubernetesAuthProvider implements KubernetesAuthProvider { authProvider: OAuthApi; diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts b/plugins/kubernetes-react/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts similarity index 100% rename from plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts rename to plugins/kubernetes-react/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts b/plugins/kubernetes-react/src/kubernetes-auth-provider/KubernetesAuthProviders.ts similarity index 99% rename from plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts rename to plugins/kubernetes-react/src/kubernetes-auth-provider/KubernetesAuthProviders.ts index 84154d5e96..77a7b156d7 100644 --- a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts +++ b/plugins/kubernetes-react/src/kubernetes-auth-provider/KubernetesAuthProviders.ts @@ -22,6 +22,7 @@ import { OAuthApi, OpenIdConnectApi } from '@backstage/core-plugin-api'; import { OidcKubernetesAuthProvider } from './OidcKubernetesAuthProvider'; import { AksKubernetesAuthProvider } from './AksKubernetesAuthProvider'; +/** @public */ export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { private readonly kubernetesAuthProviderMap: Map< string, diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts b/plugins/kubernetes-react/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts similarity index 99% rename from plugins/kubernetes/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts rename to plugins/kubernetes-react/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts index b2e6c5cbc2..c117200f56 100644 --- a/plugins/kubernetes/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts +++ b/plugins/kubernetes-react/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts @@ -19,6 +19,7 @@ import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { OpenIdConnectApi } from '@backstage/core-plugin-api'; import { KubernetesAuthProvider } from './types'; +/** @public */ export class OidcKubernetesAuthProvider implements KubernetesAuthProvider { providerName: string; authProvider: OpenIdConnectApi; diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/ServerSideAuthProvider.ts b/plugins/kubernetes-react/src/kubernetes-auth-provider/ServerSideAuthProvider.ts similarity index 100% rename from plugins/kubernetes/src/kubernetes-auth-provider/ServerSideAuthProvider.ts rename to plugins/kubernetes-react/src/kubernetes-auth-provider/ServerSideAuthProvider.ts diff --git a/plugins/kubernetes/src/error-detection/index.ts b/plugins/kubernetes-react/src/kubernetes-auth-provider/index.ts similarity index 70% rename from plugins/kubernetes/src/error-detection/index.ts rename to plugins/kubernetes-react/src/kubernetes-auth-provider/index.ts index 3a8789d79d..5ab8b0be43 100644 --- a/plugins/kubernetes/src/error-detection/index.ts +++ b/plugins/kubernetes-react/src/kubernetes-auth-provider/index.ts @@ -14,10 +14,9 @@ * limitations under the License. */ -export type { - DetectedError, - DetectedErrorsByCluster, - ErrorSeverity, - ResourceRef, -} from './types'; -export { detectErrors } from './error-detection'; +export * from './types'; +export * from './KubernetesAuthProviders'; +export * from './GoogleKubernetesAuthProvider'; +export * from './ServerSideAuthProvider'; +export * from './OidcKubernetesAuthProvider'; +export * from './AksKubernetesAuthProvider'; diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/types.ts b/plugins/kubernetes-react/src/kubernetes-auth-provider/types.ts similarity index 96% rename from plugins/kubernetes/src/kubernetes-auth-provider/types.ts rename to plugins/kubernetes-react/src/kubernetes-auth-provider/types.ts index 418758dd31..adf323d1d8 100644 --- a/plugins/kubernetes/src/kubernetes-auth-provider/types.ts +++ b/plugins/kubernetes-react/src/kubernetes-auth-provider/types.ts @@ -17,6 +17,7 @@ import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { createApiRef } from '@backstage/core-plugin-api'; +/** @public */ export interface KubernetesAuthProvider { decorateRequestBodyForAuth( requestBody: KubernetesRequestBody, @@ -24,11 +25,13 @@ export interface KubernetesAuthProvider { getCredentials(): Promise<{ token?: string }>; } +/** @public */ export const kubernetesAuthProvidersApiRef = createApiRef({ id: 'plugin.kubernetes-auth-providers.service', }); +/** @public */ export interface KubernetesAuthProvidersApi { decorateRequestBodyForAuth( authProvider: string, diff --git a/plugins/kubernetes-react/src/setupTests.ts b/plugins/kubernetes-react/src/setupTests.ts new file mode 100644 index 0000000000..865308e634 --- /dev/null +++ b/plugins/kubernetes-react/src/setupTests.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. + */ +import '@testing-library/jest-dom'; diff --git a/plugins/kubernetes/src/types/index.ts b/plugins/kubernetes-react/src/types/index.ts similarity index 100% rename from plugins/kubernetes/src/types/index.ts rename to plugins/kubernetes-react/src/types/index.ts diff --git a/plugins/kubernetes-react/src/types/types.ts b/plugins/kubernetes-react/src/types/types.ts new file mode 100644 index 0000000000..7efd1ef3ff --- /dev/null +++ b/plugins/kubernetes-react/src/types/types.ts @@ -0,0 +1,28 @@ +/* + * 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 type { JsonObject } from '@backstage/types'; + +export interface ClusterLinksFormatterOptions { + dashboardUrl?: URL; + dashboardParameters?: JsonObject; + object: any; + kind: string; +} + +export type ClusterLinksFormatter = ( + options: ClusterLinksFormatterOptions, +) => URL; diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.test.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.test.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.ts similarity index 90% rename from plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.ts index 6a998bbce2..ae3bdb950f 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts +++ b/plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.ts @@ -17,6 +17,7 @@ import type { JsonObject } from '@backstage/types'; import { defaultFormatterName, clusterLinksFormatters } from './formatters'; +// @Deprecated use import { FormatClusterLinkOptions } from '@backstage/kubernetes-react' export type FormatClusterLinkOptions = { dashboardUrl?: string; dashboardApp?: string; @@ -25,6 +26,7 @@ export type FormatClusterLinkOptions = { kind: string; }; +// @Deprecated use import { formatClusterLink } from '@backstage/kubernetes-react' export function formatClusterLink(options: FormatClusterLinkOptions) { if (!options.dashboardUrl && !options.dashboardParameters) { return undefined; diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/aks.test.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.test.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/aks.test.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.test.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/aks.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/aks.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/eks.test.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.test.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/eks.test.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.test.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/eks.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/eks.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.test.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.test.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/gke.test.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.test.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/gke.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/index.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/index.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/index.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/index.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.test.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.test.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.test.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/openshift.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/rancher.test.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.test.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/rancher.test.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.test.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/rancher.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/rancher.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.test.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.test.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/standard.test.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.test.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/standard.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/formatters/standard.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.ts diff --git a/plugins/kubernetes/src/utils/clusterLinks/index.ts b/plugins/kubernetes-react/src/utils/clusterLinks/index.ts similarity index 100% rename from plugins/kubernetes/src/utils/clusterLinks/index.ts rename to plugins/kubernetes-react/src/utils/clusterLinks/index.ts diff --git a/plugins/kubernetes/src/utils/crons.test.ts b/plugins/kubernetes-react/src/utils/crons.test.ts similarity index 100% rename from plugins/kubernetes/src/utils/crons.test.ts rename to plugins/kubernetes-react/src/utils/crons.test.ts diff --git a/plugins/kubernetes/src/utils/crons.ts b/plugins/kubernetes-react/src/utils/crons.ts similarity index 100% rename from plugins/kubernetes/src/utils/crons.ts rename to plugins/kubernetes-react/src/utils/crons.ts diff --git a/plugins/kubernetes/src/utils/index.ts b/plugins/kubernetes-react/src/utils/index.ts similarity index 100% rename from plugins/kubernetes/src/utils/index.ts rename to plugins/kubernetes-react/src/utils/index.ts diff --git a/plugins/kubernetes/src/utils/owner.test.ts b/plugins/kubernetes-react/src/utils/owner.test.ts similarity index 100% rename from plugins/kubernetes/src/utils/owner.test.ts rename to plugins/kubernetes-react/src/utils/owner.test.ts diff --git a/plugins/kubernetes/src/utils/owner.ts b/plugins/kubernetes-react/src/utils/owner.ts similarity index 100% rename from plugins/kubernetes/src/utils/owner.ts rename to plugins/kubernetes-react/src/utils/owner.ts diff --git a/plugins/kubernetes/src/utils/pod.test.tsx b/plugins/kubernetes-react/src/utils/pod.test.tsx similarity index 100% rename from plugins/kubernetes/src/utils/pod.test.tsx rename to plugins/kubernetes-react/src/utils/pod.test.tsx diff --git a/plugins/kubernetes/src/utils/pod.tsx b/plugins/kubernetes-react/src/utils/pod.tsx similarity index 100% rename from plugins/kubernetes/src/utils/pod.tsx rename to plugins/kubernetes-react/src/utils/pod.tsx diff --git a/plugins/kubernetes/src/utils/resources.ts b/plugins/kubernetes-react/src/utils/resources.ts similarity index 100% rename from plugins/kubernetes/src/utils/resources.ts rename to plugins/kubernetes-react/src/utils/resources.ts diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md index d1c1748758..64b56cf786 100644 --- a/plugins/kubernetes/api-report.md +++ b/plugins/kubernetes/api-report.md @@ -5,162 +5,10 @@ ```ts /// -import { ApiRef } from '@backstage/core-plugin-api'; -import { AsyncState } from 'react-use/lib/useAsyncFn'; import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { ClientContainerStatus } from '@backstage/plugin-kubernetes-common'; -import { ClientPodStatus } from '@backstage/plugin-kubernetes-common'; -import { ClusterAttributes } from '@backstage/plugin-kubernetes-common'; -import { ClusterObjects } from '@backstage/plugin-kubernetes-common'; -import { CustomObjectsByEntityRequest } from '@backstage/plugin-kubernetes-common'; -import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; -import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; -import { Event as Event_2 } from 'kubernetes-models/v1'; -import { IContainer } from 'kubernetes-models/v1'; -import { IContainerStatus } from 'kubernetes-models/v1'; -import { IdentityApi } from '@backstage/core-plugin-api'; -import { IIoK8sApimachineryPkgApisMetaV1ObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta'; -import { IObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta'; -import type { JsonObject } from '@backstage/types'; -import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; -import { OAuthApi } from '@backstage/core-plugin-api'; -import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; -import { OpenIdConnectApi } from '@backstage/core-plugin-api'; -import { Pod } from 'kubernetes-models/v1/Pod'; -import { Pod as Pod_2 } from 'kubernetes-models/v1'; import { default as React_2 } from 'react'; -import * as React_3 from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; -import { TypeMeta } from '@kubernetes-models/base'; -import { V1ConfigMap } from '@kubernetes/client-node'; -import { V1CronJob } from '@kubernetes/client-node'; -import { V1Deployment } from '@kubernetes/client-node'; -import { V1HorizontalPodAutoscaler } from '@kubernetes/client-node'; -import { V1Ingress } from '@kubernetes/client-node'; -import { V1Job } from '@kubernetes/client-node'; -import { V1ObjectMeta } from '@kubernetes/client-node'; -import { V1Pod } from '@kubernetes/client-node'; -import { V1ReplicaSet } from '@kubernetes/client-node'; -import { V1Service } from '@kubernetes/client-node'; -import { V1StatefulSet } from '@kubernetes/client-node'; -import { WorkloadsByEntityRequest } from '@backstage/plugin-kubernetes-common'; - -// Warning: (ae-forgotten-export) The symbol "ClusterProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "Cluster" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const Cluster: ({ - clusterObjects, - podsWithErrors, -}: ClusterProps) => React_2.JSX.Element; - -// Warning: (ae-missing-release-tag) "ClusterContext" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const ClusterContext: React_2.Context; - -// Warning: (ae-missing-release-tag) "ClusterLinksFormatter" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type ClusterLinksFormatter = ( - options: ClusterLinksFormatterOptions, -) => URL; - -// Warning: (ae-missing-release-tag) "ClusterLinksFormatterOptions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface ClusterLinksFormatterOptions { - // (undocumented) - dashboardParameters?: JsonObject; - // (undocumented) - dashboardUrl?: URL; - // (undocumented) - kind: string; - // (undocumented) - object: any; -} - -// Warning: (ae-missing-release-tag) "clusterLinksFormatters" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const clusterLinksFormatters: Record; - -// @public -export const ContainerCard: React_2.FC; - -// @public -export interface ContainerCardProps { - // (undocumented) - containerMetrics?: ClientContainerStatus; - // (undocumented) - containerSpec?: IContainer; - // (undocumented) - containerStatus: IContainerStatus; - // (undocumented) - podScope: PodScope; -} - -// @public -export interface ContainerScope extends PodScope { - // (undocumented) - containerName: string; -} - -// Warning: (ae-forgotten-export) The symbol "CronJobsAccordionsProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "CronJobsAccordions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const CronJobsAccordions: ({}: CronJobsAccordionsProps) => React_2.JSX.Element; - -// Warning: (ae-forgotten-export) The symbol "CustomResourcesProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "CustomResources" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const CustomResources: ({}: CustomResourcesProps) => React_2.JSX.Element; - -// Warning: (ae-missing-release-tag) "DeploymentResources" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface DeploymentResources { - // (undocumented) - deployments: V1Deployment[]; - // (undocumented) - horizontalPodAutoscalers: V1HorizontalPodAutoscaler[]; - // (undocumented) - pods: V1Pod[]; - // (undocumented) - replicaSets: V1ReplicaSet[]; -} - -// @public -export interface DetectedError { - // (undocumented) - message: string; - // (undocumented) - occurrenceCount: number; - // Warning: (ae-forgotten-export) The symbol "ProposedFix" needs to be exported by the entry point index.d.ts - // - // (undocumented) - proposedFix?: ProposedFix; - // (undocumented) - severity: ErrorSeverity; - // (undocumented) - sourceRef: ResourceRef; - // (undocumented) - type: string; -} - -// @public -export type DetectedErrorsByCluster = Map; - -// @public -export const DetectedErrorsContext: React_2.Context; - -// @public -export const detectErrors: ( - objects: ObjectsByEntityResponse, -) => DetectedErrorsByCluster; // Warning: (ae-missing-release-tag) "EntityKubernetesContent" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -174,338 +22,11 @@ export type EntityKubernetesContentProps = { refreshIntervalMs?: number; }; -// @public -export const ErrorList: ({ - podAndErrors, -}: ErrorListProps) => React_2.JSX.Element; - -// @public -export interface ErrorListProps { - // (undocumented) - podAndErrors: PodAndErrors[]; -} - -// @public (undocumented) -export type ErrorMatcher = { - metadata?: IIoK8sApimachineryPkgApisMetaV1ObjectMeta; -} & TypeMeta; - -// Warning: (ae-forgotten-export) The symbol "ErrorPanelProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "ErrorPanel" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const ErrorPanel: ({ - entityName, - errorMessage, - clustersWithErrors, -}: ErrorPanelProps) => React_2.JSX.Element; - -// Warning: (ae-forgotten-export) The symbol "ErrorReportingProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "ErrorReporting" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const ErrorReporting: ({ - detectedErrors, -}: ErrorReportingProps) => React_3.JSX.Element; - -// @public -export type ErrorSeverity = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; - -// @public -export const Events: ({ - involvedObjectName, - namespace, - clusterName, - warningEventsOnly, -}: EventsProps) => React_2.JSX.Element; - -// @public -export const EventsContent: ({ - events, - warningEventsOnly, -}: EventsContentProps) => React_2.JSX.Element; - -// @public -export interface EventsContentProps { - // (undocumented) - events: Event_2[]; - // (undocumented) - warningEventsOnly?: boolean; -} - -// @public -export interface EventsOptions { - // (undocumented) - clusterName: string; - // (undocumented) - involvedObjectName: string; - // (undocumented) - namespace: string; -} - -// @public -export interface EventsProps { - // (undocumented) - clusterName: string; - // (undocumented) - involvedObjectName: string; - // (undocumented) - namespace: string; - // (undocumented) - warningEventsOnly?: boolean; -} - -// @public -export const FixDialog: React_2.FC; - -// @public -export interface FixDialogProps { - // (undocumented) - clusterName: string; - // (undocumented) - error: DetectedError; - // (undocumented) - open?: boolean; - // (undocumented) - pod: Pod; -} - -// Warning: (ae-forgotten-export) The symbol "FormatClusterLinkOptions" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "formatClusterLink" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function formatClusterLink( - options: FormatClusterLinkOptions, -): string | undefined; - -// Warning: (ae-forgotten-export) The symbol "KubernetesAuthProvider" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "GoogleKubernetesAuthProvider" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export class GoogleKubernetesAuthProvider implements KubernetesAuthProvider { - constructor(authProvider: OAuthApi); - // (undocumented) - authProvider: OAuthApi; - // (undocumented) - decorateRequestBodyForAuth( - requestBody: KubernetesRequestBody, - ): Promise; - // (undocumented) - getCredentials(): Promise<{ - token: string; - }>; -} - -// Warning: (ae-missing-release-tag) "GroupedResponses" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface GroupedResponses extends DeploymentResources { - // (undocumented) - configMaps: V1ConfigMap[]; - // (undocumented) - cronJobs: V1CronJob[]; - // (undocumented) - customResources: any[]; - // (undocumented) - ingresses: V1Ingress[]; - // (undocumented) - jobs: V1Job[]; - // (undocumented) - services: V1Service[]; - // (undocumented) - statefulsets: V1StatefulSet[]; -} - -// Warning: (ae-missing-release-tag) "GroupedResponsesContext" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const GroupedResponsesContext: React_2.Context; - -// @public (undocumented) -export const HorizontalPodAutoscalerDrawer: (props: { - hpa: V1HorizontalPodAutoscaler; - expanded?: boolean; - children?: React_2.ReactNode; -}) => React_2.JSX.Element; - -// Warning: (ae-forgotten-export) The symbol "IngressesAccordionsProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "IngressesAccordions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const IngressesAccordions: ({}: IngressesAccordionsProps) => React_2.JSX.Element; - // Warning: (ae-missing-release-tag) "isKubernetesAvailable" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export const isKubernetesAvailable: (entity: Entity) => boolean; -// Warning: (ae-forgotten-export) The symbol "JobsAccordionsProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "JobsAccordions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const JobsAccordions: ({ - jobs, -}: JobsAccordionsProps) => React_2.JSX.Element; - -// Warning: (ae-missing-release-tag) "KubernetesApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface KubernetesApi { - // (undocumented) - getClusters(): Promise< - { - name: string; - authProvider: string; - oidcTokenProvider?: string | undefined; - }[] - >; - // (undocumented) - getCustomObjectsByEntity( - request: CustomObjectsByEntityRequest, - ): Promise; - // (undocumented) - getObjectsByEntity( - requestBody: KubernetesRequestBody, - ): Promise; - // (undocumented) - getWorkloadsByEntity( - request: WorkloadsByEntityRequest, - ): Promise; - // (undocumented) - proxy(options: { - clusterName: string; - path: string; - init?: RequestInit; - }): Promise; -} - -// Warning: (ae-missing-release-tag) "kubernetesApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const kubernetesApiRef: ApiRef; - -// Warning: (ae-missing-release-tag) "KubernetesAuthProviders" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { - constructor(options: { - microsoftAuthApi: OAuthApi; - googleAuthApi: OAuthApi; - oidcProviders?: { - [key: string]: OpenIdConnectApi; - }; - }); - // (undocumented) - decorateRequestBodyForAuth( - authProvider: string, - requestBody: KubernetesRequestBody, - ): Promise; - // (undocumented) - getCredentials(authProvider: string): Promise<{ - token?: string; - }>; -} - -// Warning: (ae-missing-release-tag) "KubernetesAuthProvidersApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface KubernetesAuthProvidersApi { - // (undocumented) - decorateRequestBodyForAuth( - authProvider: string, - requestBody: KubernetesRequestBody, - ): Promise; - // (undocumented) - getCredentials(authProvider: string): Promise<{ - token?: string; - }>; -} - -// Warning: (ae-missing-release-tag) "kubernetesAuthProvidersApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const kubernetesAuthProvidersApiRef: ApiRef; - -// Warning: (ae-missing-release-tag) "KubernetesBackendClient" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export class KubernetesBackendClient implements KubernetesApi { - constructor(options: { - discoveryApi: DiscoveryApi; - identityApi: IdentityApi; - kubernetesAuthProvidersApi: KubernetesAuthProvidersApi; - }); - // (undocumented) - getClusters(): Promise< - { - name: string; - authProvider: string; - }[] - >; - // (undocumented) - getCustomObjectsByEntity( - request: CustomObjectsByEntityRequest, - ): Promise; - // (undocumented) - getObjectsByEntity( - requestBody: KubernetesRequestBody, - ): Promise; - // (undocumented) - getWorkloadsByEntity( - request: WorkloadsByEntityRequest, - ): Promise; - // (undocumented) - proxy(options: { - clusterName: string; - path: string; - init?: RequestInit; - }): Promise; -} - -// Warning: (ae-forgotten-export) The symbol "KubernetesContentProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "KubernetesContent" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const KubernetesContent: ({ - entity, - refreshIntervalMs, -}: KubernetesContentProps) => React_2.JSX.Element; - -// Warning: (ae-forgotten-export) The symbol "KubernetesDrawerProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "KubernetesDrawer" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const KubernetesDrawer: ({ - open, - label, - drawerContentsHeader, - kubernetesObject, - children, -}: KubernetesDrawerProps) => React_2.JSX.Element; - -// Warning: (ae-forgotten-export) The symbol "KubernetesDrawerContentProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "KubernetesDrawerContent" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const KubernetesDrawerContent: ({ - children, - header, - kubernetesObject, - close, -}: KubernetesDrawerContentProps) => React_2.JSX.Element; - -// Warning: (ae-missing-release-tag) "KubernetesObjects" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface KubernetesObjects { - // (undocumented) - error?: string; - // (undocumented) - kubernetesObjects?: ObjectsByEntityResponse; - // (undocumented) - loading: boolean; -} - // Warning: (ae-missing-release-tag) "kubernetesPlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -518,234 +39,6 @@ const kubernetesPlugin: BackstagePlugin< export { kubernetesPlugin }; export { kubernetesPlugin as plugin }; -// Warning: (ae-missing-release-tag) "KubernetesProxyApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface KubernetesProxyApi { - // (undocumented) - getEventsByInvolvedObjectName(request: { - clusterName: string; - involvedObjectName: string; - namespace: string; - }): Promise; - // (undocumented) - getPodLogs(request: { - podName: string; - namespace: string; - clusterName: string; - containerName: string; - previous?: boolean; - }): Promise<{ - text: string; - }>; -} - -// Warning: (ae-missing-release-tag) "kubernetesProxyApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const kubernetesProxyApiRef: ApiRef; - -// @public -export class KubernetesProxyClient { - constructor(options: { kubernetesApi: KubernetesApi }); - // (undocumented) - getEventsByInvolvedObjectName({ - clusterName, - involvedObjectName, - namespace, - }: { - clusterName: string; - involvedObjectName: string; - namespace: string; - }): Promise; - // (undocumented) - getPodLogs({ - podName, - namespace, - clusterName, - containerName, - previous, - }: { - podName: string; - namespace: string; - clusterName: string; - containerName: string; - previous?: boolean; - }): Promise<{ - text: string; - }>; -} - -// Warning: (ae-forgotten-export) The symbol "KubernetesDrawerable" needs to be exported by the entry point index.d.ts -// Warning: (ae-forgotten-export) The symbol "KubernetesStructuredMetadataTableDrawerProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "KubernetesStructuredMetadataTableDrawer" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const KubernetesStructuredMetadataTableDrawer: < - T extends KubernetesDrawerable, ->({ - object, - renderObject, - kind, - buttonVariant, - expanded, - children, -}: KubernetesStructuredMetadataTableDrawerProps) => React_2.JSX.Element; - -// Warning: (ae-forgotten-export) The symbol "ErrorPanelProps_2" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "LinkErrorPanel" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const LinkErrorPanel: ({ - cluster, - errorMessage, -}: ErrorPanelProps_2) => React_2.JSX.Element; - -// @public -export const PendingPodContent: ({ - pod, -}: PendingPodContentProps) => React_2.JSX.Element; - -// @public -export interface PendingPodContentProps { - // (undocumented) - pod: Pod_2; -} - -// @public -export interface PodAndErrors { - // (undocumented) - clusterName: string; - // (undocumented) - errors: DetectedError[]; - // (undocumented) - pod: Pod_2; -} - -// Warning: (ae-forgotten-export) The symbol "PodDrawerProps" needs to be exported by the entry point index.d.ts -// -// @public -export const PodDrawer: ({ - podAndErrors, - open, -}: PodDrawerProps) => React_2.JSX.Element; - -// @public -export const PodExecTerminal: ( - props: PodExecTerminalProps, -) => React_2.JSX.Element; - -// @public -export const PodExecTerminalDialog: ( - props: PodExecTerminalProps, -) => React_2.JSX.Element; - -// @public -export interface PodExecTerminalProps { - // (undocumented) - clusterName: string; - // (undocumented) - containerName: string; - // (undocumented) - podName: string; - // (undocumented) - podNamespace: string; -} - -// @public -export const PodLogs: React_2.FC; - -// @public -export const PodLogsDialog: ({ - containerScope, -}: PodLogsDialogProps) => React_2.JSX.Element; - -// @public -export interface PodLogsDialogProps { - // (undocumented) - containerScope: ContainerScope; -} - -// @public -export interface PodLogsOptions { - // (undocumented) - containerScope: ContainerScope; - // (undocumented) - previous?: boolean; -} - -// @public -export interface PodLogsProps { - // (undocumented) - containerScope: ContainerScope; - // (undocumented) - previous?: boolean; -} - -// @public -export const PodMetricsContext: React_2.Context>; - -// Warning: (ae-missing-release-tag) "PodMetricsMatcher" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type PodMetricsMatcher = { - metadata?: IObjectMeta; -}; - -// Warning: (ae-missing-release-tag) "PodNamesWithErrorsContext" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const PodNamesWithErrorsContext: React_2.Context>; - -// Warning: (ae-missing-release-tag) "PodNamesWithMetricsContext" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const PodNamesWithMetricsContext: React_2.Context< - Map ->; - -// @public -export interface PodScope { - // (undocumented) - clusterName: string; - // (undocumented) - podName: string; - // (undocumented) - podNamespace: string; -} - -// Warning: (ae-forgotten-export) The symbol "PodsTablesProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "PodsTable" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const PodsTable: ({ - pods, - extraColumns, -}: PodsTablesProps) => React_2.JSX.Element; - -// @public -export interface ResourceRef { - // (undocumented) - apiGroup: string; - // (undocumented) - kind: string; - // (undocumented) - name: string; - // (undocumented) - namespace: string; -} - -// Warning: (ae-forgotten-export) The symbol "ResourceUtilizationProps" needs to be exported by the entry point index.d.ts -// -// @public -export const ResourceUtilization: ({ - compressed, - title, - usage, - total, - totalFormatted, -}: ResourceUtilizationProps) => React_2.JSX.Element; - // Warning: (ae-missing-release-tag) "Router" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -753,60 +46,5 @@ export const Router: (props: { refreshIntervalMs?: number; }) => React_2.JSX.Element; -// @public -export class ServerSideKubernetesAuthProvider - implements KubernetesAuthProvider -{ - // (undocumented) - decorateRequestBodyForAuth( - requestBody: KubernetesRequestBody, - ): Promise; - // (undocumented) - getCredentials(): Promise<{}>; -} - -// Warning: (ae-forgotten-export) The symbol "ServicesAccordionsProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "ServicesAccordions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const ServicesAccordions: ({}: ServicesAccordionsProps) => React_2.JSX.Element; - -// @public -export const useCustomResources: ( - entity: Entity, - customResourceMatchers: CustomResourceMatcher[], - intervalMs?: number, -) => KubernetesObjects; - -// @public -export const useEvents: ({ - involvedObjectName, - namespace, - clusterName, -}: EventsOptions) => AsyncState; - -// Warning: (ae-missing-release-tag) "useKubernetesObjects" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const useKubernetesObjects: ( - entity: Entity, - intervalMs?: number, -) => KubernetesObjects; - -// @public -export const useMatchingErrors: (matcher: ErrorMatcher) => DetectedError[]; - -// @public -export const usePodLogs: ({ - containerScope, - previous, -}: PodLogsOptions) => AsyncState<{ - text: string; -}>; - -// @public -export const usePodMetrics: ( - clusterName: string, - matcher: PodMetricsMatcher, -) => ClientPodStatus | undefined; +export * from '@backstage/plugin-kubernetes-react'; ``` diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 7f66af1296..fdc792fc52 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -41,6 +41,7 @@ "@backstage/errors": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-kubernetes-common": "workspace:^", + "@backstage/plugin-kubernetes-react": "workspace:^", "@backstage/theme": "workspace:^", "@backstage/types": "workspace:^", "@kubernetes-models/apimachinery": "^1.1.0", diff --git a/plugins/kubernetes/src/components/KubernetesContent.test.tsx b/plugins/kubernetes/src/KubernetesContent.test.tsx similarity index 91% rename from plugins/kubernetes/src/components/KubernetesContent.test.tsx rename to plugins/kubernetes/src/KubernetesContent.test.tsx index 4c85298dba..7c21c6f5a7 100644 --- a/plugins/kubernetes/src/components/KubernetesContent.test.tsx +++ b/plugins/kubernetes/src/KubernetesContent.test.tsx @@ -18,13 +18,19 @@ import React from 'react'; import { screen } from '@testing-library/react'; import { renderInTestApp } from '@backstage/test-utils'; import { KubernetesContent } from './KubernetesContent'; -import { useKubernetesObjects } from '../hooks'; +import { useKubernetesObjects } from '@backstage/plugin-kubernetes-react'; +import * as oneDeployment from './__fixtures__/1-deployments.json'; +import * as twoDeployments from './__fixtures__/2-deployments.json'; -jest.mock('../hooks'); -import * as oneDeployment from '../__fixtures__/1-deployments.json'; -import * as twoDeployments from '../__fixtures__/2-deployments.json'; +jest.mock('@backstage/plugin-kubernetes-react', () => ({ + ...jest.requireActual('@backstage/plugin-kubernetes-react'), + useKubernetesObjects: jest.fn(), +})); describe('KubernetesContent', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); it('render empty response', async () => { (useKubernetesObjects as any).mockReturnValue({ kubernetesObjects: { diff --git a/plugins/kubernetes/src/components/KubernetesContent.tsx b/plugins/kubernetes/src/KubernetesContent.tsx similarity index 81% rename from plugins/kubernetes/src/components/KubernetesContent.tsx rename to plugins/kubernetes/src/KubernetesContent.tsx index a465422095..9c266b1854 100644 --- a/plugins/kubernetes/src/components/KubernetesContent.tsx +++ b/plugins/kubernetes/src/KubernetesContent.tsx @@ -17,14 +17,23 @@ import React from 'react'; import { Grid, Typography } from '@material-ui/core'; import { Entity } from '@backstage/catalog-model'; -import { ErrorPanel } from './ErrorPanel'; -import { ErrorReporting } from './ErrorReporting'; -import { DetectedError, detectErrors } from '../error-detection'; -import { Cluster } from './Cluster'; -import EmptyStateImage from '../assets/emptystate.svg'; -import { useKubernetesObjects } from '../hooks'; -import { Content, Page, Progress } from '@backstage/core-components'; -import { DetectedErrorsContext } from '../hooks/useMatchingErrors'; +import { + ErrorPanel, + ErrorReporting, + Cluster, + useKubernetesObjects, + DetectedErrorsContext, +} from '@backstage/plugin-kubernetes-react'; +import { + DetectedError, + detectErrors, +} from '@backstage/plugin-kubernetes-common'; +import { + Content, + EmptyState, + Page, + Progress, +} from '@backstage/core-components'; type KubernetesContentProps = { entity: Entity; @@ -98,17 +107,11 @@ export const KubernetesContent = ({ alignItems="center" spacing={2} > - - - No resources on any known clusters for{' '} - {entity.metadata.name} - - - - EmptyState + diff --git a/plugins/kubernetes/src/Router.tsx b/plugins/kubernetes/src/Router.tsx index fd3a4bd0ce..bd8fc09edc 100644 --- a/plugins/kubernetes/src/Router.tsx +++ b/plugins/kubernetes/src/Router.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { Entity } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; import { Route, Routes } from 'react-router-dom'; -import { KubernetesContent } from './components/KubernetesContent'; +import { KubernetesContent } from './KubernetesContent'; import { Button } from '@material-ui/core'; import { MissingAnnotationEmptyState } from '@backstage/core-components'; diff --git a/plugins/kubernetes/src/assets/emptystate.svg b/plugins/kubernetes/src/assets/emptystate.svg deleted file mode 100644 index 8a0490727f..0000000000 --- a/plugins/kubernetes/src/assets/emptystate.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/plugins/kubernetes/src/components/IngressesAccordions/index.ts b/plugins/kubernetes/src/components/IngressesAccordions/index.ts deleted file mode 100644 index 8e7f103e42..0000000000 --- a/plugins/kubernetes/src/components/IngressesAccordions/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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 { IngressesAccordions } from './IngressesAccordions'; diff --git a/plugins/kubernetes/src/components/ServicesAccordions/index.ts b/plugins/kubernetes/src/components/ServicesAccordions/index.ts deleted file mode 100644 index 04fee9caca..0000000000 --- a/plugins/kubernetes/src/components/ServicesAccordions/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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 { ServicesAccordions } from './ServicesAccordions'; diff --git a/plugins/kubernetes/src/index.ts b/plugins/kubernetes/src/index.ts index 616caaef62..3651a861fc 100644 --- a/plugins/kubernetes/src/index.ts +++ b/plugins/kubernetes/src/index.ts @@ -27,10 +27,5 @@ export { } from './plugin'; export type { EntityKubernetesContentProps } from './plugin'; export { Router, isKubernetesAvailable } from './Router'; -export * from './api'; -export * from './kubernetes-auth-provider'; -export * from './utils/clusterLinks'; -export * from './components'; -export * from './error-detection'; -export * from './hooks'; -export * from './types'; +// TODO remove this re-export as a breaking change after a couple of releases +export * from '@backstage/plugin-kubernetes-react'; diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/index.ts b/plugins/kubernetes/src/kubernetes-auth-provider/index.ts deleted file mode 100644 index 23197321f6..0000000000 --- a/plugins/kubernetes/src/kubernetes-auth-provider/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 { kubernetesAuthProvidersApiRef } from './types'; -export type { KubernetesAuthProvidersApi } from './types'; -export { KubernetesAuthProviders } from './KubernetesAuthProviders'; -export { GoogleKubernetesAuthProvider } from './GoogleKubernetesAuthProvider'; -export { ServerSideKubernetesAuthProvider } from './ServerSideAuthProvider'; diff --git a/plugins/kubernetes/src/plugin.ts b/plugins/kubernetes/src/plugin.ts index 02c7bfd2d6..ac55dbbf23 100644 --- a/plugins/kubernetes/src/plugin.ts +++ b/plugins/kubernetes/src/plugin.ts @@ -13,10 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { KubernetesBackendClient } from './api/KubernetesBackendClient'; -import { kubernetesApiRef, kubernetesProxyApiRef } from './api/types'; -import { kubernetesAuthProvidersApiRef } from './kubernetes-auth-provider/types'; -import { KubernetesAuthProviders } from './kubernetes-auth-provider/KubernetesAuthProviders'; +import { + KubernetesBackendClient, + kubernetesApiRef, + kubernetesProxyApiRef, + kubernetesAuthProvidersApiRef, + KubernetesAuthProviders, + KubernetesProxyClient, +} from '@backstage/plugin-kubernetes-react'; import { createApiFactory, createPlugin, @@ -30,7 +34,6 @@ import { oneloginAuthApiRef, createRoutableExtension, } from '@backstage/core-plugin-api'; -import { KubernetesProxyClient } from './api'; export const rootCatalogKubernetesRouteRef = createRouteRef({ id: 'kubernetes', diff --git a/plugins/kubernetes/src/types/types.ts b/plugins/kubernetes/src/types/types.ts deleted file mode 100644 index f15c4f335a..0000000000 --- a/plugins/kubernetes/src/types/types.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 type { JsonObject } from '@backstage/types'; -import { - V1Deployment, - V1Pod, - V1ReplicaSet, - V1HorizontalPodAutoscaler, - V1Service, - V1ConfigMap, - V1Ingress, - V1Job, - V1CronJob, - V1StatefulSet, -} from '@kubernetes/client-node'; - -export interface DeploymentResources { - pods: V1Pod[]; - replicaSets: V1ReplicaSet[]; - deployments: V1Deployment[]; - horizontalPodAutoscalers: V1HorizontalPodAutoscaler[]; -} - -export interface GroupedResponses extends DeploymentResources { - services: V1Service[]; - configMaps: V1ConfigMap[]; - ingresses: V1Ingress[]; - jobs: V1Job[]; - cronJobs: V1CronJob[]; - customResources: any[]; - statefulsets: V1StatefulSet[]; -} - -export interface ClusterLinksFormatterOptions { - dashboardUrl?: URL; - dashboardParameters?: JsonObject; - object: any; - kind: string; -} - -export type ClusterLinksFormatter = ( - options: ClusterLinksFormatterOptions, -) => URL; diff --git a/yarn.lock b/yarn.lock index c1887a4ea0..29a232840d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7636,8 +7636,56 @@ __metadata: dependencies: "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/errors": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/types": "workspace:^" "@kubernetes/client-node": 0.18.1 + kubernetes-models: ^4.3.1 + lodash: ^4.17.21 + luxon: ^3.0.0 + msw: ^1.3.1 + languageName: unknown + linkType: soft + +"@backstage/plugin-kubernetes-react@workspace:^, @backstage/plugin-kubernetes-react@workspace:plugins/kubernetes-react": + version: 0.0.0-use.local + resolution: "@backstage/plugin-kubernetes-react@workspace:plugins/kubernetes-react" + dependencies: + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-kubernetes-common": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/types": "workspace:^" + "@kubernetes-models/apimachinery": ^1.1.0 + "@kubernetes-models/base": ^4.0.1 + "@kubernetes/client-node": ^0.19.0 + "@material-ui/core": ^4.9.13 + "@material-ui/icons": ^4.11.3 + "@material-ui/lab": ^4.0.0-alpha.61 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/react-hooks": ^8.0.1 + "@types/react": ^16.13.1 || ^17.0.0 + cronstrue: ^2.32.0 + jest-websocket-mock: ^2.5.0 + js-yaml: ^4.1.0 + kubernetes-models: ^4.3.1 + lodash: ^4.17.21 + luxon: ^3.0.0 + msw: ^1.3.1 + react-use: ^17.4.0 + xterm: ^5.3.0 + xterm-addon-attach: ^0.9.0 + xterm-addon-fit: ^0.8.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 languageName: unknown linkType: soft @@ -7655,6 +7703,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-kubernetes-common": "workspace:^" + "@backstage/plugin-kubernetes-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@backstage/types": "workspace:^" @@ -12776,6 +12825,32 @@ __metadata: languageName: node linkType: hard +"@kubernetes/client-node@npm:^0.19.0": + version: 0.19.0 + resolution: "@kubernetes/client-node@npm:0.19.0" + dependencies: + "@types/js-yaml": ^4.0.1 + "@types/node": ^20.1.1 + "@types/request": ^2.47.1 + "@types/ws": ^8.5.3 + byline: ^5.0.0 + isomorphic-ws: ^5.0.0 + js-yaml: ^4.1.0 + jsonpath-plus: ^7.2.0 + openid-client: ^5.3.0 + request: ^2.88.0 + rfc4648: ^1.3.0 + stream-buffers: ^3.0.2 + tar: ^6.1.11 + tslib: ^2.4.1 + ws: ^8.11.0 + dependenciesMeta: + openid-client: + optional: true + checksum: d29ccfb562ac51a81f74de570eb832d150be6b73ba887ae1be682df9a34c3ab846d4d4ba74f0a9f0e0ce4da573f949ba712115e1d0513148cdf683a22d729e7f + languageName: node + linkType: hard + "@leichtgewicht/ip-codec@npm:^2.0.1": version: 2.0.3 resolution: "@leichtgewicht/ip-codec@npm:2.0.3" @@ -12949,7 +13024,7 @@ __metadata: languageName: node linkType: hard -"@material-ui/icons@npm:^4.11.2, @material-ui/icons@npm:^4.9.1": +"@material-ui/icons@npm:^4.11.2, @material-ui/icons@npm:^4.11.3, @material-ui/icons@npm:^4.9.1": version: 4.11.3 resolution: "@material-ui/icons@npm:4.11.3" dependencies: @@ -13008,7 +13083,7 @@ __metadata: languageName: node linkType: hard -"@material-ui/lab@npm:4.0.0-alpha.61, @material-ui/lab@npm:^4.0.0-alpha.57, @material-ui/lab@npm:^4.0.0-alpha.60": +"@material-ui/lab@npm:4.0.0-alpha.61, @material-ui/lab@npm:^4.0.0-alpha.57, @material-ui/lab@npm:^4.0.0-alpha.60, @material-ui/lab@npm:^4.0.0-alpha.61": version: 4.0.0-alpha.61 resolution: "@material-ui/lab@npm:4.0.0-alpha.61" dependencies: @@ -17866,10 +17941,10 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0": - version: 20.6.3 - resolution: "@types/node@npm:20.6.3" - checksum: 444a6f1f41cfa8d3e20ce0108e6e43960fb2ae0e481f233bb1c14d6252aa63a92e021de561cd317d9fdb411688f871065f40175a1f18763282dee2613a08f8a3 +"@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^20.1.1": + version: 20.6.5 + resolution: "@types/node@npm:20.6.5" + checksum: b849e849cf7631458a65c5019c81962028e306d8c4455a48422277b240f5a7eb8a1f1dafa60306bd4c773b77263bb8b05c074b1026e868bd137bb2022cf63ea2 languageName: node linkType: hard @@ -22570,12 +22645,12 @@ __metadata: languageName: node linkType: hard -"cronstrue@npm:^2.2.0": - version: 2.31.0 - resolution: "cronstrue@npm:2.31.0" +"cronstrue@npm:^2.2.0, cronstrue@npm:^2.32.0": + version: 2.32.0 + resolution: "cronstrue@npm:2.32.0" bin: cronstrue: bin/cli.js - checksum: 8001433f65751ccd471497be14924dfecd6b91992d615ec7de1fec978792e4a3ab977d05874bea7b6a478dc786ea775554735126c79c8bbe3c94535f20ebebab + checksum: a0925e256583122792fe2f3b92cd49b954ab3e4466c7569a9148b9981db8a389faca139d4eb215142e7b67438a5562219956c56041ed0b8b046b798e72a357a8 languageName: node linkType: hard @@ -29833,7 +29908,7 @@ __metadata: languageName: node linkType: hard -"jest-websocket-mock@npm:^2.4.1": +"jest-websocket-mock@npm:^2.4.1, jest-websocket-mock@npm:^2.5.0": version: 2.5.0 resolution: "jest-websocket-mock@npm:2.5.0" dependencies: @@ -30887,7 +30962,7 @@ __metadata: languageName: node linkType: hard -"kubernetes-models@npm:^4.1.0": +"kubernetes-models@npm:^4.1.0, kubernetes-models@npm:^4.3.1": version: 4.3.1 resolution: "kubernetes-models@npm:4.3.1" dependencies: @@ -33053,7 +33128,7 @@ __metadata: languageName: node linkType: hard -"msw@npm:^1.0.0, msw@npm:^1.0.1, msw@npm:^1.2.1, msw@npm:^1.2.3": +"msw@npm:^1.0.0, msw@npm:^1.0.1, msw@npm:^1.2.1, msw@npm:^1.2.3, msw@npm:^1.3.1": version: 1.3.1 resolution: "msw@npm:1.3.1" dependencies: @@ -42703,6 +42778,15 @@ __metadata: languageName: node linkType: hard +"xterm-addon-attach@npm:^0.9.0": + version: 0.9.0 + resolution: "xterm-addon-attach@npm:0.9.0" + peerDependencies: + xterm: ^5.0.0 + checksum: 70e5d3ecf139c04fae13c644b79c33858ef1a6e28dfe78f91dad3e34f5a155579029b87e91d1d016575acaf17f74e6c59402bde4bcff03461595bea0870f1ec1 + languageName: node + linkType: hard + "xterm-addon-fit@npm:^0.7.0": version: 0.7.0 resolution: "xterm-addon-fit@npm:0.7.0" @@ -42712,10 +42796,19 @@ __metadata: languageName: node linkType: hard -"xterm@npm:^5.2.1": - version: 5.2.1 - resolution: "xterm@npm:5.2.1" - checksum: 3a9de30e772c7ae30895ec97fcfb3b0906429c5ea0cddf8948e8e30301385f82e467c6e6aca28ae50a48300ce795381d83fe35b4e17886ab4a1357054a15f68f +"xterm-addon-fit@npm:^0.8.0": + version: 0.8.0 + resolution: "xterm-addon-fit@npm:0.8.0" + peerDependencies: + xterm: ^5.0.0 + checksum: 5af2041b442f7c804eda2e6f62e3b68b5159b0ae6bd96e2aa8d85b26441df57291cbfed653d1196d4af5d9b94bfc39993df8b409a25c35e0d36bdaf6f5cdfe5f + languageName: node + linkType: hard + +"xterm@npm:^5.2.1, xterm@npm:^5.3.0": + version: 5.3.0 + resolution: "xterm@npm:5.3.0" + checksum: 1bdfdfe4cae4412128376180d85e476b43fb021cdd1114b18acad821c9ea44b5b600e0d88febf2b3572f38fad7741e5161ce0178a44369617cf937222cc6e011 languageName: node linkType: hard From ade908a100185d43b8ba800a89e629d20bd026ac Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 26 Sep 2023 21:32:15 -0300 Subject: [PATCH 021/207] Add Cielo to ADOPTERS.md Signed-off-by: Alex --- ADOPTERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ADOPTERS.md b/ADOPTERS.md index 0d5b9fba59..958d24b968 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -260,3 +260,4 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Localiza&Co](https://www.localiza.com/) | [Augusto Amormino](https://github.com/augustoamormino), [Jonas Soares](https://github.com/jonaopower), [Alexandre Amormino](https://github.com/alexandreamormino), [Greg Almeida](https://github.com/sephh) | We're excited to announce our adoption of Backstage as our Internal Developer Portal! Our mission is to elevate the Developer Experience by streaming information access. Backstage will serve as the ultimate hub for developer resources, including documentation, tools, software insights, and metrics. Through Backstage, we're simplifying processes, offering software templates to empowered and efficient development journey, enhancing self-service capabilities with the embedded all best practices. | | [V2 Digital](https://v2.digital) | [Joe Patterson](https://github.com/jrwpatterson)| We will be using it to be a corporate dashboard plus our software catalog. | | [AppsFlyer](https://www.appsflyer.com/) | [Shahar Shmaram](https://github.com/shmaram) | Internal Developer Portal, a catalog of all company resources, custom providers and processors, scaffolder for generating new resources. +| [Cielo](https://www.cielo.com.br) | [@Alex Silva](https://github.com/narokwq) | We are using as our Internal Developer Portal, it provides developers with the resources, information, and tools they need to build high-quality applications and adhere to organizational standards and security practices. | From bbfa6526f9cdcc58bf32b0eae54bc073c192e938 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 07:41:55 +0000 Subject: [PATCH 022/207] chore(deps): update dependency @types/node-forge to v1.3.6 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 54d0650ad7..48e57bb072 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17933,11 +17933,11 @@ __metadata: linkType: hard "@types/node-forge@npm:^1.3.0": - version: 1.3.5 - resolution: "@types/node-forge@npm:1.3.5" + version: 1.3.6 + resolution: "@types/node-forge@npm:1.3.6" dependencies: "@types/node": "*" - checksum: b93dae2639ab166d8703567285538f14a53fbe9199b02c1e3752d147260be4a8be5257246558a81fc3eee3c5880704039a6aa22c4415aeb06758aad0391ac39c + checksum: 5fe97ce83937c51215a52eb8c9d5c4458abbca2b3cfd91a65142f20fd4a2830ed10ab1a8c860efc55ff36553f939a75c4a6d5c243ed6e24e55a005c9bddeaf43 languageName: node linkType: hard From f18fdc9a43bea25da353267f66050dacd36c0808 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 07:50:26 +0000 Subject: [PATCH 023/207] chore(deps): update dependency @types/nunjucks to v3.2.4 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86e1eb70c1..0288cdebd4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17991,9 +17991,9 @@ __metadata: linkType: hard "@types/nunjucks@npm:^3.1.4": - version: 3.2.3 - resolution: "@types/nunjucks@npm:3.2.3" - checksum: f4263a39f0bafb701fe75a088cf2100f0fe717ab29c53d13eb60fea77e945f8cfdabfb84bd6ce85fd11586f90aa36539cf5bd489166edcf56a189a0407d481a2 + version: 3.2.4 + resolution: "@types/nunjucks@npm:3.2.4" + checksum: d154c6cc98320b6b9f48892eb4238f961b0196e24eb98252f9dceaa0b17bf70cd480a11d4ffda9f419d2570abf6d96524ebd3193b101f0fcf73c65af3e56d064 languageName: node linkType: hard From b777bc45da4f12a756e2c4b243aeef1e1df37f89 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 27 Sep 2023 10:05:14 +0200 Subject: [PATCH 024/207] Adding myself as a codeowner for the - New Relic Browser Analytics plugin - Octopus Deploy plugin Signed-off-by: Jonathan Mezach --- .github/CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a0ba1163f3..cb8101e1b1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -21,6 +21,7 @@ yarn.lock @backstage/maintainers @backst /plugins/azure-devops @backstage/maintainers @backstage/reviewers @awanlin /plugins/azure-devops-backend @backstage/maintainers @backstage/reviewers @awanlin /plugins/azure-devops-common @backstage/maintainers @backstage/reviewers @awanlin +/plugins/analytics-module-newrelic-browser @backstage/maintainers @backstage/reviewers @jmezach /plugins/bitbucket-cloud-common @backstage/maintainers @backstage/reviewers @pjungermann /plugins/bitrise @backstage/maintainers @backstage/reviewers @backstage/sda-se-reviewers /plugins/catalog @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @@ -62,6 +63,7 @@ yarn.lock @backstage/maintainers @backst /plugins/linguist @backstage/maintainers @backstage/reviewers @awanlin /plugins/linguist-backend @backstage/maintainers @backstage/reviewers @awanlin /plugins/linguist-common @backstage/maintainers @backstage/reviewers @awanlin +/plugins/octopus-deploy @backstage/maintainers @backstage/reviewers @jmezach /plugins/permission-* @backstage/permission-maintainers /plugins/playlist @backstage/maintainers @backstage/reviewers @kuangp /plugins/playlist-* @backstage/maintainers @backstage/reviewers @kuangp From fd7072f8582810d691932e94c97ff688b5a66445 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 09:15:45 +0000 Subject: [PATCH 025/207] chore(deps): update dependency @types/passport-auth0 to v1.0.7 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86e1eb70c1..0e38e39234 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18021,12 +18021,12 @@ __metadata: linkType: hard "@types/passport-auth0@npm:^1.0.5": - version: 1.0.5 - resolution: "@types/passport-auth0@npm:1.0.5" + version: 1.0.7 + resolution: "@types/passport-auth0@npm:1.0.7" dependencies: "@types/express": "*" "@types/passport": "*" - checksum: b86b69a182864cae6877c0f16a1d62e24a394dc9cde8e7285a29aef89d52fbb555b899e061157bfd52420dcbccd6fd9b189155e5367a22763b0b2813cbb28354 + checksum: 75b17c3424054a8b0238905088a7c34efab771a0bccc5ce0270d5c6f238ba859fb7354531c0df4f39e7b2c28f10090f9c260ffc42773211fc216a9acbf11170a languageName: node linkType: hard From e2cc718bb5499b7fb567f3e90ed0a928d9efadff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 09:16:17 +0000 Subject: [PATCH 026/207] chore(deps): update dependency @types/passport-github2 to v1.2.6 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86e1eb70c1..40532363ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18031,13 +18031,13 @@ __metadata: linkType: hard "@types/passport-github2@npm:^1.2.4": - version: 1.2.5 - resolution: "@types/passport-github2@npm:1.2.5" + version: 1.2.6 + resolution: "@types/passport-github2@npm:1.2.6" dependencies: "@types/express": "*" "@types/passport": "*" "@types/passport-oauth2": "*" - checksum: a4f1851edb91a2502136b7e76dd10fd3c52aebec938ff21ffa2ade40b1f62d0e7f65991c80589f5cfa40b6cba04bf0b8ea46db6942975bf5918fa4690f681235 + checksum: 72d1c8bc335d0d7f329372ac8bc7edb22c8bea151d4438d876036b6b768f4d12c8de305abbc25b650f373b902bae250008cb185074d2d78da49d15e981208d81 languageName: node linkType: hard From 81f2ffbbb9671b2b66c4ec4b87035aafb53bc65a Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Wed, 27 Sep 2023 11:35:40 +0200 Subject: [PATCH 027/207] Register Pulumi plugin Signed-off-by: Ringo De Smet --- microsite/data/plugins/pulumi.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 microsite/data/plugins/pulumi.yaml diff --git a/microsite/data/plugins/pulumi.yaml b/microsite/data/plugins/pulumi.yaml new file mode 100644 index 0000000000..4724f00f58 --- /dev/null +++ b/microsite/data/plugins/pulumi.yaml @@ -0,0 +1,10 @@ +--- +title: Pulumi +author: pulumi.com +authorUrl: https://www.pulumi.com +category: Infrastructure +description: View Pulumi stack information in Backstage. +documentation: https://github.com/pulumi/pulumi-backstage-plugin +iconUrl: https://www.pulumi.com/logos/brand/avatar-on-white.png +npmPackageName: '@pulumi/backstage-plugin-pulumi' +addedDate: '2023-09-27' From 2c5a5cf6edf32847827458a331d3fc41be1e3b2e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:32:22 +0000 Subject: [PATCH 028/207] chore(deps): update dependency @types/marked to v4.3.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86e1eb70c1..d5433077b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17821,9 +17821,9 @@ __metadata: linkType: hard "@types/marked@npm:^4.0.0": - version: 4.3.1 - resolution: "@types/marked@npm:4.3.1" - checksum: eb6891b925d53ea53057f088b28f9232016499e62639cbb4a67f7d34f288ec6a8e40aae4836dbd06bd0fc3c541fca1175cd50d9e8d405547b6be7b7781e6a2a5 + version: 4.3.2 + resolution: "@types/marked@npm:4.3.2" + checksum: c1107079d6c368dd60a668a41aa2101d006cad404b6eb4af6723d419dc869b278928fb769825f11d0d311a8cf437428992729c8a47253b6a3894a6326b1ee4d9 languageName: node linkType: hard From fce94934eb8923d5912ee37e1693ef004242f5dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:32:54 +0000 Subject: [PATCH 029/207] chore(deps): update dependency @types/mime-types to v2.1.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86e1eb70c1..27da5650a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17844,9 +17844,9 @@ __metadata: linkType: hard "@types/mime-types@npm:^2.1.0": - version: 2.1.1 - resolution: "@types/mime-types@npm:2.1.1" - checksum: 106b5d556add46446a579ad25ff15d6b421851790d887edcad558c90c1e64b1defc72bfbaf4b08f208916e21d9cc45cdb951d77be51268b18221544cfe054a3c + version: 2.1.2 + resolution: "@types/mime-types@npm:2.1.2" + checksum: 9e3c78f1c63211e0450901212566a046da68d4438a5e543333ec9b0be3259bd5d01532734dc51ead40104889b98d12c7663b65212a318aafad3e34c98204e9e1 languageName: node linkType: hard From c24cd93ef6d6ee821943d50e969459a2fcef393d Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Wed, 27 Sep 2023 13:49:49 +0200 Subject: [PATCH 030/207] Update microsite/data/plugins/pulumi.yaml Co-authored-by: Philipp Hugenroth Signed-off-by: Ringo De Smet --- microsite/data/plugins/pulumi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/data/plugins/pulumi.yaml b/microsite/data/plugins/pulumi.yaml index 4724f00f58..ea97bcdef3 100644 --- a/microsite/data/plugins/pulumi.yaml +++ b/microsite/data/plugins/pulumi.yaml @@ -1,6 +1,6 @@ --- title: Pulumi -author: pulumi.com +author: Pulumi authorUrl: https://www.pulumi.com category: Infrastructure description: View Pulumi stack information in Backstage. From 149a500278878cd0767ceb70dd45230587b3c561 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 12:27:24 +0000 Subject: [PATCH 031/207] chore(deps): update dependency @types/minimist to v1.2.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86e1eb70c1..242918d863 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17872,9 +17872,9 @@ __metadata: linkType: hard "@types/minimist@npm:^1.2.0": - version: 1.2.2 - resolution: "@types/minimist@npm:1.2.2" - checksum: b8da83c66eb4aac0440e64674b19564d9d86c80ae273144db9681e5eeff66f238ade9515f5006ffbfa955ceff8b89ad2bd8ec577d7caee74ba101431fb07045d + version: 1.2.3 + resolution: "@types/minimist@npm:1.2.3" + checksum: 666ea4f8c39dcbdfbc3171fe6b3902157c845cc9cb8cee33c10deb706cda5e0cc80f98ace2d6d29f6774b0dc21180c96cd73c592a1cbefe04777247c7ba0e84b languageName: node linkType: hard From 1b4d43e4f3ecb1ebbf947a23a515c9d048af124b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 12:27:59 +0000 Subject: [PATCH 032/207] chore(deps): update dependency @types/mock-fs to v4.13.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86e1eb70c1..7037587a67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17879,11 +17879,11 @@ __metadata: linkType: hard "@types/mock-fs@npm:^4.10.0, @types/mock-fs@npm:^4.13.0": - version: 4.13.1 - resolution: "@types/mock-fs@npm:4.13.1" + version: 4.13.2 + resolution: "@types/mock-fs@npm:4.13.2" dependencies: "@types/node": "*" - checksum: a5fcf8212daa270e6aa560019a4bd28a66e6fa49c55c1373746d5894f4aa1aafa5588335194953cf014de3c77df6be67a041fb6638ead7124307370985880b6c + checksum: 726975ae51f7b4068bb059c633ae28a1d85595d3036c235d3f9c9dc3a9c519dc6b811713af1b686807e80a484a6ec47a742a11b4ada32a6e74eee6538a9f4658 languageName: node linkType: hard From 36292f085411c91bdbabc0705efad4a13e54e939 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 14:58:30 +0000 Subject: [PATCH 033/207] chore(deps): update dependency @types/morgan to v1.9.6 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9b10f4f99a..930378e7e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17888,11 +17888,11 @@ __metadata: linkType: hard "@types/morgan@npm:^1.9.0": - version: 1.9.5 - resolution: "@types/morgan@npm:1.9.5" + version: 1.9.6 + resolution: "@types/morgan@npm:1.9.6" dependencies: "@types/node": "*" - checksum: f98deb4c7f2ad6049ad34ed7b0f0d427546bdf2358011070af9d597de1b0a03b38cc10cfe65ef2e7673e569c384303d949e76df701acefe288d547f614142973 + checksum: 6525248325a74342f929c958be69c0840c8f3a288e003a8904319cae92e531f17a8aa2700701e66775adcca7f9506dd630fec2f95dc04a3e73add04fde42aab8 languageName: node linkType: hard From 2fd3103fc84da27d9266e0b9b6aa20565722d294 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 14:59:02 +0000 Subject: [PATCH 034/207] chore(deps): update dependency @types/passport-google-oauth20 to v2.0.12 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9b10f4f99a..0f75161ae9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18042,13 +18042,13 @@ __metadata: linkType: hard "@types/passport-google-oauth20@npm:^2.0.3": - version: 2.0.11 - resolution: "@types/passport-google-oauth20@npm:2.0.11" + version: 2.0.12 + resolution: "@types/passport-google-oauth20@npm:2.0.12" dependencies: "@types/express": "*" "@types/passport": "*" "@types/passport-oauth2": "*" - checksum: 5e87a0bf40d77ce863dbcea4ae1cd6bccc663282593c9b6ce83b0e2d5d6c56ed9dc0275a04f5d81832f03b3a477fd47d17fd9b3ee22ceb69ca445ab0b0d326d7 + checksum: e73fff5b7e3191ab1a3633b05b4463d656ef658fe0612bc33517a1df81c8a1f019c91dcbd244233320f9eb133892b589dcb6a6348082e85e45aa5c6ed034d191 languageName: node linkType: hard From 2561949c4b96ad7059cf84b0a3341a5fad1dba73 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 16:13:38 +0000 Subject: [PATCH 035/207] chore(deps): update dependency @types/passport-microsoft to v1.0.1 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9b10f4f99a..5f6335b243 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18053,11 +18053,11 @@ __metadata: linkType: hard "@types/passport-microsoft@npm:^1.0.0": - version: 1.0.0 - resolution: "@types/passport-microsoft@npm:1.0.0" + version: 1.0.1 + resolution: "@types/passport-microsoft@npm:1.0.1" dependencies: "@types/passport-oauth2": "*" - checksum: d7c8b439b18cddcf707ea0c575748ecb344b6fb3c78a847aaad83246abf081c8b485efa86a3788cd5f49f4ca84a1444d813697a433fab9d04f35fb67d628cb23 + checksum: eec44ee6e14448b89434503a438021df6738513fa705b42a6d979a6b817ce89f939996a5d30707a64bca700dbc7c6ae52f1010ad2e986bb7ccd9f935d2114c9e languageName: node linkType: hard From 40203692c439a9729249c4f3081abfe5abd14621 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 16:14:09 +0000 Subject: [PATCH 036/207] chore(deps): update dependency @types/passport-saml to v1.1.4 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9b10f4f99a..6cc3ccf862 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18073,12 +18073,12 @@ __metadata: linkType: hard "@types/passport-saml@npm:^1.1.3": - version: 1.1.3 - resolution: "@types/passport-saml@npm:1.1.3" + version: 1.1.4 + resolution: "@types/passport-saml@npm:1.1.4" dependencies: "@types/express": "*" "@types/passport": "*" - checksum: 1d0abc04b1f19c043f9dd311248d3d98b00b311ed6d2cfa6cb17ef0954d0b403de4ccca4f1be192cbfda92105eb799c7963da6f39e4542ca254b06d5c467ed4a + checksum: 2a71d64c72b0f6cf4cafcc21138f5c925cc9bc375a0dd7ece664e8b1254dd4a704566632bafa3e16032821a7f010de4023169589b643a3b952709cde228a8c8c languageName: node linkType: hard From c804e45743827a67719e5c198329c54b66a92b8c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 17:13:02 +0000 Subject: [PATCH 037/207] chore(deps): update dependency @types/passport-strategy to v0.2.36 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 604a9de5b3..6dda2d5b79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18083,12 +18083,12 @@ __metadata: linkType: hard "@types/passport-strategy@npm:^0.2.35": - version: 0.2.35 - resolution: "@types/passport-strategy@npm:0.2.35" + version: 0.2.36 + resolution: "@types/passport-strategy@npm:0.2.36" dependencies: "@types/express": "*" "@types/passport": "*" - checksum: e5949063ad8977ce1f7cf2a5df6bc379c4d43a959c9946bfed6570ef379c6c12d1713212a29b3b5aafc631c5ebe9bfe082116f3e75ca1bf45d79dd889671532d + checksum: 7f626eb6a12110c1ce64dd5d5181fc0795e77d60123872e33f6fa1c02a2a19451207eaf03543232241a1d70bfe0318f2ffeef88f6309d7cbaa43d2bf6ec1d1e8 languageName: node linkType: hard From 2934320c1ffd3072c5f5256b0cefba75a81870b9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 17:13:33 +0000 Subject: [PATCH 038/207] chore(deps): update dependency @types/pg to v8.10.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 604a9de5b3..4c5d3df522 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18102,13 +18102,13 @@ __metadata: linkType: hard "@types/pg@npm:^8.6.6": - version: 8.10.2 - resolution: "@types/pg@npm:8.10.2" + version: 8.10.3 + resolution: "@types/pg@npm:8.10.3" dependencies: "@types/node": "*" pg-protocol: "*" pg-types: ^4.0.1 - checksum: 49da89f64cec1bd12a3fbc0c72b17d685c2fee579726a529f62fcab395dbc5696d80455073409947a577164b3c53a90181a331e4a5d9357679f724d4ce37f4b9 + checksum: 05a12be3f18cc67728e3aee5a7426f065351ca991e351d2e7a0562c5d9063425d67fe88fd35108834e0fa1f5624032fefbf371cf8f3cc47230a666aa953425b9 languageName: node linkType: hard From f0efaa5e06c7d5f0c9ebbea9e34e8eead62e16c4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 18:19:51 +0000 Subject: [PATCH 039/207] chore(deps): update dependency @types/ping to v0.4.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 604a9de5b3..a01abd73bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18113,9 +18113,9 @@ __metadata: linkType: hard "@types/ping@npm:^0.4.1": - version: 0.4.1 - resolution: "@types/ping@npm:0.4.1" - checksum: 9b94837fe66df70558c5a42b0e0c8371b4950ab56b96c42c8df809ff2cf52477dd0a7e01d2e6b38af8bb6683b3dcb54587960b96b4b1f3d40fdb529aea348ad0 + version: 0.4.2 + resolution: "@types/ping@npm:0.4.2" + checksum: 4ea20f8c04d6d52ac9d4a551af03b940c273616fc647d9905197400f920f744c5224ee6913ef26b845633e8e44ebab4195e4fd71daf271090336f303069b7fef languageName: node linkType: hard From ba4820883cfb128281b5204769e76d5fcb0b0816 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 18:20:14 +0000 Subject: [PATCH 040/207] chore(deps): update dependency @types/pluralize to ^0.0.31 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .changeset/renovate-a1c52e8.md | 5 +++++ plugins/cost-insights/package.json | 2 +- yarn.lock | 10 +++++----- 3 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 .changeset/renovate-a1c52e8.md diff --git a/.changeset/renovate-a1c52e8.md b/.changeset/renovate-a1c52e8.md new file mode 100644 index 0000000000..c11c866b68 --- /dev/null +++ b/.changeset/renovate-a1c52e8.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights': patch +--- + +Updated dependency `@types/pluralize` to `^0.0.31`. diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 4ff0db65f4..0f3843ddb3 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -70,7 +70,7 @@ "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", - "@types/pluralize": "^0.0.30", + "@types/pluralize": "^0.0.31", "@types/recharts": "^1.8.14", "@types/regression": "^2.0.0", "@types/yup": "^0.29.13", diff --git a/yarn.lock b/yarn.lock index 604a9de5b3..10e1503628 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6367,7 +6367,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/pluralize": ^0.0.30 + "@types/pluralize": ^0.0.31 "@types/react": ^16.13.1 || ^17.0.0 "@types/recharts": ^1.8.14 "@types/regression": ^2.0.0 @@ -18119,10 +18119,10 @@ __metadata: languageName: node linkType: hard -"@types/pluralize@npm:^0.0.30": - version: 0.0.30 - resolution: "@types/pluralize@npm:0.0.30" - checksum: 7a9a4a24aac1f74bd63e592a824ebec114486e0635a94496e92aa37fa388fac585be108d3ccfc7b2c490963679ec4900fbf394d22fa6cbf419f22cc499ab5a29 +"@types/pluralize@npm:^0.0.31": + version: 0.0.31 + resolution: "@types/pluralize@npm:0.0.31" + checksum: 950d52d8f6709cdb7001336942fba0a63bf54b45695391fc2244d03db69b0eb6f187f80519d74941f5ce1dfa900d3975f2ed52e98b1f63a79045f5c085832beb languageName: node linkType: hard From 0628445771cfc129908d2dd449e9649d2a8892b7 Mon Sep 17 00:00:00 2001 From: Valber Junior <84424883+ValberJunior@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:37:20 -0300 Subject: [PATCH 041/207] Create gitlab-pipelines.yaml Create gitlab-pipelines.yaml Signed-off-by: Valber Junior <84424883+ValberJunior@users.noreply.github.com> --- microsite/data/plugins/gitlab-pipelines.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 microsite/data/plugins/gitlab-pipelines.yaml diff --git a/microsite/data/plugins/gitlab-pipelines.yaml b/microsite/data/plugins/gitlab-pipelines.yaml new file mode 100644 index 0000000000..22f42684db --- /dev/null +++ b/microsite/data/plugins/gitlab-pipelines.yaml @@ -0,0 +1,16 @@ +--- +title: Veecode Gitlab Pipelines +author: Veecode Platform +authorUrl: https://platform.vee.codes +category: CI/CD +description: The Gitlab pipelines plugin integrates GitlabCi with its backstage component in a simple way. +documentation: https://github.com/veecode-platform/platform-backstage-plugins/tree/master/plugins/gitlab-pipelines +iconUrl: https://veecode-platform.github.io/support/imgs/logo_1.svg +npmPackageName: '@veecode-platform/backstage-plugin-gitlab-pipelines' +tags: + - ci + - cd + - gitlabCi + - pipelines + - jobs +addedDate: '2023-09-27' From 425c7c92a950404a9f3fc0dc8428c2089d2c7698 Mon Sep 17 00:00:00 2001 From: Valber Junior <84424883+ValberJunior@users.noreply.github.com> Date: Wed, 27 Sep 2023 16:09:22 -0300 Subject: [PATCH 042/207] Update and rename veecode-github-workflows.yaml to github-workflows.yaml Hello friends We've just uploaded another pull-request (#20203), a new plugin for Backstage use, which we're very excited about because we're very grateful to be able to contribute to Backstage. In order to standardize our plugins, we had to make new changes to this github plugin as well. The changes to the "github-workflows" plugin will be: - Url of the Veecode page, which now instead of being our github repository, will be our website. - The name of the file has changed slightly, taking github as the initial, so that it can be ordered next to the github plugins that already exist. Thanks to everyone Signed-off-by: Valber Junior <84424883+ValberJunior@users.noreply.github.com> --- .../{veecode-github-workflows.yaml => github-workflows.yaml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename microsite/data/plugins/{veecode-github-workflows.yaml => github-workflows.yaml} (92%) diff --git a/microsite/data/plugins/veecode-github-workflows.yaml b/microsite/data/plugins/github-workflows.yaml similarity index 92% rename from microsite/data/plugins/veecode-github-workflows.yaml rename to microsite/data/plugins/github-workflows.yaml index cd518dd8b8..de17a218b6 100644 --- a/microsite/data/plugins/veecode-github-workflows.yaml +++ b/microsite/data/plugins/github-workflows.yaml @@ -1,7 +1,7 @@ --- title: Veecode GitHub Workflows author: Veecode Platform -authorUrl: https://github.com/veecode-platform +authorUrl: https://platform.vee.codes/ category: CI/CD description: The Github Workflows plugin provides an alternative for manually triggering GitHub workflows from within your Backstage component. documentation: https://github.com/veecode-platform/platform-backstage-plugins/tree/master/plugins/github-workflows From 6779d722cdb3883bf27e88777a21e97cbb2cece6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 19:39:57 +0000 Subject: [PATCH 043/207] chore(deps): update dependency @types/prop-types to v15.7.7 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6f1a40c8c5..0ecb8f0d01 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18134,9 +18134,9 @@ __metadata: linkType: hard "@types/prop-types@npm:*, @types/prop-types@npm:^15.0.0, @types/prop-types@npm:^15.7.3, @types/prop-types@npm:^15.7.5": - version: 15.7.6 - resolution: "@types/prop-types@npm:15.7.6" - checksum: 5f2796c7330461a556c4d18035fb914b372f96b1619a4f8302d07e1ea708e06a2dbe666dfcd8ff03f64c625aa4c12b31f677d0298a32910f5ab7ee51521d8086 + version: 15.7.7 + resolution: "@types/prop-types@npm:15.7.7" + checksum: 023b95f7dd82e1c594f51dcb93ec4c382600cef6eeee29a2ac7b782b92c0882eab8da16d4cbd6e18b39e85ac8d94ebf4ca02c6e248ce5b5fb4b16dbab5d82861 languageName: node linkType: hard From beb4a92f004e1f31971792b22de12ed9b99b228c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 19:40:28 +0000 Subject: [PATCH 044/207] chore(deps): update dependency @types/react-helmet to v6.1.7 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6f1a40c8c5..2b775eb191 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18191,11 +18191,11 @@ __metadata: linkType: hard "@types/react-helmet@npm:^6.1.0": - version: 6.1.6 - resolution: "@types/react-helmet@npm:6.1.6" + version: 6.1.7 + resolution: "@types/react-helmet@npm:6.1.7" dependencies: "@types/react": "*" - checksum: 81560c56bfe854b6a43aee31360862588ac875d1177b975da5ce049ac9aa2f7c98dcde65d4397bfaa04e468f40cf3ab2975a2ef966a69d64a60493422898698d + checksum: d5ee8343f10f8746a022249c6401493baa73241a90b5002b59e8a6ce31650b9e1ab38d398eba5564af026f68eda107c8fcdca01fc046a163a96dc422710f6a77 languageName: node linkType: hard From 360cc71a25bab2e6e99e0e4be8052df62b4654ff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 21:08:26 +0000 Subject: [PATCH 045/207] chore(deps): update dependency @types/jquery to v3.5.20 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6f1a40c8c5..03066112cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17633,11 +17633,11 @@ __metadata: linkType: hard "@types/jquery@npm:^3.3.34": - version: 3.5.19 - resolution: "@types/jquery@npm:3.5.19" + version: 3.5.20 + resolution: "@types/jquery@npm:3.5.20" dependencies: "@types/sizzle": "*" - checksum: 0298e53a353089e2abae4be2f660b5f2bfb4797464623701c5c2f2c911317b554f1887c2c3d587d0f724d70a3fb5e31907bf7fa5d96df33af07e2842660ef52a + checksum: 9bd69faea3d60f52d3029a87b890003042a9dcf4f538c23ac2c11b3bd0e0ccd86b281d5ba3028d1b02df67c69266b8dc0ef0a35696ae174515ecf34523a0287b languageName: node linkType: hard From 8a4145a6b16bf26cc4b9b3759e60f7bf5f8b7547 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 21:08:58 +0000 Subject: [PATCH 046/207] chore(deps): update dependency @types/react-window to v1.8.6 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6f1a40c8c5..1a5897feb2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18266,11 +18266,11 @@ __metadata: linkType: hard "@types/react-window@npm:^1.8.5": - version: 1.8.5 - resolution: "@types/react-window@npm:1.8.5" + version: 1.8.6 + resolution: "@types/react-window@npm:1.8.6" dependencies: "@types/react": "*" - checksum: 5f519e1402300d11b6e6595223feb6499f3227e38da166cbc565773cd7f71862abcf855b7835d391b5119fcfacdfba79d73a965b45f60a293fc1ff25986319ed + checksum: 3084190ab50a84d8499a6df574ad67474566cd7aeeb8fc6ce82a7a13421fd39e21a059c51f9d12f38e5ac52eb9d65f6184e3fb6cb62841e93b197b7401b36e35 languageName: node linkType: hard From b809095e82ba1dedddba4dee257b5b1d122c85e5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 01:31:41 +0000 Subject: [PATCH 047/207] chore(deps): update dependency @types/recharts to v1.8.25 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6f1a40c8c5..ac63e97613 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18295,12 +18295,12 @@ __metadata: linkType: hard "@types/recharts@npm:^1.8.14, @types/recharts@npm:^1.8.15": - version: 1.8.24 - resolution: "@types/recharts@npm:1.8.24" + version: 1.8.25 + resolution: "@types/recharts@npm:1.8.25" dependencies: "@types/d3-shape": ^1 "@types/react": "*" - checksum: 1341e5472bf62a83ab98648bc5c14a9a81fba16af9255203ef12a21caa21a988fac3198d9771703394eb876d4fbefb42e818865e35ecfe0d105aee1d1164aa6e + checksum: b2ab1596f391b70e349ae5f6fc6b29c16f6298f1151747aff84b3380f4644c4e087a489ca55325dc627794317f8e677c9906ab75d2e270c79e45da976a347af5 languageName: node linkType: hard From 5370fe5446f43efa0042a3495cc131ce6a526245 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 01:32:14 +0000 Subject: [PATCH 048/207] chore(deps): update dependency @types/recursive-readdir to v2.2.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6f1a40c8c5..64548244f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18305,11 +18305,11 @@ __metadata: linkType: hard "@types/recursive-readdir@npm:^2.2.0": - version: 2.2.1 - resolution: "@types/recursive-readdir@npm:2.2.1" + version: 2.2.2 + resolution: "@types/recursive-readdir@npm:2.2.2" dependencies: "@types/node": "*" - checksum: 9e8d5ecb98c009016bf65f1b7cc1f997847dc64634e1c4209fae10718a1fcecd3c3a72c4bae66cbc9973165da5e4e7f5b4cda8793b3a5cefca8c05963f6dbf82 + checksum: ed7f73d11354c7df7c5296a73500ace0b9874083c9f9cce4c5a294bb6c9b11f92d25c08a23bdc991f0537358d31e2ae3943169d42fe739ff54ecfddf9ff6b420 languageName: node linkType: hard From 308b5f728731ad1ddbb3391d36f97b63ed3569d4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 04:29:35 +0000 Subject: [PATCH 049/207] chore(deps): update dependency @types/regression to v2.0.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6f1a40c8c5..2f4bd2b9d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18314,9 +18314,9 @@ __metadata: linkType: hard "@types/regression@npm:^2.0.0": - version: 2.0.2 - resolution: "@types/regression@npm:2.0.2" - checksum: 28ae464c5ffda1698cecf1b1c2e21ed016ae1d71623c7f40bc5404aa55569cca03ac33d29737805059851cc734946027b006858d13a642e12240267c96d49299 + version: 2.0.3 + resolution: "@types/regression@npm:2.0.3" + checksum: 774ef76911225b61c44946573b54ab710401d0e65b9433aa7014c701272167c47e818d4c9809284514881837c2159cd47aad6b290f00f8581920f2c7a146a512 languageName: node linkType: hard From 4757e81c04bbda94d4507bb8fd1770e2188d1771 Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Thu, 28 Sep 2023 10:32:14 +0100 Subject: [PATCH 050/207] Transfering ownership of Spotify's internal instance of Bacsktage to Helen Greul Signed-off-by: Lee Mills --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index 958d24b968..f03ed8d270 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -5,7 +5,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | Organization | Contact | Description of Use | |-----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. | +| [Spotify](https://www.spotify.com) | [@helengreul](https://github.com/helengreul) | Main interface towards all of Spotify's infrastructure and technical documentation. | | [bol.com](https://www.bol.com) | [@acierto](https://github.com/acierto), [@clanghout](https://github.com/clanghout) | Initial work being done to unify platform tooling. | | [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. | | [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up | From 086b5ccabcc8512aff95c176d68a04341a49651b Mon Sep 17 00:00:00 2001 From: Federico Morreale Date: Thu, 28 Sep 2023 11:44:56 +0200 Subject: [PATCH 051/207] fix: action buttons are now responsive Signed-off-by: Federico Morreale --- microsite/src/components/contentBlock/contentBlock.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/microsite/src/components/contentBlock/contentBlock.tsx b/microsite/src/components/contentBlock/contentBlock.tsx index 983f684927..5c3e47fe74 100644 --- a/microsite/src/components/contentBlock/contentBlock.tsx +++ b/microsite/src/components/contentBlock/contentBlock.tsx @@ -37,7 +37,14 @@ export const ContentBlock = ({ {children && React.isValidElement(children) ? children :

{children}

} {actionButtons && ( -
+
{actionButtons.map(({ link, label }, index) => ( Date: Thu, 28 Sep 2023 10:52:49 +0100 Subject: [PATCH 052/207] Proposing Helen Gruel to take up role as End User Sponsor Signed-off-by: Lee Mills --- OWNERS.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/OWNERS.md b/OWNERS.md index 6c26078f8c..3681741040 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -118,11 +118,12 @@ Scope: Tooling for frontend and backend schema-first OpenAPI development. ## Sponsors -| Name | Organization | GitHub | Email | -| ----------------- | ------------ | ------------------------------------------- | ----------------- | -| Niklas Gustavsson | Spotify | [protocol7](https://github.com/protocol7) | ngn@spotify.com | -| Dave Zolotusky | Spotify | [dzolotusky](https://github.com/dzolotusky) | dzolo@spotify.com | -| Lee Mills | Spotify | [leemills83](https://github.com/leemills83) | leem@spotify.com | +| Name | Organization | GitHub | Email | +| ----------------- | ------------ | ------------------------------------------- | ------------------ | +| Niklas Gustavsson | Spotify | [protocol7](https://github.com/protocol7) | ngn@spotify.com | +| Dave Zolotusky | Spotify | [dzolotusky](https://github.com/dzolotusky) | dzolo@spotify.com | +| Helen Gruel | Spotify | [helengruel](https://github.com/dzolotusky) | heleng@spotify.com | +| Lee Mills | Spotify | [leemills83](https://github.com/leemills83) | leem@spotify.com | ## Organization Members From c2ca5fe56d7b535c78f4746cd5783d5ae0c0ab21 Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Thu, 28 Sep 2023 10:57:50 +0100 Subject: [PATCH 053/207] Removing myself from End Users Sponsors to Emeritus status Signed-off-by: Lee Mills --- OWNERS.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OWNERS.md b/OWNERS.md index 3681741040..5e2dbf07c0 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -123,7 +123,6 @@ Scope: Tooling for frontend and backend schema-first OpenAPI development. | Niklas Gustavsson | Spotify | [protocol7](https://github.com/protocol7) | ngn@spotify.com | | Dave Zolotusky | Spotify | [dzolotusky](https://github.com/dzolotusky) | dzolo@spotify.com | | Helen Gruel | Spotify | [helengruel](https://github.com/dzolotusky) | heleng@spotify.com | -| Lee Mills | Spotify | [leemills83](https://github.com/leemills83) | leem@spotify.com | ## Organization Members @@ -153,3 +152,9 @@ Scope: Tooling for frontend and backend schema-first OpenAPI development. | Maintainer | Organization | GitHub | Discord | | ------------ | ------------ | --------------------------------------------- | -------------- | | Stefan Ålund | Spotify | [stefanalund](https://github.com/stefanalund) | `stalund#9602` | + +## Emeritus End User Sponsors + +| Name | Organization | GitHub | Discord | +| --------- | ------------ | ------------------------------------------- | -------------- | +| Lee Mills | Spotify | [leemills83](https://github.com/leemills83) | `.binarypoint` | From 569b3927cad456898eceacf7edcab81e05268450 Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Thu, 28 Sep 2023 11:03:35 +0100 Subject: [PATCH 054/207] Update OWNERS.md Co-authored-by: Vincenzo Scamporlino Signed-off-by: Lee Mills Signed-off-by: Lee Mills --- OWNERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OWNERS.md b/OWNERS.md index 5e2dbf07c0..4d09c29f0f 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -122,7 +122,7 @@ Scope: Tooling for frontend and backend schema-first OpenAPI development. | ----------------- | ------------ | ------------------------------------------- | ------------------ | | Niklas Gustavsson | Spotify | [protocol7](https://github.com/protocol7) | ngn@spotify.com | | Dave Zolotusky | Spotify | [dzolotusky](https://github.com/dzolotusky) | dzolo@spotify.com | -| Helen Gruel | Spotify | [helengruel](https://github.com/dzolotusky) | heleng@spotify.com | +| Helen Greul | Spotify | [helengreul](https://github.com/helengreul) | heleng@spotify.com | ## Organization Members From a6e09d8712ef784817847c96e367df62886f50d3 Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Thu, 28 Sep 2023 13:43:41 +0200 Subject: [PATCH 055/207] Fixed documentation mistake on configuring routes Signed-off-by: Jasper Boeijenga --- docs/plugins/plugin-development.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plugins/plugin-development.md b/docs/plugins/plugin-development.md index 100f9012be..8d8db8c387 100644 --- a/docs/plugins/plugin-development.md +++ b/docs/plugins/plugin-development.md @@ -79,5 +79,5 @@ This extension can then be imported and used in the app as follow, typically placed within the top-level ``: ```tsx -} /> +} /> ``` From 892423c9407898dd0a725eb5793c881974596198 Mon Sep 17 00:00:00 2001 From: Federico Morreale Date: Thu, 28 Sep 2023 14:48:12 +0200 Subject: [PATCH 056/207] fix: watch now button not displayed if link is undefined Signed-off-by: Federico Morreale --- microsite/src/pages/demos/index.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/microsite/src/pages/demos/index.tsx b/microsite/src/pages/demos/index.tsx index 1221c38a63..e3b4b7dbfd 100644 --- a/microsite/src/pages/demos/index.tsx +++ b/microsite/src/pages/demos/index.tsx @@ -175,12 +175,16 @@ const Demos = () => { {demoItem.title}} - actionButtons={[ - { - link: demoItem.actionItemLink, - label: 'WATCH NOW', - }, - ]} + actionButtons={ + demoItem.actionItemLink + ? [ + { + link: demoItem.actionItemLink, + label: 'WATCH NOW', + }, + ] + : [] + } > {demoItem.content} From 3b148d7bcf3d29357c9e869a7ec4a33b03bdb809 Mon Sep 17 00:00:00 2001 From: Federico Morreale Date: Thu, 28 Sep 2023 15:07:21 +0200 Subject: [PATCH 057/207] fix: update year in the footer Signed-off-by: Federico Morreale --- microsite/docusaurus.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/docusaurus.config.js b/microsite/docusaurus.config.js index a7df33623a..1879e35e72 100644 --- a/microsite/docusaurus.config.js +++ b/microsite/docusaurus.config.js @@ -276,7 +276,7 @@ module.exports = { }, ], copyright: - '

Made with ❤️ at Spotify

', + '

Made with ❤️ at Spotify

', }, algolia: { apiKey: '1f0ba86672ccfc3576faa94583e5b318', From 24d9f44ccb12942cc9ddd77a7df2d7dfbe338762 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Sat, 23 Sep 2023 11:41:08 +0200 Subject: [PATCH 058/207] chore(search-react): configure alpha subpath Signed-off-by: Camila Belo --- plugins/search-react/package.json | 19 ++++++++++++++++--- plugins/search-react/src/alpha.ts | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 plugins/search-react/src/alpha.ts diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 4454d44574..6255ccb0ff 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -5,9 +5,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "web-library" diff --git a/plugins/search-react/src/alpha.ts b/plugins/search-react/src/alpha.ts new file mode 100644 index 0000000000..eb2f165350 --- /dev/null +++ b/plugins/search-react/src/alpha.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ From b54222b62d6a7bfbcb79f2aa3459ae35978efa96 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 25 Sep 2023 08:47:36 +0200 Subject: [PATCH 059/207] feat(search-react): create search result item extension Signed-off-by: Camila Belo --- plugins/search-react/package.json | 2 + plugins/search-react/src/alpha.ts | 2 + plugins/search-react/src/extensions.tsx | 4 +- ...eateSearchResultListItemExtension.test.tsx | 175 ++++++++++++++++++ .../createSearchResultListItemExtension.tsx | 111 +++++++++++ plugins/search-react/src/wiring/index.ts | 17 ++ yarn.lock | 2 + 7 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx create mode 100644 plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx create mode 100644 plugins/search-react/src/wiring/index.ts diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 6255ccb0ff..31e12db763 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -47,6 +47,8 @@ "dependencies": { "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-app-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "@backstage/theme": "workspace:^", "@backstage/types": "workspace:^", diff --git a/plugins/search-react/src/alpha.ts b/plugins/search-react/src/alpha.ts index eb2f165350..e006e249eb 100644 --- a/plugins/search-react/src/alpha.ts +++ b/plugins/search-react/src/alpha.ts @@ -13,3 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +export * from './wiring'; diff --git a/plugins/search-react/src/extensions.tsx b/plugins/search-react/src/extensions.tsx index a29311b1ff..5cd0aab76e 100644 --- a/plugins/search-react/src/extensions.tsx +++ b/plugins/search-react/src/extensions.tsx @@ -86,11 +86,11 @@ export type SearchResultListItemExtensionProps = Props & >; /** - * @internal + * @public * Extends children with extension capabilities. * @param props - see {@link SearchResultListItemExtensionProps}. */ -const SearchResultListItemExtension = ( +export const SearchResultListItemExtension = ( props: SearchResultListItemExtensionProps, ) => { const { diff --git a/plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx b/plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx new file mode 100644 index 0000000000..d7a2947e1f --- /dev/null +++ b/plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx @@ -0,0 +1,175 @@ +/* + * 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 { render, screen } from '@testing-library/react'; + +import { + createExtensionInput, + createPageExtension, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { SearchResult } from '@backstage/plugin-search-common'; +import { createApp } from '@backstage/frontend-app-api'; +import { MockConfigApi } from '@backstage/test-utils'; + +import { + BaseSearchResultListItemProps, + createSearchResultListItemExtension, + searchResultItemExtensionData, +} from './createSearchResultListItemExtension'; + +// TODO: Remove this mock when we have a permanent solution for nav items extensions +// The `GraphiQLIcon` used in "packages/frontend-app-api/src/extensions/CoreNav.tsx" file +// is throwing a "ReferenceError: ref is not defined" error during test +jest.mock('@backstage/plugin-graphiql', () => ({ + ...jest.requireActual('@backstage/plugin-graphiql'), + GraphiQLIcon: () => null, +})); + +describe('createSearchResultListItemExtension', () => { + it('Should use the correct result component', async () => { + const TechDocsSearchResultItemComponent = ( + props: BaseSearchResultListItemProps, + ) =>
TechDocs - Rank: {props.rank}
; + + const TechDocsSearchResultItemExtension = + createSearchResultListItemExtension({ + id: 'techdocs', + at: 'plugin.search.page/items', + predicate: result => result.type === 'techdocs', + component: async () => TechDocsSearchResultItemComponent, + }); + + const ExploreSearchResultItemComponent = ( + props: BaseSearchResultListItemProps, + ) =>
Explore - Rank: {props.rank}
; + + const ExploreSearchResultItemExtension = + createSearchResultListItemExtension({ + id: 'explore', + at: 'plugin.search.page/items', + predicate: result => result.type === 'explore', + component: async () => ExploreSearchResultItemComponent, + }); + + const SearchPageExtension = createPageExtension({ + id: 'plugin.search.page', + defaultPath: '/', + inputs: { + items: createExtensionInput({ + item: searchResultItemExtensionData, + }), + }, + loader: async ({ inputs }) => { + const results = [ + { + type: 'techdocs', + rank: 1, + document: { + title: 'Title1', + text: 'Text1', + location: '/location1', + }, + }, + { + type: 'explore', + rank: 2, + document: { + title: 'Title2', + text: 'Text2', + location: '/location2', + }, + }, + { + type: 'other', + rank: 3, + document: { + title: 'Title3', + text: 'Text3', + location: '/location3', + }, + }, + ]; + + const DefaultResultItem = (props: BaseSearchResultListItemProps) => ( +
Default - Rank: {props.rank}
+ ); + + const getResultItemComponent = (result: SearchResult) => { + const value = inputs.items.find(({ item }) => + item?.predicate?.(result), + ); + return value?.item.component ?? DefaultResultItem; + }; + + const Component = () => { + return ( +
+

Search Page

+
    + {results.map((result, index) => { + const SearchResultListItem = getResultItemComponent(result); + return ( + + ); + })} +
+
+ ); + }; + + return ; + }, + }); + + const SearchPlugin = createPlugin({ + id: 'search.plugin', + extensions: [ + SearchPageExtension, + ExploreSearchResultItemExtension, + TechDocsSearchResultItemExtension, + ], + }); + + const app = createApp({ + plugins: [SearchPlugin], + configLoader: async () => new MockConfigApi({}), + }); + + render(app.createRoot()); + + expect(await screen.findByText(/Search Page/)).toBeInTheDocument(); + + expect( + await screen.findByText(/TechDocs - Rank: 1/, { exact: false }), + ).toBeInTheDocument(); + + expect( + await screen.findByText(/Explore - Rank: 2/, { exact: false }), + ).toBeInTheDocument(); + + expect( + await screen.findByText(/Default - Rank: 3/, { exact: false }), + ).toBeInTheDocument(); + }); +}); diff --git a/plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx b/plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx new file mode 100644 index 0000000000..4ad0e54e1f --- /dev/null +++ b/plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx @@ -0,0 +1,111 @@ +/* + * 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, { lazy, Suspense } from 'react'; + +import { ListItemProps } from '@material-ui/core'; + +import { + ExtensionBoundary, + createExtension, + createExtensionDataRef, +} from '@backstage/frontend-plugin-api'; +import { Progress } from '@backstage/core-components'; +import { SearchDocument, SearchResult } from '@backstage/plugin-search-common'; + +import { SearchResultListItemExtension } from '../extensions'; + +/** @alpha */ +export type SearchResultItemExtensionComponent = < + P extends BaseSearchResultListItemProps, +>( + props: P, +) => JSX.Element | null; + +/** @alpha */ +export type SearchResultItemExtensionPredicate = ( + result: SearchResult, +) => boolean; + +/** @alpha */ +export const searchResultItemExtensionData = createExtensionDataRef<{ + predicate?: SearchResultItemExtensionPredicate; + component: SearchResultItemExtensionComponent; +}>('plugin.search.result.item.data'); + +/** @alpha */ +export type SearchResultItemExtensionOptions = { + /** + * The extension id. + */ + id: string; + /** + * The extension attachment point (e.g., search modal or page). + */ + at: string; + /** + * The extension component. + */ + component: () => Promise; + /** + * When an extension defines a predicate, it returns true if the result should be rendered by that extension. + * Defaults to a predicate that returns true, which means it renders all sorts of results. + */ + predicate?: SearchResultItemExtensionPredicate; +}; + +/** @alpha */ +export type BaseSearchResultListItemProps = { + rank?: number; + result?: SearchDocument; + noTrack?: boolean; +} & Omit; + +/** @alpha */ +export const createSearchResultListItemExtension = ( + options: SearchResultItemExtensionOptions, +) => + createExtension({ + id: `plugin.search.result.item.${options.id}`, + at: options.at, + output: { + item: searchResultItemExtensionData, + }, + factory({ bind, source }) { + const LazyComponent = lazy(() => + options.component().then(component => ({ default: component })), + ) as unknown as SearchResultItemExtensionComponent; + + bind({ + item: { + predicate: options.predicate, + component: props => ( + + }> + + + + + + ), + }, + }); + }, + }); diff --git a/plugins/search-react/src/wiring/index.ts b/plugins/search-react/src/wiring/index.ts new file mode 100644 index 0000000000..7cf5b0d6f5 --- /dev/null +++ b/plugins/search-react/src/wiring/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 * from './createSearchResultListItemExtension'; diff --git a/yarn.lock b/yarn.lock index 6f1a40c8c5..e429806816 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9079,6 +9079,8 @@ __metadata: "@backstage/core-app-api": "workspace:^" "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" + "@backstage/frontend-app-api": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-search-common": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" From 0639f2840abaa7f1fce0d2c5d9bdb115aa9e3c39 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 25 Sep 2023 23:37:51 +0200 Subject: [PATCH 060/207] chore(search-react): update api reports Signed-off-by: Camila Belo --- plugins/search-react/alpha-api-report.md | 56 ++++++++++++++++++++++++ plugins/search-react/api-report.md | 5 +++ 2 files changed, 61 insertions(+) create mode 100644 plugins/search-react/alpha-api-report.md diff --git a/plugins/search-react/alpha-api-report.md b/plugins/search-react/alpha-api-report.md new file mode 100644 index 0000000000..90492f9434 --- /dev/null +++ b/plugins/search-react/alpha-api-report.md @@ -0,0 +1,56 @@ +## API Report File for "@backstage/plugin-search-react" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; +import { Extension } from '@backstage/frontend-plugin-api'; +import { ListItemProps } from '@material-ui/core'; +import { SearchDocument } from '@backstage/plugin-search-common'; +import { SearchResult } from '@backstage/plugin-search-common'; + +// @alpha (undocumented) +export type BaseSearchResultListItemProps = { + rank?: number; + result?: SearchDocument; + noTrack?: boolean; +} & Omit; + +// @alpha (undocumented) +export const createSearchResultListItemExtension: ( + options: SearchResultItemExtensionOptions, +) => Extension; + +// @alpha (undocumented) +export type SearchResultItemExtensionComponent = < + P extends BaseSearchResultListItemProps, +>( + props: P, +) => JSX.Element | null; + +// @alpha (undocumented) +export const searchResultItemExtensionData: ConfigurableExtensionDataRef< + { + predicate?: SearchResultItemExtensionPredicate | undefined; + component: SearchResultItemExtensionComponent; + }, + {} +>; + +// @alpha (undocumented) +export type SearchResultItemExtensionOptions = { + id: string; + at: string; + component: () => Promise; + predicate?: SearchResultItemExtensionPredicate; +}; + +// @alpha (undocumented) +export type SearchResultItemExtensionPredicate = ( + result: SearchResult, +) => boolean; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index 97c8300c14..21dd6135a9 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/api-report.md @@ -391,6 +391,11 @@ export const SearchResultList: ( props: SearchResultListProps, ) => React_2.JSX.Element; +// @public +export const SearchResultListItemExtension: ( + props: SearchResultListItemExtensionProps, +) => React_2.JSX.Element; + // @public export type SearchResultListItemExtensionOptions< Component extends (props: any) => JSX.Element | null, From 703a4ffc5beec70c7d6b013f8d421627ef2cf440 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 00:01:56 +0200 Subject: [PATCH 061/207] chore(search-react): add changeset file Signed-off-by: Camila Belo --- .changeset/wicked-rings-flash.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/wicked-rings-flash.md diff --git a/.changeset/wicked-rings-flash.md b/.changeset/wicked-rings-flash.md new file mode 100644 index 0000000000..b872c0c71f --- /dev/null +++ b/.changeset/wicked-rings-flash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +Create `createSearchResultListItem` alpha version that only supports declarative integration. From 184be50385cf98e32b3bf5c5593b7d035510f75a Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 27 Sep 2023 14:29:54 +0200 Subject: [PATCH 062/207] refactor(search-react): apply review suggestions Signed-off-by: Camila Belo --- plugins/search-react/alpha-api-report.md | 23 +++++++--- plugins/search-react/api-report.md | 5 --- plugins/search-react/src/extensions.tsx | 2 +- ...eateSearchResultListItemExtension.test.tsx | 43 ++++++++++++++++--- .../createSearchResultListItemExtension.tsx | 43 ++++++++++++++----- 5 files changed, 86 insertions(+), 30 deletions(-) diff --git a/plugins/search-react/alpha-api-report.md b/plugins/search-react/alpha-api-report.md index 90492f9434..163247bf5e 100644 --- a/plugins/search-react/alpha-api-report.md +++ b/plugins/search-react/alpha-api-report.md @@ -8,20 +8,22 @@ import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; import { ListItemProps } from '@material-ui/core'; +import { PortableSchema } from '@backstage/frontend-plugin-api'; import { SearchDocument } from '@backstage/plugin-search-common'; import { SearchResult } from '@backstage/plugin-search-common'; // @alpha (undocumented) -export type BaseSearchResultListItemProps = { +export type BaseSearchResultListItemProps = T & { rank?: number; result?: SearchDocument; - noTrack?: boolean; } & Omit; // @alpha (undocumented) -export const createSearchResultListItemExtension: ( - options: SearchResultItemExtensionOptions, -) => Extension; +export function createSearchResultListItemExtension< + TConfig extends { + noTrack?: boolean; + }, +>(options: SearchResultItemExtensionOptions): Extension; // @alpha (undocumented) export type SearchResultItemExtensionComponent = < @@ -40,10 +42,17 @@ export const searchResultItemExtensionData: ConfigurableExtensionDataRef< >; // @alpha (undocumented) -export type SearchResultItemExtensionOptions = { +export type SearchResultItemExtensionOptions< + TConfig extends { + noTrack?: boolean; + }, +> = { id: string; at: string; - component: () => Promise; + configSchema?: PortableSchema; + component: (options: { + config: TConfig; + }) => Promise; predicate?: SearchResultItemExtensionPredicate; }; diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index 21dd6135a9..97c8300c14 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/api-report.md @@ -391,11 +391,6 @@ export const SearchResultList: ( props: SearchResultListProps, ) => React_2.JSX.Element; -// @public -export const SearchResultListItemExtension: ( - props: SearchResultListItemExtensionProps, -) => React_2.JSX.Element; - // @public export type SearchResultListItemExtensionOptions< Component extends (props: any) => JSX.Element | null, diff --git a/plugins/search-react/src/extensions.tsx b/plugins/search-react/src/extensions.tsx index 5cd0aab76e..132fad25b5 100644 --- a/plugins/search-react/src/extensions.tsx +++ b/plugins/search-react/src/extensions.tsx @@ -86,7 +86,7 @@ export type SearchResultListItemExtensionProps = Props & >; /** - * @public + * @internal * Extends children with extension capabilities. * @param props - see {@link SearchResultListItemExtensionProps}. */ diff --git a/plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx b/plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx index d7a2947e1f..ca0e7e0672 100644 --- a/plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx +++ b/plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx @@ -22,6 +22,7 @@ import { createExtensionInput, createPageExtension, createPlugin, + createSchemaFromZod, } from '@backstage/frontend-plugin-api'; import { SearchResult } from '@backstage/plugin-search-common'; import { createApp } from '@backstage/frontend-app-api'; @@ -43,16 +44,32 @@ jest.mock('@backstage/plugin-graphiql', () => ({ describe('createSearchResultListItemExtension', () => { it('Should use the correct result component', async () => { + type TechDocsSearchReasulListItemProps = BaseSearchResultListItemProps<{ + lineClamp: number; + }>; const TechDocsSearchResultItemComponent = ( - props: BaseSearchResultListItemProps, - ) =>
TechDocs - Rank: {props.rank}
; + props: TechDocsSearchReasulListItemProps, + ) => ( +
+ TechDocs - Rank: {props.rank} - Line clamp: {props.lineClamp} +
+ ); const TechDocsSearchResultItemExtension = createSearchResultListItemExtension({ id: 'techdocs', at: 'plugin.search.page/items', + configSchema: createSchemaFromZod(z => + z.object({ + noTrack: z.boolean().default(true), + lineClamp: z.number().default(5), + }), + ), predicate: result => result.type === 'techdocs', - component: async () => TechDocsSearchResultItemComponent, + component: + async ({ config }) => + props => + , }); const ExploreSearchResultItemComponent = ( @@ -129,7 +146,6 @@ describe('createSearchResultListItemExtension', () => { key={index} rank={result.rank} result={result.document} - noTrack /> ); })} @@ -153,7 +169,20 @@ describe('createSearchResultListItemExtension', () => { const app = createApp({ plugins: [SearchPlugin], - configLoader: async () => new MockConfigApi({}), + configLoader: async () => + new MockConfigApi({ + app: { + extensions: [ + { + 'plugin.search.result.item.techdocs': { + config: { + lineClamp: 3, + }, + }, + }, + ], + }, + }), }); render(app.createRoot()); @@ -161,7 +190,9 @@ describe('createSearchResultListItemExtension', () => { expect(await screen.findByText(/Search Page/)).toBeInTheDocument(); expect( - await screen.findByText(/TechDocs - Rank: 1/, { exact: false }), + await screen.findByText(/TechDocs - Rank: 1 - Line clamp: 3/, { + exact: false, + }), ).toBeInTheDocument(); expect( diff --git a/plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx b/plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx index 4ad0e54e1f..b276c5e60a 100644 --- a/plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx +++ b/plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx @@ -20,8 +20,10 @@ import { ListItemProps } from '@material-ui/core'; import { ExtensionBoundary, + PortableSchema, createExtension, createExtensionDataRef, + createSchemaFromZod, } from '@backstage/frontend-plugin-api'; import { Progress } from '@backstage/core-components'; import { SearchDocument, SearchResult } from '@backstage/plugin-search-common'; @@ -47,7 +49,9 @@ export const searchResultItemExtensionData = createExtensionDataRef<{ }>('plugin.search.result.item.data'); /** @alpha */ -export type SearchResultItemExtensionOptions = { +export type SearchResultItemExtensionOptions< + TConfig extends { noTrack?: boolean }, +> = { /** * The extension id. */ @@ -56,10 +60,16 @@ export type SearchResultItemExtensionOptions = { * The extension attachment point (e.g., search modal or page). */ at: string; + /** + * Optional extension config schema. + */ + configSchema?: PortableSchema; /** * The extension component. */ - component: () => Promise; + component: (options: { + config: TConfig; + }) => Promise; /** * When an extension defines a predicate, it returns true if the result should be rendered by that extension. * Defaults to a predicate that returns true, which means it renders all sorts of results. @@ -68,25 +78,35 @@ export type SearchResultItemExtensionOptions = { }; /** @alpha */ -export type BaseSearchResultListItemProps = { +export type BaseSearchResultListItemProps = T & { rank?: number; result?: SearchDocument; - noTrack?: boolean; } & Omit; /** @alpha */ -export const createSearchResultListItemExtension = ( - options: SearchResultItemExtensionOptions, -) => - createExtension({ +export function createSearchResultListItemExtension< + TConfig extends { noTrack?: boolean }, +>(options: SearchResultItemExtensionOptions) { + const configSchema = + 'configSchema' in options + ? options.configSchema + : (createSchemaFromZod(z => + z.object({ + noTrack: z.boolean().default(true), + }), + ) as PortableSchema); + return createExtension({ id: `plugin.search.result.item.${options.id}`, at: options.at, + configSchema, output: { item: searchResultItemExtensionData, }, - factory({ bind, source }) { + factory({ bind, config, source }) { const LazyComponent = lazy(() => - options.component().then(component => ({ default: component })), + options + .component({ config }) + .then(component => ({ default: component })), ) as unknown as SearchResultItemExtensionComponent; bind({ @@ -98,7 +118,7 @@ export const createSearchResultListItemExtension = ( @@ -109,3 +129,4 @@ export const createSearchResultListItemExtension = ( }); }, }); +} From d36f92de248c885544e900a9ac4907ef06975dd3 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 28 Sep 2023 09:37:16 +0200 Subject: [PATCH 063/207] refactor(search-react): move everything to alpha file Signed-off-by: Camila Belo --- plugins/search-react/package.json | 4 ++-- ...istItemExtension.test.tsx => alpha.test.tsx} | 6 +++--- plugins/search-react/src/alpha.ts | 17 ----------------- ...rchResultListItemExtension.tsx => alpha.tsx} | 16 ++++++++-------- plugins/search-react/src/wiring/index.ts | 17 ----------------- 5 files changed, 13 insertions(+), 47 deletions(-) rename plugins/search-react/src/{wiring/createSearchResultListItemExtension.test.tsx => alpha.test.tsx} (97%) delete mode 100644 plugins/search-react/src/alpha.ts rename plugins/search-react/src/{wiring/createSearchResultListItemExtension.tsx => alpha.tsx} (97%) delete mode 100644 plugins/search-react/src/wiring/index.ts diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 31e12db763..da4092fcbd 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -9,13 +9,13 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", + "./alpha": "./src/alpha.tsx", "./package.json": "./package.json" }, "typesVersions": { "*": { "alpha": [ - "src/alpha.ts" + "src/alpha.tsx" ], "package.json": [ "package.json" diff --git a/plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx b/plugins/search-react/src/alpha.test.tsx similarity index 97% rename from plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx rename to plugins/search-react/src/alpha.test.tsx index ca0e7e0672..b61a400832 100644 --- a/plugins/search-react/src/wiring/createSearchResultListItemExtension.test.tsx +++ b/plugins/search-react/src/alpha.test.tsx @@ -31,8 +31,8 @@ import { MockConfigApi } from '@backstage/test-utils'; import { BaseSearchResultListItemProps, createSearchResultListItemExtension, - searchResultItemExtensionData, -} from './createSearchResultListItemExtension'; + searchResultItemExtensionData as searchResultListItemExtensionData, +} from './alpha'; // TODO: Remove this mock when we have a permanent solution for nav items extensions // The `GraphiQLIcon` used in "packages/frontend-app-api/src/extensions/CoreNav.tsx" file @@ -89,7 +89,7 @@ describe('createSearchResultListItemExtension', () => { defaultPath: '/', inputs: { items: createExtensionInput({ - item: searchResultItemExtensionData, + item: searchResultListItemExtensionData, }), }, loader: async ({ inputs }) => { diff --git a/plugins/search-react/src/alpha.ts b/plugins/search-react/src/alpha.ts deleted file mode 100644 index e006e249eb..0000000000 --- a/plugins/search-react/src/alpha.ts +++ /dev/null @@ -1,17 +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. - */ - -export * from './wiring'; diff --git a/plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx b/plugins/search-react/src/alpha.tsx similarity index 97% rename from plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx rename to plugins/search-react/src/alpha.tsx index b276c5e60a..4b5bb79669 100644 --- a/plugins/search-react/src/wiring/createSearchResultListItemExtension.tsx +++ b/plugins/search-react/src/alpha.tsx @@ -28,7 +28,13 @@ import { import { Progress } from '@backstage/core-components'; import { SearchDocument, SearchResult } from '@backstage/plugin-search-common'; -import { SearchResultListItemExtension } from '../extensions'; +import { SearchResultListItemExtension } from './extensions'; + +/** @alpha */ +export type BaseSearchResultListItemProps = T & { + rank?: number; + result?: SearchDocument; +} & Omit; /** @alpha */ export type SearchResultItemExtensionComponent = < @@ -77,12 +83,6 @@ export type SearchResultItemExtensionOptions< predicate?: SearchResultItemExtensionPredicate; }; -/** @alpha */ -export type BaseSearchResultListItemProps = T & { - rank?: number; - result?: SearchDocument; -} & Omit; - /** @alpha */ export function createSearchResultListItemExtension< TConfig extends { noTrack?: boolean }, @@ -92,7 +92,7 @@ export function createSearchResultListItemExtension< ? options.configSchema : (createSchemaFromZod(z => z.object({ - noTrack: z.boolean().default(true), + noTrack: z.boolean().default(false), }), ) as PortableSchema); return createExtension({ diff --git a/plugins/search-react/src/wiring/index.ts b/plugins/search-react/src/wiring/index.ts deleted file mode 100644 index 7cf5b0d6f5..0000000000 --- a/plugins/search-react/src/wiring/index.ts +++ /dev/null @@ -1,17 +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. - */ - -export * from './createSearchResultListItemExtension'; From cc9c99329bf9e74c8aff52ca866160b10e330ca4 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:30:18 +0200 Subject: [PATCH 064/207] feat(frontend-app-api): set base path using app router logic Signed-off-by: Camila Belo --- .../frontend-app-api/src/extensions/CoreNav.tsx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/frontend-app-api/src/extensions/CoreNav.tsx b/packages/frontend-app-api/src/extensions/CoreNav.tsx index e66bee8212..50aa8fd408 100644 --- a/packages/frontend-app-api/src/extensions/CoreNav.tsx +++ b/packages/frontend-app-api/src/extensions/CoreNav.tsx @@ -19,6 +19,8 @@ import { createExtension, coreExtensionData, createExtensionInput, + useRouteRef, + NavTarget, } from '@backstage/frontend-plugin-api'; import { makeStyles } from '@material-ui/core'; import { @@ -29,7 +31,6 @@ import { SidebarDivider, SidebarItem, } from '@backstage/core-components'; -import { GraphiQLIcon } from '@backstage/plugin-graphiql'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import LogoIcon from '../../../app/src/components/Root/LogoIcon'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports @@ -68,20 +69,26 @@ export const CoreNav = createExtension({ at: 'core.layout/nav', inputs: { items: createExtensionInput({ - path: coreExtensionData.navTarget, + target: coreExtensionData.navTarget, }), }, output: { element: coreExtensionData.reactElement, }, - factory({ bind }) { + factory({ bind, inputs }) { + const SidebarNavItem = (props: NavTarget) => { + const { icon, title, routeRef } = props; + const to = useRouteRef(routeRef)(); + return ; + }; bind({ - // TODO: set base path using the logic from AppRouter element: ( - + {inputs.items.map((item, index) => ( + + ))} ), }); From 6e9fbc540df4935392e06ee7281499be02db3dd1 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:44:47 +0200 Subject: [PATCH 065/207] feat(frontend-app-api): register app default api implementations Signed-off-by: Camila Belo --- .../frontend-app-api/src/wiring/createApp.tsx | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index bb50dea075..dc7db79022 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -49,6 +49,7 @@ import { featureFlagsApiRef, attachComponentData, useRouteRef, + identityApiRef, } from '@backstage/core-plugin-api'; import { getAvailablePlugins } from './discovery'; import { @@ -62,6 +63,8 @@ import { // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { AppThemeProvider } from '../../../core-app-api/src/app/AppThemeProvider'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports import { AppContextProvider } from '../../../core-app-api/src/app/AppContext'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { LocalStorageFeatureFlags } from '../../../core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags'; @@ -366,13 +369,13 @@ function createApiHolder( ): ApiHolder { const factoryRegistry = new ApiFactoryRegistry(); - const apiFactories = + const pluginApis = coreExtension.attachments .get('apis') ?.map(e => e.getData(coreExtensionData.apiFactory)) .filter((x): x is AnyApiFactory => !!x) ?? []; - for (const factory of apiFactories) { + for (const factory of [...defaultApis, ...pluginApis]) { factoryRegistry.register('default', factory); } @@ -383,6 +386,38 @@ function createApiHolder( factory: () => new LocalStorageFeatureFlags(), }); + factoryRegistry.register('static', { + api: identityApiRef, + deps: {}, + factory: () => { + const appIdentityProxy = new AppIdentityProxy(); + // TODO: Remove this when sign-in page is migrated + appIdentityProxy.setTarget( + { + getUserId: () => 'guest', + getIdToken: async () => undefined, + getProfile: () => ({ + email: 'guest@example.com', + displayName: 'Guest', + }), + getProfileInfo: async () => ({ + email: 'guest@example.com', + displayName: 'Guest', + }), + getBackstageIdentity: async () => ({ + type: 'user', + userEntityRef: 'user:default/guest', + ownershipEntityRefs: ['user:default/guest'], + }), + getCredentials: async () => ({}), + signOut: async () => {}, + }, + { signOutTargetUrl: '/' }, + ); + return appIdentityProxy; + }, + }); + factoryRegistry.register('static', { api: appThemeApiRef, deps: {}, From 5d92f07ff6b053ba2fdecdd72fb490928fb0e6b4 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 27 Sep 2023 09:38:24 +0200 Subject: [PATCH 066/207] feat(frontend-app-api): add support for sidebar group Signed-off-by: Camila Belo --- .../src/extensions/CoreNav.tsx | 18 +++++++--- .../src/extensions/createNavItemExtension.tsx | 35 ++++++++++++++++--- .../src/wiring/coreExtensionData.ts | 1 + 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/packages/frontend-app-api/src/extensions/CoreNav.tsx b/packages/frontend-app-api/src/extensions/CoreNav.tsx index 50aa8fd408..9c829a348f 100644 --- a/packages/frontend-app-api/src/extensions/CoreNav.tsx +++ b/packages/frontend-app-api/src/extensions/CoreNav.tsx @@ -30,6 +30,7 @@ import { sidebarConfig, SidebarDivider, SidebarItem, + SidebarGroup, } from '@backstage/core-components'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import LogoIcon from '../../../app/src/components/Root/LogoIcon'; @@ -64,6 +65,18 @@ const SidebarLogo = () => { ); }; +const SidebarNavItem = (props: NavTarget) => { + const { icon: Icon, title, group, routeRef } = props; + const to = useRouteRef(routeRef)(); + return group ? ( + } label={title}> + {group} + + ) : ( + + ); +}; + export const CoreNav = createExtension({ id: 'core.nav', at: 'core.layout/nav', @@ -76,11 +89,6 @@ export const CoreNav = createExtension({ element: coreExtensionData.reactElement, }, factory({ bind, inputs }) { - const SidebarNavItem = (props: NavTarget) => { - const { icon, title, routeRef } = props; - const to = useRouteRef(routeRef)(); - return ; - }; bind({ element: ( diff --git a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx index 8c55531866..723c9e9956 100644 --- a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx @@ -16,19 +16,33 @@ import { IconComponent, RouteRef } from '@backstage/core-plugin-api'; import { createSchemaFromZod } from '../schema/createSchemaFromZod'; -import { coreExtensionData, createExtension } from '../wiring'; +import { + AnyExtensionInputMap, + ExtensionInputValues, + coreExtensionData, + createExtension, +} from '../wiring'; +import { Expand } from '../wiring/createExtension'; +import { Suspense, lazy } from 'react'; +import React from 'react'; /** * Helper for creating extensions for a nav item. * @public */ -export function createNavItemExtension(options: { +export function createNavItemExtension< + TInputs extends AnyExtensionInputMap, +>(options: { id: string; routeRef: RouteRef; title: string; icon: IconComponent; + inputs?: TInputs; + group?: (options: { + inputs: Expand>; + }) => Promise; }) { - const { id, routeRef, title, icon } = options; + const { id, routeRef, title, icon, group } = options; return createExtension({ id, at: 'core.nav/items', @@ -37,15 +51,28 @@ export function createNavItemExtension(options: { title: z.string().default(title), }), ), + inputs: options.inputs, output: { navTarget: coreExtensionData.navTarget, }, - factory: ({ bind, config }) => { + factory: ({ bind, config, inputs }) => { + const Group = group + ? (lazy(() => + group({ inputs }).then(element => ({ + default: () => element, + })), + ) as unknown as () => JSX.Element) + : undefined; bind({ navTarget: { title: config.title, icon, routeRef, + group: Group ? ( + + + + ) : undefined, }, }); }, diff --git a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts index 079d5bcb18..d03513677d 100644 --- a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts +++ b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts @@ -27,6 +27,7 @@ export type NavTarget = { title: string; icon: IconComponent; routeRef: RouteRef<{}>; + group?: JSX.Element; }; /** @public */ From f22ab808eb5c05adf4446b55a98a31d9e2c6b27c Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:46:21 +0200 Subject: [PATCH 067/207] feat(catalog): create plugin and api extensions Signed-off-by: Camila Belo --- plugins/catalog/package.json | 1 + plugins/catalog/src/alpha.ts | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 412c7d0716..4ef0db4910 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -51,6 +51,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/integration-react": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", diff --git a/plugins/catalog/src/alpha.ts b/plugins/catalog/src/alpha.ts index 3509c1fb7f..ffa50ea1f7 100644 --- a/plugins/catalog/src/alpha.ts +++ b/plugins/catalog/src/alpha.ts @@ -15,3 +15,40 @@ */ export * from './translation'; + +import { + DiscoveryApi, + FetchApi, + discoveryApiRef, + fetchApiRef, +} from '@backstage/core-plugin-api'; +import { CatalogClient } from '@backstage/catalog-client'; +import { + createApiExtension, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; + +/** @alpha */ +export const CatalogApi = createApiExtension({ + factory: { + api: catalogApiRef, + deps: { + discoveryApi: discoveryApiRef, + fetchApi: fetchApiRef, + }, + factory: ({ + discoveryApi, + fetchApi, + }: { + discoveryApi: DiscoveryApi; + fetchApi: FetchApi; + }) => new CatalogClient({ discoveryApi, fetchApi }), + }, +}); + +/** @alpha */ +export default createPlugin({ + id: 'plugin.catalog', + extensions: [CatalogApi], +}); From 3de3a1b872b59fa701ffc43a1346ccd08fa53f32 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:48:19 +0200 Subject: [PATCH 068/207] feat(search): configure alpha subpath Signed-off-by: Camila Belo --- plugins/search/package.json | 19 ++++++++++++++++--- plugins/search/src/alpha.tsx | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 plugins/search/src/alpha.tsx diff --git a/plugins/search/package.json b/plugins/search/package.json index 77c3bd4727..f5d4042964 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -6,9 +6,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.tsx", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.tsx" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "frontend-plugin" diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx new file mode 100644 index 0000000000..eb2f165350 --- /dev/null +++ b/plugins/search/src/alpha.tsx @@ -0,0 +1,15 @@ +/* + * 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. + */ From baf56d5abf4cbc44bd43e1a874851e50d804c1d0 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:50:35 +0200 Subject: [PATCH 069/207] feat(search): create search api extension Signed-off-by: Camila Belo --- plugins/search/package.json | 1 + plugins/search/src/alpha.tsx | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/plugins/search/package.json b/plugins/search/package.json index f5d4042964..8b90867a5a 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -51,6 +51,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "@backstage/plugin-search-react": "workspace:^", diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index eb2f165350..89ff6b7664 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -13,3 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import { + DiscoveryApi, + IdentityApi, + discoveryApiRef, + identityApiRef, +} from '@backstage/core-plugin-api'; + +import { createApiExtension } from '@backstage/frontend-plugin-api'; + +import { searchApiRef } from '@backstage/plugin-search-react'; + +import { SearchClient } from './apis'; + +/** @alpha */ +export const SearchApi = createApiExtension({ + factory: { + api: searchApiRef, + deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef }, + factory: ({ + identityApi, + discoveryApi, + }: { + identityApi: IdentityApi; + discoveryApi: DiscoveryApi; + }) => new SearchClient({ discoveryApi, identityApi }), + }, +}); From 51b63d4939e2479b9e2f26bdb5923a2eee13887e Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:52:52 +0200 Subject: [PATCH 070/207] feat(search): create search page extension Signed-off-by: Camila Belo --- plugins/search/src/alpha.tsx | 188 +++++++++++++++++- .../src/components/SearchPage/UrlUpdater.tsx | 85 ++++++++ 2 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 plugins/search/src/components/SearchPage/UrlUpdater.tsx diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index 89ff6b7664..669656338d 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -14,16 +14,55 @@ * limitations under the License. */ +import React from 'react'; + +import { Grid, makeStyles, Paper, Theme } from '@material-ui/core'; + import { + CatalogIcon, + Content, + DocsIcon, + Header, + Page, + useSidebarPinState, +} from '@backstage/core-components'; +import { + createRouteRef, + useApi, DiscoveryApi, IdentityApi, discoveryApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { createApiExtension } from '@backstage/frontend-plugin-api'; +import { + createApiExtension, + createPageExtension, + createExtensionInput, + createSchemaFromZod, +} from '@backstage/frontend-plugin-api'; +import { + catalogApiRef, + CATALOG_FILTER_EXISTS, +} from '@backstage/plugin-catalog-react'; + +import { SearchType } from '@backstage/plugin-search'; +import { + DefaultResultListItem, + SearchBar, + SearchFilter, + SearchPagination, + SearchResult as SearchResults, + SearchResultPager, + useSearch, + SearchContextProvider, +} from '@backstage/plugin-search-react'; +import { SearchResult } from '@backstage/plugin-search-common'; import { searchApiRef } from '@backstage/plugin-search-react'; +import { searchResultItemExtensionData } from '@backstage/plugin-search-react/alpha'; + +import { UrlUpdater } from './components/SearchPage/SearchPage'; import { SearchClient } from './apis'; @@ -41,3 +80,150 @@ export const SearchApi = createApiExtension({ }) => new SearchClient({ discoveryApi, identityApi }), }, }); + +const useStyles = makeStyles((theme: Theme) => ({ + filter: { + '& + &': { + marginTop: theme.spacing(2.5), + }, + }, + filters: { + padding: theme.spacing(2), + marginTop: theme.spacing(2), + }, +})); + +const searchRouteRef = createRouteRef({ id: 'plugin.search.page' }); + +/** @alpha */ +export const SearchPage = createPageExtension({ + id: 'plugin.search.page', + routeRef: searchRouteRef, + configSchema: createSchemaFromZod(z => + z.object({ + path: z.string().default('/search'), + noTrack: z.boolean().default(false), + }), + ), + inputs: { + items: createExtensionInput({ + item: searchResultItemExtensionData, + }), + }, + loader: async ({ config, inputs }) => { + const getResultItemComponent = (result: SearchResult) => { + const value = inputs.items.find(({ item }) => item?.predicate?.(result)); + return value?.item.component ?? DefaultResultListItem; + }; + + const Component = () => { + const classes = useStyles(); + const { isMobile } = useSidebarPinState(); + const { types } = useSearch(); + const catalogApi = useApi(catalogApiRef); + + return ( + + {!isMobile &&
} + + + + + + {!isMobile && ( + + , + }, + { + value: 'techdocs', + name: 'Documentation', + icon: , + }, + { + value: 'adr', + name: 'Architecture Decision Records', + icon: , + }, + ]} + /> + + {types.includes('techdocs') && ( + { + // Return a list of entities which are documented. + const { items } = await catalogApi.getEntities({ + fields: ['metadata.name'], + filter: { + 'metadata.annotations.backstage.io/techdocs-ref': + CATALOG_FILTER_EXISTS, + }, + }); + + const names = items.map( + entity => entity.metadata.name, + ); + names.sort(); + return names; + }} + /> + )} + + + + + )} + + + + {({ results }) => + results.map((result, index) => { + const SearchResultListItem = + getResultItemComponent(result); + return ( + + ); + }) + } + + + + + + + ); + }; + + return ( + + + + + ); + }, +}); diff --git a/plugins/search/src/components/SearchPage/UrlUpdater.tsx b/plugins/search/src/components/SearchPage/UrlUpdater.tsx new file mode 100644 index 0000000000..d44195b6e2 --- /dev/null +++ b/plugins/search/src/components/SearchPage/UrlUpdater.tsx @@ -0,0 +1,85 @@ +/* + * 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 { useEffect } from 'react'; +import usePrevious from 'react-use/lib/usePrevious'; +import qs from 'qs'; +import { useLocation } from 'react-router-dom'; +import { useSearch } from '@backstage/plugin-search-react'; +import { JsonObject } from '@backstage/types'; + +export const UrlUpdater = () => { + const location = useLocation(); + const { + term, + setTerm, + types, + setTypes, + pageCursor, + setPageCursor, + filters, + setFilters, + } = useSearch(); + + const prevQueryParams = usePrevious(location.search); + + useEffect(() => { + // Only respond to changes to url query params + if (location.search === prevQueryParams) { + return; + } + + const query = + qs.parse(location.search.substring(1), { arrayLimit: 0 }) || {}; + + if (query.filters) { + setFilters(query.filters as JsonObject); + } + + if (query.query) { + setTerm(query.query as string); + } + + if (query.pageCursor) { + setPageCursor(query.pageCursor as string); + } + + if (query.types) { + setTypes(query.types as string[]); + } + }, [prevQueryParams, location, setTerm, setTypes, setPageCursor, setFilters]); + + useEffect(() => { + const newParams = qs.stringify( + { + query: term, + types, + pageCursor, + filters, + }, + { arrayFormat: 'brackets' }, + ); + const newUrl = `${window.location.pathname}?${newParams}`; + + // We directly manipulate window history here in order to not re-render + // infinitely (state => location => state => etc). The intention of this + // code is just to ensure the right query/filters are loaded when a user + // clicks the "back" button after clicking a result. + window.history.replaceState(null, document.title, newUrl); + }, [term, types, pageCursor, filters]); + + return null; +}; From d0fb8e148148c26a837cd00dea3e14f7fa3e10c1 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:53:49 +0200 Subject: [PATCH 071/207] feat(search): create search nav item extension Signed-off-by: Camila Belo --- plugins/search/src/alpha.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index 669656338d..599997495e 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -17,6 +17,7 @@ import React from 'react'; import { Grid, makeStyles, Paper, Theme } from '@material-ui/core'; +import SearchIcon from '@material-ui/icons/Search'; import { CatalogIcon, @@ -39,6 +40,7 @@ import { createApiExtension, createPageExtension, createExtensionInput, + createNavItemExtension, createSchemaFromZod, } from '@backstage/frontend-plugin-api'; @@ -227,3 +229,11 @@ export const SearchPage = createPageExtension({ ); }, }); + +/** @alpha */ +export const SearchNavItem = createNavItemExtension({ + id: 'plugin.search.nav.index', + routeRef: searchRouteRef, + title: 'Search', + icon: SearchIcon, +}); From 99f557f2563a9a6fc5019b3971dd904a1ff6bfbb Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 27 Sep 2023 09:43:12 +0200 Subject: [PATCH 072/207] feat(search): create search modal extension Signed-off-by: Camila Belo --- plugins/search/src/alpha.tsx | 264 ++++++++++++++++++++++++++++++++++- 1 file changed, 257 insertions(+), 7 deletions(-) diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index 599997495e..c8a96a4a5a 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -14,10 +14,24 @@ * limitations under the License. */ -import React from 'react'; +import React, { useCallback, useEffect, useRef } from 'react'; +import { useNavigate } from 'react-router-dom'; -import { Grid, makeStyles, Paper, Theme } from '@material-ui/core'; +import { + makeStyles, + Theme, + Grid, + Box, + Paper, + DialogActions, + DialogContent, + DialogTitle, + Button, + IconButton, +} from '@material-ui/core'; +import CloseIcon from '@material-ui/icons/Close'; import SearchIcon from '@material-ui/icons/Search'; +import ArrowForwardIcon from '@material-ui/icons/ArrowForward'; import { CatalogIcon, @@ -41,6 +55,8 @@ import { createPageExtension, createExtensionInput, createNavItemExtension, + createExtensionDataRef, + createExtension, createSchemaFromZod, } from '@backstage/frontend-plugin-api'; @@ -49,7 +65,6 @@ import { CATALOG_FILTER_EXISTS, } from '@backstage/plugin-catalog-react'; -import { SearchType } from '@backstage/plugin-search'; import { DefaultResultListItem, SearchBar, @@ -64,9 +79,11 @@ import { SearchResult } from '@backstage/plugin-search-common'; import { searchApiRef } from '@backstage/plugin-search-react'; import { searchResultItemExtensionData } from '@backstage/plugin-search-react/alpha'; -import { UrlUpdater } from './components/SearchPage/SearchPage'; - import { SearchClient } from './apis'; +import { SearchType } from './components/SearchType'; +import { UrlUpdater } from './components/SearchPage/SearchPage'; +import { SidebarSearchModal } from './components/SidebarSearchModal/SidebarSearchModal'; +import { useSearchModal } from './components/SearchModal'; /** @alpha */ export const SearchApi = createApiExtension({ @@ -83,7 +100,7 @@ export const SearchApi = createApiExtension({ }, }); -const useStyles = makeStyles((theme: Theme) => ({ +const useSearchPageStyles = makeStyles((theme: Theme) => ({ filter: { '& + &': { marginTop: theme.spacing(2.5), @@ -119,7 +136,7 @@ export const SearchPage = createPageExtension({ }; const Component = () => { - const classes = useStyles(); + const classes = useSearchPageStyles(); const { isMobile } = useSidebarPinState(); const { types } = useSearch(); const catalogApi = useApi(catalogApiRef); @@ -230,10 +247,243 @@ export const SearchPage = createPageExtension({ }, }); +const searchModalExtensionData = createExtensionDataRef( + 'plugin.search.modal.element', +); + +const useSearchModalStyles = makeStyles(theme => ({ + dialogTitle: { + gap: theme.spacing(1), + display: 'grid', + alignItems: 'center', + gridTemplateColumns: '1fr auto', + '&> button': { + marginTop: theme.spacing(1), + }, + }, + container: { + borderRadius: 30, + display: 'flex', + height: '2.4em', + padding: theme.spacing(1), + }, + filter: { + '& + &': { + marginTop: theme.spacing(2.5), + }, + }, + filters: { + padding: theme.spacing(2), + marginTop: theme.spacing(2), + }, + input: { + flex: 1, + }, + button: { + '&:hover': { + background: 'none', + }, + }, + dialogActionsContainer: { padding: theme.spacing(1, 3) }, + viewResultsLink: { verticalAlign: '0.5em' }, +})); + +/** @alpha */ +export const SearchModal = createExtension({ + id: 'plugin.search.modal', + at: 'plugin.search.nav.index/modal', + configSchema: createSchemaFromZod(z => + z.object({ + noTrack: z.boolean().default(false), + }), + ), + inputs: { + items: createExtensionInput({ + item: searchResultItemExtensionData, + }), + }, + output: { + element: searchModalExtensionData, + }, + factory({ bind, config, inputs }) { + const getResultItemComponent = (result: SearchResult) => { + const value = inputs.items.find(({ item }) => item?.predicate?.(result)); + return value?.item.component ?? DefaultResultListItem; + }; + + const Component = () => { + const classes = useSearchModalStyles(); + const navigate = useNavigate(); + const catalogApi = useApi(catalogApiRef); + + const { types } = useSearch(); + const { toggleModal } = useSearchModal(); + const searchRootRoute = '/search'; + const searchBarRef = useRef(null); + + useEffect(() => { + searchBarRef?.current?.focus(); + }); + + // This handler is called when "enter" is pressed + const handleSearchBarSubmit = useCallback(() => { + toggleModal(); + // Using ref to get the current field value without waiting for a query debounce + const query = searchBarRef.current?.value ?? ''; + navigate(`${searchRootRoute}?query=${query}`); + }, [navigate, toggleModal, searchRootRoute]); + + return ( + <> + + + + + + + + + + + + + + + + {types.includes('techdocs') && ( + + { + // Return a list of entities which are documented. + const { items } = await catalogApi.getEntities({ + fields: ['metadata.name'], + filter: { + 'metadata.annotations.backstage.io/techdocs-ref': + CATALOG_FILTER_EXISTS, + }, + }); + + const names = items.map(entity => entity.metadata.name); + names.sort(); + return names; + }} + /> + + )} + + + + + + + + + + + + + + + {({ results }) => + results.map((result, index) => { + const SearchResultListItem = + getResultItemComponent(result); + return ( + + ); + }) + } + + + + + + + + + + + + + ); + }; + + bind({ + element: , + }); + }, +}); + /** @alpha */ export const SearchNavItem = createNavItemExtension({ id: 'plugin.search.nav.index', routeRef: searchRouteRef, title: 'Search', icon: SearchIcon, + group: async ({ inputs }) => ( + {() => inputs.modal.element} + ), + inputs: { + modal: createExtensionInput( + { + element: searchModalExtensionData, + }, + { + singleton: true, + }, + ), + }, }); From 9143802c1c62ee8221d01dd429a5fd0ae0304097 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:55:02 +0200 Subject: [PATCH 073/207] feat(search): create search plugin extension Signed-off-by: Camila Belo --- plugins/search/src/alpha.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index c8a96a4a5a..9eb9d489f4 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -51,6 +51,7 @@ import { } from '@backstage/core-plugin-api'; import { + createPlugin, createApiExtension, createPageExtension, createExtensionInput, @@ -487,3 +488,9 @@ export const SearchNavItem = createNavItemExtension({ ), }, }); + +/** @alpha */ +export default createPlugin({ + id: 'plugin.search', + extensions: [SearchApi, SearchPage, SearchModal, SearchNavItem], +}); From a094b8301439046137b35c8dd3bfe03c5e3c87ac Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:56:00 +0200 Subject: [PATCH 074/207] feat(app-next): install search plugin Signed-off-by: Camila Belo --- packages/app-next/src/examples/pagesPlugin.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/app-next/src/examples/pagesPlugin.tsx b/packages/app-next/src/examples/pagesPlugin.tsx index c805442305..290c6b118e 100644 --- a/packages/app-next/src/examples/pagesPlugin.tsx +++ b/packages/app-next/src/examples/pagesPlugin.tsx @@ -48,6 +48,9 @@ const IndexPage = createPageExtension({
GraphiQL
+
+ Search +
); }; From 08e7675364d8440a6653b5f0a7f61c3a12eedbb7 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:56:48 +0200 Subject: [PATCH 075/207] chore: update yarn.lock Signed-off-by: Camila Belo --- yarn.lock | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yarn.lock b/yarn.lock index e429806816..2fe1ebc6f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6023,6 +6023,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/integration-react": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" @@ -9117,6 +9118,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-search-common": "workspace:^" "@backstage/plugin-search-react": "workspace:^" From d13c57733e2dccb17f1ba27387787e6577eafe3b Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 14:59:17 +0200 Subject: [PATCH 076/207] chore: update api reports Signed-off-by: Camila Belo --- .../api-report.md | 2 -- plugins/catalog/alpha-api-report.md | 9 ++++++ plugins/search/alpha-api-report.md | 30 +++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 plugins/search/alpha-api-report.md diff --git a/plugins/catalog-backend-module-incremental-ingestion/api-report.md b/plugins/catalog-backend-module-incremental-ingestion/api-report.md index 4088b05bb5..c2bfcedfce 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/api-report.md +++ b/plugins/catalog-backend-module-incremental-ingestion/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 { CatalogBuilder } from '@backstage/plugin-catalog-backend'; import type { Config } from '@backstage/config'; import type { DeferredEntity } from '@backstage/plugin-catalog-node'; diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/alpha-api-report.md index 27de408f86..631c43e73c 100644 --- a/plugins/catalog/alpha-api-report.md +++ b/plugins/catalog/alpha-api-report.md @@ -3,8 +3,13 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { Extension } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; +// @alpha (undocumented) +export const CatalogApi: Extension<{}>; + // @alpha (undocumented) export const catalogTranslationRef: TranslationRef< 'catalog', @@ -14,5 +19,9 @@ export const catalogTranslationRef: TranslationRef< } >; +// @alpha (undocumented) +const _default: BackstagePlugin; +export default _default; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/search/alpha-api-report.md b/plugins/search/alpha-api-report.md new file mode 100644 index 0000000000..dd1bce1f9f --- /dev/null +++ b/plugins/search/alpha-api-report.md @@ -0,0 +1,30 @@ +## API Report File for "@backstage/plugin-search" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { Extension } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +const _default: BackstagePlugin; +export default _default; + +// @alpha (undocumented) +export const SearchApi: Extension<{}>; + +// @alpha (undocumented) +export const SearchModal: Extension; + +// @alpha (undocumented) +export const SearchNavItem: Extension<{ + title: string; +}>; + +// @alpha (undocumented) +export const SearchPage: Extension<{ + path: string; +}>; + +// (No @packageDocumentation comment for this package) +``` From e5a2956dd265059d7dad25ea6ebb2142a33d17dc Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 26 Sep 2023 15:04:18 +0200 Subject: [PATCH 077/207] chore: add changeset files Signed-off-by: Camila Belo --- .changeset/olive-cars-rescue.md | 5 +++++ .changeset/purple-forks-fetch.md | 5 +++++ .changeset/tasty-avocados-hope.md | 5 +++++ .changeset/tough-camels-enjoy.md | 5 +++++ 4 files changed, 20 insertions(+) create mode 100644 .changeset/olive-cars-rescue.md create mode 100644 .changeset/purple-forks-fetch.md create mode 100644 .changeset/tasty-avocados-hope.md create mode 100644 .changeset/tough-camels-enjoy.md diff --git a/.changeset/olive-cars-rescue.md b/.changeset/olive-cars-rescue.md new file mode 100644 index 0000000000..95728eb45e --- /dev/null +++ b/.changeset/olive-cars-rescue.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Create an experimental search plugin that is compatible with declarative integration system. diff --git a/.changeset/purple-forks-fetch.md b/.changeset/purple-forks-fetch.md new file mode 100644 index 0000000000..022fc32e71 --- /dev/null +++ b/.changeset/purple-forks-fetch.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Register default api implementations when creating declarative integrated apps. diff --git a/.changeset/tasty-avocados-hope.md b/.changeset/tasty-avocados-hope.md new file mode 100644 index 0000000000..c5bea6a79c --- /dev/null +++ b/.changeset/tasty-avocados-hope.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Migrate catalog api to declarative integration system. diff --git a/.changeset/tough-camels-enjoy.md b/.changeset/tough-camels-enjoy.md new file mode 100644 index 0000000000..07422e1b1b --- /dev/null +++ b/.changeset/tough-camels-enjoy.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Add support for `SidebarGroup` on the sidebar item extension. From d3a37f55c0862443355bb3b55bb8ef6f922c4f4e Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 28 Sep 2023 13:18:35 +0200 Subject: [PATCH 078/207] chore: update changeset files Signed-off-by: Camila Belo --- .changeset/{tough-camels-enjoy.md => late-papayas-push.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changeset/{tough-camels-enjoy.md => late-papayas-push.md} (100%) diff --git a/.changeset/tough-camels-enjoy.md b/.changeset/late-papayas-push.md similarity index 100% rename from .changeset/tough-camels-enjoy.md rename to .changeset/late-papayas-push.md From 18d667507612f1e64b64da500b334e2a391929d7 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 28 Sep 2023 13:45:22 +0200 Subject: [PATCH 079/207] refactor(search): remove search modal for now Signed-off-by: Camila Belo --- .../src/extensions/CoreNav.tsx | 12 +- .../src/extensions/createNavItemExtension.tsx | 35 +-- .../src/wiring/coreExtensionData.ts | 1 - plugins/search/alpha-api-report.md | 4 +- plugins/search/src/alpha.tsx | 257 +----------------- 5 files changed, 11 insertions(+), 298 deletions(-) diff --git a/packages/frontend-app-api/src/extensions/CoreNav.tsx b/packages/frontend-app-api/src/extensions/CoreNav.tsx index 9c829a348f..71ab71a6aa 100644 --- a/packages/frontend-app-api/src/extensions/CoreNav.tsx +++ b/packages/frontend-app-api/src/extensions/CoreNav.tsx @@ -30,7 +30,6 @@ import { sidebarConfig, SidebarDivider, SidebarItem, - SidebarGroup, } from '@backstage/core-components'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import LogoIcon from '../../../app/src/components/Root/LogoIcon'; @@ -66,15 +65,10 @@ const SidebarLogo = () => { }; const SidebarNavItem = (props: NavTarget) => { - const { icon: Icon, title, group, routeRef } = props; + const { icon: Icon, title, routeRef } = props; const to = useRouteRef(routeRef)(); - return group ? ( - } label={title}> - {group} - - ) : ( - - ); + // TODO: Support opening modal, for example, the search one + return ; }; export const CoreNav = createExtension({ diff --git a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx index 723c9e9956..8c55531866 100644 --- a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx @@ -16,33 +16,19 @@ import { IconComponent, RouteRef } from '@backstage/core-plugin-api'; import { createSchemaFromZod } from '../schema/createSchemaFromZod'; -import { - AnyExtensionInputMap, - ExtensionInputValues, - coreExtensionData, - createExtension, -} from '../wiring'; -import { Expand } from '../wiring/createExtension'; -import { Suspense, lazy } from 'react'; -import React from 'react'; +import { coreExtensionData, createExtension } from '../wiring'; /** * Helper for creating extensions for a nav item. * @public */ -export function createNavItemExtension< - TInputs extends AnyExtensionInputMap, ->(options: { +export function createNavItemExtension(options: { id: string; routeRef: RouteRef; title: string; icon: IconComponent; - inputs?: TInputs; - group?: (options: { - inputs: Expand>; - }) => Promise; }) { - const { id, routeRef, title, icon, group } = options; + const { id, routeRef, title, icon } = options; return createExtension({ id, at: 'core.nav/items', @@ -51,28 +37,15 @@ export function createNavItemExtension< title: z.string().default(title), }), ), - inputs: options.inputs, output: { navTarget: coreExtensionData.navTarget, }, - factory: ({ bind, config, inputs }) => { - const Group = group - ? (lazy(() => - group({ inputs }).then(element => ({ - default: () => element, - })), - ) as unknown as () => JSX.Element) - : undefined; + factory: ({ bind, config }) => { bind({ navTarget: { title: config.title, icon, routeRef, - group: Group ? ( - - - - ) : undefined, }, }); }, diff --git a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts index d03513677d..079d5bcb18 100644 --- a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts +++ b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts @@ -27,7 +27,6 @@ export type NavTarget = { title: string; icon: IconComponent; routeRef: RouteRef<{}>; - group?: JSX.Element; }; /** @public */ diff --git a/plugins/search/alpha-api-report.md b/plugins/search/alpha-api-report.md index dd1bce1f9f..5799ff5cd6 100644 --- a/plugins/search/alpha-api-report.md +++ b/plugins/search/alpha-api-report.md @@ -13,9 +13,6 @@ export default _default; // @alpha (undocumented) export const SearchApi: Extension<{}>; -// @alpha (undocumented) -export const SearchModal: Extension; - // @alpha (undocumented) export const SearchNavItem: Extension<{ title: string; @@ -24,6 +21,7 @@ export const SearchNavItem: Extension<{ // @alpha (undocumented) export const SearchPage: Extension<{ path: string; + noTrack: boolean; }>; // (No @packageDocumentation comment for this package) diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index 9eb9d489f4..2a9a714abd 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -14,24 +14,10 @@ * limitations under the License. */ -import React, { useCallback, useEffect, useRef } from 'react'; -import { useNavigate } from 'react-router-dom'; +import React from 'react'; -import { - makeStyles, - Theme, - Grid, - Box, - Paper, - DialogActions, - DialogContent, - DialogTitle, - Button, - IconButton, -} from '@material-ui/core'; -import CloseIcon from '@material-ui/icons/Close'; +import { makeStyles, Theme, Grid, Paper } from '@material-ui/core'; import SearchIcon from '@material-ui/icons/Search'; -import ArrowForwardIcon from '@material-ui/icons/ArrowForward'; import { CatalogIcon, @@ -56,8 +42,6 @@ import { createPageExtension, createExtensionInput, createNavItemExtension, - createExtensionDataRef, - createExtension, createSchemaFromZod, } from '@backstage/frontend-plugin-api'; @@ -83,8 +67,6 @@ import { searchResultItemExtensionData } from '@backstage/plugin-search-react/al import { SearchClient } from './apis'; import { SearchType } from './components/SearchType'; import { UrlUpdater } from './components/SearchPage/SearchPage'; -import { SidebarSearchModal } from './components/SidebarSearchModal/SidebarSearchModal'; -import { useSearchModal } from './components/SearchModal'; /** @alpha */ export const SearchApi = createApiExtension({ @@ -248,249 +230,16 @@ export const SearchPage = createPageExtension({ }, }); -const searchModalExtensionData = createExtensionDataRef( - 'plugin.search.modal.element', -); - -const useSearchModalStyles = makeStyles(theme => ({ - dialogTitle: { - gap: theme.spacing(1), - display: 'grid', - alignItems: 'center', - gridTemplateColumns: '1fr auto', - '&> button': { - marginTop: theme.spacing(1), - }, - }, - container: { - borderRadius: 30, - display: 'flex', - height: '2.4em', - padding: theme.spacing(1), - }, - filter: { - '& + &': { - marginTop: theme.spacing(2.5), - }, - }, - filters: { - padding: theme.spacing(2), - marginTop: theme.spacing(2), - }, - input: { - flex: 1, - }, - button: { - '&:hover': { - background: 'none', - }, - }, - dialogActionsContainer: { padding: theme.spacing(1, 3) }, - viewResultsLink: { verticalAlign: '0.5em' }, -})); - -/** @alpha */ -export const SearchModal = createExtension({ - id: 'plugin.search.modal', - at: 'plugin.search.nav.index/modal', - configSchema: createSchemaFromZod(z => - z.object({ - noTrack: z.boolean().default(false), - }), - ), - inputs: { - items: createExtensionInput({ - item: searchResultItemExtensionData, - }), - }, - output: { - element: searchModalExtensionData, - }, - factory({ bind, config, inputs }) { - const getResultItemComponent = (result: SearchResult) => { - const value = inputs.items.find(({ item }) => item?.predicate?.(result)); - return value?.item.component ?? DefaultResultListItem; - }; - - const Component = () => { - const classes = useSearchModalStyles(); - const navigate = useNavigate(); - const catalogApi = useApi(catalogApiRef); - - const { types } = useSearch(); - const { toggleModal } = useSearchModal(); - const searchRootRoute = '/search'; - const searchBarRef = useRef(null); - - useEffect(() => { - searchBarRef?.current?.focus(); - }); - - // This handler is called when "enter" is pressed - const handleSearchBarSubmit = useCallback(() => { - toggleModal(); - // Using ref to get the current field value without waiting for a query debounce - const query = searchBarRef.current?.value ?? ''; - navigate(`${searchRootRoute}?query=${query}`); - }, [navigate, toggleModal, searchRootRoute]); - - return ( - <> - - - - - - - - - - - - - - - - {types.includes('techdocs') && ( - - { - // Return a list of entities which are documented. - const { items } = await catalogApi.getEntities({ - fields: ['metadata.name'], - filter: { - 'metadata.annotations.backstage.io/techdocs-ref': - CATALOG_FILTER_EXISTS, - }, - }); - - const names = items.map(entity => entity.metadata.name); - names.sort(); - return names; - }} - /> - - )} - - - - - - - - - - - - - - - {({ results }) => - results.map((result, index) => { - const SearchResultListItem = - getResultItemComponent(result); - return ( - - ); - }) - } - - - - - - - - - - - - - ); - }; - - bind({ - element: , - }); - }, -}); - /** @alpha */ export const SearchNavItem = createNavItemExtension({ id: 'plugin.search.nav.index', routeRef: searchRouteRef, title: 'Search', icon: SearchIcon, - group: async ({ inputs }) => ( - {() => inputs.modal.element} - ), - inputs: { - modal: createExtensionInput( - { - element: searchModalExtensionData, - }, - { - singleton: true, - }, - ), - }, }); /** @alpha */ export default createPlugin({ id: 'plugin.search', - extensions: [SearchApi, SearchPage, SearchModal, SearchNavItem], + extensions: [SearchApi, SearchPage, SearchNavItem], }); From e9950c327cf5a4463dd8c016212bc154ff5166c2 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 28 Sep 2023 14:50:43 +0200 Subject: [PATCH 080/207] fix(catalog): use correct plugin id Signed-off-by: Camila Belo --- plugins/catalog/src/alpha.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/alpha.ts b/plugins/catalog/src/alpha.ts index ffa50ea1f7..d9c2af338d 100644 --- a/plugins/catalog/src/alpha.ts +++ b/plugins/catalog/src/alpha.ts @@ -49,6 +49,6 @@ export const CatalogApi = createApiExtension({ /** @alpha */ export default createPlugin({ - id: 'plugin.catalog', + id: 'catalog', extensions: [CatalogApi], }); From 2dbc40c80cbecfd9378fd6ddddff564a7d98a931 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 28 Sep 2023 14:52:00 +0200 Subject: [PATCH 081/207] chore: mention alpha exports on changesets Signed-off-by: Camila Belo --- .changeset/olive-cars-rescue.md | 2 +- .changeset/tasty-avocados-hope.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/olive-cars-rescue.md b/.changeset/olive-cars-rescue.md index 95728eb45e..fd6c8fe331 100644 --- a/.changeset/olive-cars-rescue.md +++ b/.changeset/olive-cars-rescue.md @@ -2,4 +2,4 @@ '@backstage/plugin-search': patch --- -Create an experimental search plugin that is compatible with declarative integration system. +Create an experimental search plugin that is compatible with the declarative integration system, it is exported from `/alpha` subpath. diff --git a/.changeset/tasty-avocados-hope.md b/.changeset/tasty-avocados-hope.md index c5bea6a79c..0772b55683 100644 --- a/.changeset/tasty-avocados-hope.md +++ b/.changeset/tasty-avocados-hope.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog': patch --- -Migrate catalog api to declarative integration system. +Migrate catalog api to declarative integration system, it is exported from `/alpha` subpath. From 4eab5cf9011e6dade62024bdeb75b69f745609cb Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 28 Sep 2023 15:58:38 +0200 Subject: [PATCH 082/207] core-components: always navigate on tab click Signed-off-by: Patrik Oldsberg --- .changeset/lemon-masks-greet.md | 5 +++ .../TabbedLayout/TabbedLayout.test.tsx | 38 +++++++++++++++++++ .../src/layout/HeaderTabs/HeaderTabs.tsx | 2 +- 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 .changeset/lemon-masks-greet.md diff --git a/.changeset/lemon-masks-greet.md b/.changeset/lemon-masks-greet.md new file mode 100644 index 0000000000..79c7b7e92b --- /dev/null +++ b/.changeset/lemon-masks-greet.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +The `TabbedLayout` component will now also navigate when clicking the active tab, which allows for navigation back from any sub routes. diff --git a/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx b/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx index b84a7f262d..f5a059d615 100644 --- a/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx +++ b/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx @@ -17,6 +17,7 @@ import { renderInTestApp, withLogCollector } from '@backstage/test-utils'; import { act, fireEvent } from '@testing-library/react'; import React from 'react'; import { TabbedLayout } from './TabbedLayout'; +import { Link, Route, Routes } from 'react-router-dom'; describe('TabbedLayout', () => { it('renders simplest case', async () => { @@ -81,4 +82,41 @@ describe('TabbedLayout', () => { expect(getByText('tabbed-test-title-2')).toBeInTheDocument(); expect(getByText('tabbed-test-content-2')).toBeInTheDocument(); }); + + it('navigates when user clicks the same tab', async () => { + const { getByText, queryByText, queryAllByRole } = await renderInTestApp( + + +
+ tabbed-test-content +
+ tabbed-test-sub-link + + tabbed-test-sub-content
} + /> + +
+
+ + +
tabbed-test-content-2
+
+ , + ); + + const subLink = getByText('tabbed-test-sub-link'); + expect(subLink).toBeInTheDocument(); + act(() => { + fireEvent.click(subLink); + }); + + expect(queryByText('tabbed-test-sub-content')).toBeInTheDocument(); + const [firstTab] = queryAllByRole('tab'); + act(() => { + fireEvent.click(firstTab); + }); + expect(queryByText('tabbed-test-sub-content')).not.toBeInTheDocument(); + }); }); diff --git a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx index 48e0a8906a..704df67374 100644 --- a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx +++ b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx @@ -85,7 +85,7 @@ export function HeaderTabs(props: HeaderTabsProps) { if (selectedIndex === undefined) { setSelectedTab(index); } - if (onChange && selectedIndex !== index) onChange(index); + if (onChange) onChange(index); }, [selectedIndex, onChange], ); From 2b7fb9e1ca5ce9e50a5e9b3ecae05feb9cf8dc63 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 28 Sep 2023 16:10:39 +0200 Subject: [PATCH 083/207] chore: update catalog backend api report Signed-off-by: Camila Belo --- .../catalog-backend-module-incremental-ingestion/api-report.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/catalog-backend-module-incremental-ingestion/api-report.md b/plugins/catalog-backend-module-incremental-ingestion/api-report.md index c2bfcedfce..4088b05bb5 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-node'; From a1f1d3114aa329dc95ae20e0d514ea4a5338d75b Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Thu, 28 Sep 2023 17:11:00 +0200 Subject: [PATCH 084/207] Added class to support textwrap in menuitems in the SupportButton component Signed-off-by: Jasper Boeijenga --- .../src/components/SupportButton/SupportButton.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index dcd4ead321..a07c03b7d2 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -46,6 +46,9 @@ const useStyles = makeStyles( minWidth: 260, maxWidth: 400, }, + menuItem: { + whiteSpace: 'normal', + }, }, { name: 'BackstageSupportButton' }, ); @@ -145,12 +148,16 @@ export function SupportButton(props: SupportButtonProps) { autoFocusItem={Boolean(anchorEl)} > {title && ( - + {title} )} {React.Children.map(children, (child, i) => ( - + {child} ))} From 997a71850c21355fba73a2eb94fc38c5050c1fb6 Mon Sep 17 00:00:00 2001 From: Jasper Boeijenga Date: Thu, 28 Sep 2023 18:44:34 +0200 Subject: [PATCH 085/207] Added changeset Signed-off-by: Jasper Boeijenga --- .changeset/popular-dots-design.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/popular-dots-design.md diff --git a/.changeset/popular-dots-design.md b/.changeset/popular-dots-design.md new file mode 100644 index 0000000000..c333ce0105 --- /dev/null +++ b/.changeset/popular-dots-design.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Changed SupportButton menuitems to support text wrap From 94b2b0ae6c45628e4ac54ac5bf094e637d5e1d6a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:25:31 +0000 Subject: [PATCH 086/207] chore(deps): update dependency @types/rollup-plugin-peer-deps-external to v2.2.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 20b1df5e05..b872b37aa3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18372,12 +18372,12 @@ __metadata: 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" + version: 2.2.2 + resolution: "@types/rollup-plugin-peer-deps-external@npm:2.2.2" dependencies: "@types/node": "*" rollup: ^0.63.4 - checksum: d6bf4ca92e8b09ca35c0397b89a8b8368bb3d1448a5b82a39ab18886f4b4a3d73f197ed49470e10350b2b5ddc892d4050c5e01ac6247fc63321a5ac9fc6f7363 + checksum: a821911276d1882cf30c9650abc3c1cf7b29490ecacfdd537663a4de32b42ff7171bcd69568ce1b256191ad1d2937b1de839d1db85538769787986a5877273e2 languageName: node linkType: hard From 4cd186972012579d55e7cbf21c6d56e94bd99521 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:35:31 +0000 Subject: [PATCH 087/207] chore(deps): update dependency @types/sanitize-html to v2.9.1 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d896b91bce..4cb2f6db32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18391,11 +18391,11 @@ __metadata: linkType: hard "@types/sanitize-html@npm:^2.6.2": - version: 2.9.0 - resolution: "@types/sanitize-html@npm:2.9.0" + version: 2.9.1 + resolution: "@types/sanitize-html@npm:2.9.1" dependencies: htmlparser2: ^8.0.0 - checksum: b60f42b740bbfb1b1434ce8b43925a38ecc608b60aa654fd009d2e22e33f324b61d370768c55bd2fd98e03de08518ffa8911d61606c483526fb931bb8b59d1b0 + checksum: 381db8e3f22876e8f6aa8f0997af73c71220c8398545d809ebd4e25d33480e73642b8c143a87d87bba504a43ab58d70a724c60eb3fd8fde31a813b682730c98f languageName: node linkType: hard From d3835e593a819c4f529235f7112216b7633ca80f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 18:45:48 +0000 Subject: [PATCH 088/207] chore(deps): update dependency @types/semver to v7.5.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d896b91bce..6e9262f9cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18407,9 +18407,9 @@ __metadata: linkType: hard "@types/semver@npm:^7.3.12, @types/semver@npm:^7.3.8, @types/semver@npm:^7.5.0": - version: 7.5.2 - resolution: "@types/semver@npm:7.5.2" - checksum: 743aa8a2b58e20b329c19bd2459152cb049d12fafab7279b90ac11e0f268c97efbcb606ea0c681cca03f79015381b40d9b1244349b354270bec3f939ed49f6e9 + version: 7.5.3 + resolution: "@types/semver@npm:7.5.3" + checksum: 349fdd1ab6c213bac5c991bac766bd07b8b12e63762462bb058740dcd2eb09c8193d068bb226f134661275f2022976214c0e727a4e5eb83ec1b131127c980d3e languageName: node linkType: hard From f9d17eabdb7556ce647e23105a69ea6130c31d48 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 18:46:20 +0000 Subject: [PATCH 089/207] chore(deps): update dependency @types/serve-handler to v6.1.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d896b91bce..1a4bc8b682 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18424,11 +18424,11 @@ __metadata: linkType: hard "@types/serve-handler@npm:^6.1.0": - version: 6.1.1 - resolution: "@types/serve-handler@npm:6.1.1" + version: 6.1.2 + resolution: "@types/serve-handler@npm:6.1.2" dependencies: "@types/node": "*" - checksum: f519f83b18d7dea80f188f387a56dfe30fe944196849c470902fabf9db344c083c470f67e3362ad3f2294512950bc55924282c5c7a911ec8d507c37c6861d8ce + checksum: 6b206cba18bf77b938e340e1015c631d92b492918ba78dfdff57590a25da8c4bc63fba90f43d763f854c5aa523b243c283ba84d14cfeb1841795337c8b978bd6 languageName: node linkType: hard From c30abec76e2a0356a1066471d21edc9b6c01ea5d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 19:23:18 +0000 Subject: [PATCH 090/207] chore(deps): update dependency @types/supertest to v2.0.13 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2d7257a851..b1972728b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18547,11 +18547,11 @@ __metadata: linkType: hard "@types/supertest@npm:^2.0.12, @types/supertest@npm:^2.0.8": - version: 2.0.12 - resolution: "@types/supertest@npm:2.0.12" + version: 2.0.13 + resolution: "@types/supertest@npm:2.0.13" dependencies: "@types/superagent": "*" - checksum: f0e2b44f86bec2f708d6a3d0cb209055b487922040773049b0f8c6b557af52d4b5fa904e17dfaa4ce6e610172206bbec7b62420d158fa57b6ffc2de37b1730d3 + checksum: fe66be8e16626f254dc9d9691706942689f47a84edf7d3baaeadd6d4d576dbf915ee70cebdd7034015e83fa91fcd2dcff1cd0252514e4c510619817a183b5b4f languageName: node linkType: hard From c1e08f3bec1a4cedbbda480e780eea21f5263d58 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 19:23:49 +0000 Subject: [PATCH 091/207] chore(deps): update dependency @types/swagger-ui-react to v4.18.1 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2d7257a851..31337948da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18565,11 +18565,11 @@ __metadata: linkType: hard "@types/swagger-ui-react@npm:^4.18.0": - version: 4.18.0 - resolution: "@types/swagger-ui-react@npm:4.18.0" + version: 4.18.1 + resolution: "@types/swagger-ui-react@npm:4.18.1" dependencies: "@types/react": "*" - checksum: fa946a76ece76cdbaf8d8dc2945d690787f67b29a9ed14d95b706b8a7fca2d4161a62eeda74ce81c09b872c23b788f86dab36607e891744c91f425b92e302cef + checksum: 33c5e9aeccaf6591bd8f59489f8ef50b941daf491f08ba00cb1f26140a756b00ecd6a84fcf0171cdb068134e52c3877bdac571357e12f224ae7fc5979aeedb6f languageName: node linkType: hard From 9edd866945578c1b0e743bd190dc6560b1e1460d Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Thu, 28 Sep 2023 14:25:48 -0500 Subject: [PATCH 092/207] Clarified docker node and debian version Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/small-pugs-build.md | 4 ++-- docs/releases/v1.19.0-next.0-changelog.md | 4 ++-- packages/create-app/CHANGELOG.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.changeset/small-pugs-build.md b/.changeset/small-pugs-build.md index d1640340ba..68e11cd967 100644 --- a/.changeset/small-pugs-build.md +++ b/.changeset/small-pugs-build.md @@ -2,6 +2,6 @@ '@backstage/create-app': patch --- -Bump Docker base images to `node:18-bullseye-slim` to fix compatibility issues raised during image build. +Bump Docker base images to `node:18-bookworm-slim` to fix node compatibility issues raised during image build. -You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bullseye-slim` +You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bookworm-slim` diff --git a/docs/releases/v1.19.0-next.0-changelog.md b/docs/releases/v1.19.0-next.0-changelog.md index ed95166757..d1861165b9 100644 --- a/docs/releases/v1.19.0-next.0-changelog.md +++ b/docs/releases/v1.19.0-next.0-changelog.md @@ -297,9 +297,9 @@ - de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. -- 04a3f65e15: Bump Docker base images to `node:18-bullseye-slim` to fix compatibility issues raised during image build. +- 04a3f65e15: Bump Docker base images to `node:18-bookworm-slim` to fix node compatibility issues raised during image build. - You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bullseye-slim` + You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bookworm-slim` - 5eacd5d213: The E2E test setup based on Cypress has been replaced with one based on [Playwright](https://playwright.dev/). Migrating existing apps is not required as this is a standalone setup, only do so if you also want to switch from Cypress to Playwright. diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 03bd32e124..3d9f76e93d 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -12,9 +12,9 @@ - deed089a3d: Bump `cypress` to fix the end-to-end tests - de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. -- 04a3f65e15: Bump Docker base images to `node:18-bullseye-slim` to fix compatibility issues raised during image build. +- 04a3f65e15: Bump Docker base images to `node:18-bookworm-slim` to fix node compatibility issues raised during image build. - You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bullseye-slim` + You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bookworm-slim` - 5eacd5d213: The E2E test setup based on Cypress has been replaced with one based on [Playwright](https://playwright.dev/). Migrating existing apps is not required as this is a standalone setup, only do so if you also want to switch from Cypress to Playwright. From 208faf8756950ed23a09d584a242c42496c4f34c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 20:37:12 +0000 Subject: [PATCH 093/207] chore(deps): update dependency @types/webpack to v5.28.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 02c4184f9c..a236b6e28d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18695,13 +18695,13 @@ __metadata: linkType: hard "@types/webpack@npm:^5.28.0": - version: 5.28.2 - resolution: "@types/webpack@npm:5.28.2" + version: 5.28.3 + resolution: "@types/webpack@npm:5.28.3" dependencies: "@types/node": "*" tapable: ^2.2.0 webpack: ^5 - checksum: 0b147aaaaa8992417a5ed65af83eb0df9b5247c38ab482f3c844495935a29c474cb21bc865ca36052c353034f40d14c8d232f0c831fdc1a6956baa985d7b1135 + checksum: 8452528f7ff61eb5e53d9d1dc08c05c648af2d850e14debf49141859b72798ea2d91f2892f849d7fa97e208fef7ae82960eea24b1019cb072b4713b515e74bfc languageName: node linkType: hard From 9e734aebc43932010d80ee235d9dfbe0f06bd067 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 20:38:46 +0000 Subject: [PATCH 094/207] chore(deps): update dependency @types/webpack-env to v1.18.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- microsite/yarn.lock | 6 +++--- yarn.lock | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 427f73c27a..d94e257c41 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -3137,9 +3137,9 @@ __metadata: linkType: hard "@types/webpack-env@npm:^1.18.0": - version: 1.18.1 - resolution: "@types/webpack-env@npm:1.18.1" - checksum: 3173c069763e51a96565d602af7e6dac9d772ae4aa6f26cac187cbf599a7f0b88f790b4b050b9dbdb0485daed3061b4a337863f3b8ce66f8a4e51f75ad387c6a + version: 1.18.2 + resolution: "@types/webpack-env@npm:1.18.2" + checksum: 883908ade827d35a10efc574fb6f2728a7c520d4296cf1507633ac7457204ccd697bc6c8cadac99bc5d96074a6109c658ebfde59f42ba5ba0fdfffc538892b0f languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index 02c4184f9c..70631bfeb2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18688,9 +18688,9 @@ __metadata: linkType: hard "@types/webpack-env@npm:^1.15.2, @types/webpack-env@npm:^1.15.3": - version: 1.18.1 - resolution: "@types/webpack-env@npm:1.18.1" - checksum: 3173c069763e51a96565d602af7e6dac9d772ae4aa6f26cac187cbf599a7f0b88f790b4b050b9dbdb0485daed3061b4a337863f3b8ce66f8a4e51f75ad387c6a + version: 1.18.2 + resolution: "@types/webpack-env@npm:1.18.2" + checksum: 883908ade827d35a10efc574fb6f2728a7c520d4296cf1507633ac7457204ccd697bc6c8cadac99bc5d96074a6109c658ebfde59f42ba5ba0fdfffc538892b0f languageName: node linkType: hard From dfb99e8e5c581dd732718ee57095ae0f9981ef36 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:36:56 +0000 Subject: [PATCH 095/207] chore(deps): update dependency @types/yarnpkg__lockfile to v1.1.7 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 02c4184f9c..9877134012 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18756,9 +18756,9 @@ __metadata: linkType: hard "@types/yarnpkg__lockfile@npm:^1.1.4": - version: 1.1.6 - resolution: "@types/yarnpkg__lockfile@npm:1.1.6" - checksum: c0983d88c479f7b00a66d927fda9f8972e072745d5d16922cf381807aa6e88553319bb9f2b21b58f9e1ebea1a198a22d4da3111d93c81288589371ebb00d65f5 + version: 1.1.7 + resolution: "@types/yarnpkg__lockfile@npm:1.1.7" + checksum: f7d898bfa7a75440ecc57a72d5297c9ce1566d10996004a61765bc79fa82f0c6c82df892442343e983602956f04f0943249902b9e4c09af472873382d0029b21 languageName: node linkType: hard From 0728f5f9da7f2c98ec226dfe941047c92a761bf9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:37:26 +0000 Subject: [PATCH 096/207] chore(deps): update dependency @types/yauzl to v2.10.1 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 02c4184f9c..219ff98537 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18763,11 +18763,11 @@ __metadata: linkType: hard "@types/yauzl@npm:^2.10.0": - version: 2.10.0 - resolution: "@types/yauzl@npm:2.10.0" + version: 2.10.1 + resolution: "@types/yauzl@npm:2.10.1" dependencies: "@types/node": "*" - checksum: 55d27ae5d346ea260e40121675c24e112ef0247649073848e5d4e03182713ae4ec8142b98f61a1c6cbe7d3b72fa99bbadb65d8b01873e5e605cdc30f1ff70ef2 + checksum: 3377916a2d493cb2422b167fb7dfff8cb3ea045a9489dab4955858719bf7fe6808e5f6a51ee819904fb7f623f7ac092b87f9d6a857ea1214a45070d19c8b3d7e languageName: node linkType: hard From 9f95d27c73016748357a712c4391e165967f08c5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 02:08:00 +0000 Subject: [PATCH 097/207] chore(deps): update dependency esbuild to v0.19.4 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 182 +++++++++++++++++++++++++++--------------------------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/yarn.lock b/yarn.lock index 02c4184f9c..ecf6d5b0fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10789,9 +10789,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/android-arm64@npm:0.19.3" +"@esbuild/android-arm64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/android-arm64@npm:0.19.4" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -10810,9 +10810,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/android-arm@npm:0.19.3" +"@esbuild/android-arm@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/android-arm@npm:0.19.4" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -10824,9 +10824,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/android-x64@npm:0.19.3" +"@esbuild/android-x64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/android-x64@npm:0.19.4" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -10838,9 +10838,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/darwin-arm64@npm:0.19.3" +"@esbuild/darwin-arm64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/darwin-arm64@npm:0.19.4" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -10852,9 +10852,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/darwin-x64@npm:0.19.3" +"@esbuild/darwin-x64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/darwin-x64@npm:0.19.4" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -10866,9 +10866,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/freebsd-arm64@npm:0.19.3" +"@esbuild/freebsd-arm64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/freebsd-arm64@npm:0.19.4" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -10880,9 +10880,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/freebsd-x64@npm:0.19.3" +"@esbuild/freebsd-x64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/freebsd-x64@npm:0.19.4" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -10894,9 +10894,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/linux-arm64@npm:0.19.3" +"@esbuild/linux-arm64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/linux-arm64@npm:0.19.4" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -10908,9 +10908,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/linux-arm@npm:0.19.3" +"@esbuild/linux-arm@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/linux-arm@npm:0.19.4" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -10922,9 +10922,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/linux-ia32@npm:0.19.3" +"@esbuild/linux-ia32@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/linux-ia32@npm:0.19.4" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -10943,9 +10943,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/linux-loong64@npm:0.19.3" +"@esbuild/linux-loong64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/linux-loong64@npm:0.19.4" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -10957,9 +10957,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/linux-mips64el@npm:0.19.3" +"@esbuild/linux-mips64el@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/linux-mips64el@npm:0.19.4" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -10971,9 +10971,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/linux-ppc64@npm:0.19.3" +"@esbuild/linux-ppc64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/linux-ppc64@npm:0.19.4" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -10985,9 +10985,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/linux-riscv64@npm:0.19.3" +"@esbuild/linux-riscv64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/linux-riscv64@npm:0.19.4" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -10999,9 +10999,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/linux-s390x@npm:0.19.3" +"@esbuild/linux-s390x@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/linux-s390x@npm:0.19.4" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -11013,9 +11013,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/linux-x64@npm:0.19.3" +"@esbuild/linux-x64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/linux-x64@npm:0.19.4" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -11027,9 +11027,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/netbsd-x64@npm:0.19.3" +"@esbuild/netbsd-x64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/netbsd-x64@npm:0.19.4" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -11041,9 +11041,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/openbsd-x64@npm:0.19.3" +"@esbuild/openbsd-x64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/openbsd-x64@npm:0.19.4" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -11055,9 +11055,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/sunos-x64@npm:0.19.3" +"@esbuild/sunos-x64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/sunos-x64@npm:0.19.4" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -11069,9 +11069,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/win32-arm64@npm:0.19.3" +"@esbuild/win32-arm64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/win32-arm64@npm:0.19.4" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -11083,9 +11083,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/win32-ia32@npm:0.19.3" +"@esbuild/win32-ia32@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/win32-ia32@npm:0.19.4" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -11097,9 +11097,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.19.3": - version: 0.19.3 - resolution: "@esbuild/win32-x64@npm:0.19.3" +"@esbuild/win32-x64@npm:0.19.4": + version: 0.19.4 + resolution: "@esbuild/win32-x64@npm:0.19.4" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -24658,31 +24658,31 @@ __metadata: linkType: hard "esbuild@npm:^0.19.0": - version: 0.19.3 - resolution: "esbuild@npm:0.19.3" + version: 0.19.4 + resolution: "esbuild@npm:0.19.4" dependencies: - "@esbuild/android-arm": 0.19.3 - "@esbuild/android-arm64": 0.19.3 - "@esbuild/android-x64": 0.19.3 - "@esbuild/darwin-arm64": 0.19.3 - "@esbuild/darwin-x64": 0.19.3 - "@esbuild/freebsd-arm64": 0.19.3 - "@esbuild/freebsd-x64": 0.19.3 - "@esbuild/linux-arm": 0.19.3 - "@esbuild/linux-arm64": 0.19.3 - "@esbuild/linux-ia32": 0.19.3 - "@esbuild/linux-loong64": 0.19.3 - "@esbuild/linux-mips64el": 0.19.3 - "@esbuild/linux-ppc64": 0.19.3 - "@esbuild/linux-riscv64": 0.19.3 - "@esbuild/linux-s390x": 0.19.3 - "@esbuild/linux-x64": 0.19.3 - "@esbuild/netbsd-x64": 0.19.3 - "@esbuild/openbsd-x64": 0.19.3 - "@esbuild/sunos-x64": 0.19.3 - "@esbuild/win32-arm64": 0.19.3 - "@esbuild/win32-ia32": 0.19.3 - "@esbuild/win32-x64": 0.19.3 + "@esbuild/android-arm": 0.19.4 + "@esbuild/android-arm64": 0.19.4 + "@esbuild/android-x64": 0.19.4 + "@esbuild/darwin-arm64": 0.19.4 + "@esbuild/darwin-x64": 0.19.4 + "@esbuild/freebsd-arm64": 0.19.4 + "@esbuild/freebsd-x64": 0.19.4 + "@esbuild/linux-arm": 0.19.4 + "@esbuild/linux-arm64": 0.19.4 + "@esbuild/linux-ia32": 0.19.4 + "@esbuild/linux-loong64": 0.19.4 + "@esbuild/linux-mips64el": 0.19.4 + "@esbuild/linux-ppc64": 0.19.4 + "@esbuild/linux-riscv64": 0.19.4 + "@esbuild/linux-s390x": 0.19.4 + "@esbuild/linux-x64": 0.19.4 + "@esbuild/netbsd-x64": 0.19.4 + "@esbuild/openbsd-x64": 0.19.4 + "@esbuild/sunos-x64": 0.19.4 + "@esbuild/win32-arm64": 0.19.4 + "@esbuild/win32-ia32": 0.19.4 + "@esbuild/win32-x64": 0.19.4 dependenciesMeta: "@esbuild/android-arm": optional: true @@ -24730,7 +24730,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: f998ba82b1bbf0f3036201dc2cb94f92aff887b7552738ea3e4dd6f386f87740ef76aabae2fc1c4b91a519354d390f6d9fd89eb71e26882983f6fbaf75369206 + checksum: 024309a16365b020815a30e9a3a9354894a391cf1adbfad7f44a975cf161ab5e961619b30e1ec8ea02994631d71e6b38831119be69f8ccb610c32bbe21addc79 languageName: node linkType: hard From d01a82f34ee7f8d82a9266b74e3498d5a917ce94 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 02:08:32 +0000 Subject: [PATCH 098/207] chore(deps): update dependency swr to v2.2.4 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 02c4184f9c..eb3bd9f73c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40142,14 +40142,14 @@ __metadata: linkType: hard "swr@npm:^2.0.0": - version: 2.2.2 - resolution: "swr@npm:2.2.2" + version: 2.2.4 + resolution: "swr@npm:2.2.4" dependencies: client-only: ^0.0.1 use-sync-external-store: ^1.2.0 peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 - checksum: afb3d4824f7631bc3a045483f4e4beb5ca9bfa82b64690b3d1133cdf0666ad8e4a9a879657fac5b34dbf19ea9a1503cf92c9bde972f3d40cefe434c73bd9627a + checksum: d1398f89fd68af0e0cb6100a5769b1e17c0dbe8a778898643ad28456acda64add43344754c7d919e3f2ca82854adf86ff7d465aba25a2d555bcb669e457138f8 languageName: node linkType: hard From 9c87c4972c5d75ac562b241aba9e20165a89fb9d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 04:27:57 +0000 Subject: [PATCH 099/207] chore(deps): update github/codeql-action action to v2.21.9 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 4f48fa83b4..6fe4ab0f9e 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -61,6 +61,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 + uses: github/codeql-action/upload-sarif@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9 with: sarif_file: results.sarif From e26868601e8f8a1f70e05ffe48c316972894d2e6 Mon Sep 17 00:00:00 2001 From: ivgo Date: Tue, 26 Sep 2023 13:57:27 +0200 Subject: [PATCH 100/207] Make sure the archived parameter is set in URL Signed-off-by: ivgo --- plugins/catalog-backend-module-gitlab/src/lib/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index 79ae328ce2..daf82245e8 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -309,7 +309,7 @@ export class GitLabClient { ): Promise> { const request = new URL(`${this.config.apiBaseUrl}${endpoint}`); for (const key in options) { - if (options[key]) { + if (options[key] !== undefined && options[key] !== '') { request.searchParams.append(key, options[key]!.toString()); } } From 2da314370c0ca644b2b06ad333930deae1463889 Mon Sep 17 00:00:00 2001 From: ivgo Date: Tue, 26 Sep 2023 13:58:07 +0200 Subject: [PATCH 101/207] Remove unnecessary entry from test mock Signed-off-by: ivgo --- .../src/GitLabDiscoveryProcessor.test.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.test.ts b/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.test.ts index a56c229105..f836500c6e 100644 --- a/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.test.ts @@ -237,14 +237,6 @@ describe('GitlabDiscoveryProcessor', () => { web_url: 'https://gitlab.fake/3', path_with_namespace: '3', }, - { - id: 4, - archived: true, // ARCHIVED - default_branch: 'master', - last_activity_at: '2021-08-05T11:03:05.774Z', - web_url: 'https://gitlab.fake/4', - path_with_namespace: '4', - }, { id: 5, archived: false, From c11113ddedcd80ebbbfe512d4c38d43ee8e05e2e Mon Sep 17 00:00:00 2001 From: ivgo Date: Fri, 29 Sep 2023 08:39:59 +0200 Subject: [PATCH 102/207] Add tests to verify the searchParams are added as expected Signed-off-by: ivgo --- .../src/lib/client.test.ts | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts index dda30fd86a..dad126e3e4 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts @@ -120,6 +120,14 @@ function setupFakeHasFileEndpoint(srv: SetupServer, apiBaseUrl: string) { ); } +function setupFakeURLReturnEndpoint(srv: SetupServer, url: string) { + srv.use( + rest.get(url, (req, res, ctx) => { + return res(ctx.json([{ endpoint: req.url.toString() }])); + }), + ); +} + describe('GitLabClient', () => { describe('isSelfManaged', () => { it('returns true if self managed instance', () => { @@ -933,3 +941,84 @@ describe('hasFile', () => { expect(hasFile).toBe(false); }); }); + +describe('pagedRequest search params', () => { + beforeEach(() => { + // setup fake paginated endpoint with 4 pages each returning one item + setupFakeURLReturnEndpoint(server, FAKE_PAGED_URL); + }); + + it('no search params provided', async () => { + const client = new GitLabClient({ + config: MOCK_CONFIG, + logger: getVoidLogger(), + }); + + const { items } = await client.pagedRequest<{ endpoint: string }>( + FAKE_PAGED_ENDPOINT, + ); + // fake page contains exactly one item + expect(items).toHaveLength(1); + expect(items).toEqual([ + { endpoint: 'https://example.com/api/v4/some-endpoint' }, + ]); + }); + + it('defined numeric search params', async () => { + const client = new GitLabClient({ + config: MOCK_CONFIG, + logger: getVoidLogger(), + }); + + const { items } = await client.pagedRequest<{ endpoint: string }>( + FAKE_PAGED_ENDPOINT, + { page: 1, per_page: 50 }, + ); + // fake page contains exactly one item + expect(items).toHaveLength(1); + expect(items).toEqual([ + { + endpoint: 'https://example.com/api/v4/some-endpoint?page=1&per_page=50', + }, + ]); + }); + + it('defined string search params', async () => { + const client = new GitLabClient({ + config: MOCK_CONFIG, + logger: getVoidLogger(), + }); + + const { items } = await client.pagedRequest<{ endpoint: string }>( + FAKE_PAGED_ENDPOINT, + { test: 'value', empty: '' }, + ); + // fake page contains exactly one item + expect(items).toHaveLength(1); + expect(items).toEqual([ + { + endpoint: 'https://example.com/api/v4/some-endpoint?test=value', + }, + ]); + }); + + it('defined boolean search params', async () => { + const client = new GitLabClient({ + config: MOCK_CONFIG, + logger: getVoidLogger(), + }); + + const { items } = await client.pagedRequest<{ endpoint: string }>( + FAKE_PAGED_ENDPOINT, + { active: true, archived: false }, + ); + // fake page contains exactly one item + expect(items).toHaveLength(1); + expect(items).toEqual([ + { + endpoint: + 'https://example.com/api/v4/some-endpoint?active=true&archived=false', + }, + ]); + }); +}); From 6ae7f12abb720529ff3e477f8d09890363a5d4e5 Mon Sep 17 00:00:00 2001 From: ivgo Date: Tue, 26 Sep 2023 14:07:44 +0200 Subject: [PATCH 103/207] Add changeset Signed-off-by: ivgo --- .changeset/shy-seas-sip.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/shy-seas-sip.md diff --git a/.changeset/shy-seas-sip.md b/.changeset/shy-seas-sip.md new file mode 100644 index 0000000000..dfbc4ff0e0 --- /dev/null +++ b/.changeset/shy-seas-sip.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-gitlab': patch +--- + +Make sure the archived projects are skipped with the Gitlab API From 63bf2d7279ce88308f539e0f33761d56b07c3b28 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 28 Sep 2023 14:36:08 +0200 Subject: [PATCH 104/207] docs: add release notes template Signed-off-by: Patrik Oldsberg --- docs/release-notes-template.md | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/release-notes-template.md diff --git a/docs/release-notes-template.md b/docs/release-notes-template.md new file mode 100644 index 0000000000..9f9a0b76ee --- /dev/null +++ b/docs/release-notes-template.md @@ -0,0 +1,40 @@ +--- +id: v1.1.0 +title: v1.1.0 +description: Backstage Release v1.1.0 +--- + +These are the release notes for the v1.1.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 + +### + +<short description>. Contributed by [@<user>](https://github.com/<user>) [#<pr>](https://github.com/backstage/backstage/pull/<pr>) + +## Security Fixes + +This release does not contain any security fixes. + +<or> + +@backstage/<package-name>, please upgrade to the latest version if you are using this module. + +## 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/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) + +Sign up for our [newsletter](https://info.backstage.spotify.com/newsletter_subscribe) if you want to be informed about what is happening in the world of Backstage. From c6a492f976e7f162ff7a0e47560f06773c0c692d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 09:56:00 +0000 Subject: [PATCH 105/207] chore(deps): update react monorepo to v17.0.66 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4ed9c0a6b0..ea57e15a39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18177,11 +18177,11 @@ __metadata: linkType: hard "@types/react-dom@npm:^17": - version: 17.0.20 - resolution: "@types/react-dom@npm:17.0.20" + version: 17.0.21 + resolution: "@types/react-dom@npm:17.0.21" dependencies: "@types/react": ^17 - checksum: 525439fb14a033fc5dbe74711ecc50ec82273a528df9656594066a6219401e975101dafffd15d9a1a57a9442d52ea0c92eaacae09554dde27cd792e773f67467 + checksum: a2e3f068c1374601856b63bc57f3f436cf6270c1ba5c5cef0776def6de296c8bdd31c39b5be9e9e77f4652e923bef1e71ae377a2b038f4a81bfd0fec8d10d0d0 languageName: node linkType: hard @@ -18279,13 +18279,13 @@ __metadata: linkType: hard "@types/react@npm:^17": - version: 17.0.65 - resolution: "@types/react@npm:17.0.65" + version: 17.0.66 + resolution: "@types/react@npm:17.0.66" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: bb862f0f97a49e690cd5c62743307d17398ee62b87bbb2c85c1b01cb992244c0aef4ecdedaab0e8d33c6315d5a8f067cf90e7f1c366b8819678c59204e202932 + checksum: b364a98670ccee222dbd21ddd6cd1be78ad22bca40c7e1c073fff908121fd51fe1de0e9afc3d4ef8dfb6ceedfa28c5257dde9f23af0096f4d350e60c4b2f8858 languageName: node linkType: hard From db351ffc0bbd6d36f60231ccefd1896e29acc40c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 10:10:49 +0000 Subject: [PATCH 106/207] fix(deps): update dependency @codemirror/view to v6.20.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 29aa1732c4..94c3110421 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10477,13 +10477,13 @@ __metadata: linkType: hard "@codemirror/view@npm:^6.0.0": - version: 6.20.1 - resolution: "@codemirror/view@npm:6.20.1" + version: 6.21.0 + resolution: "@codemirror/view@npm:6.21.0" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.1.0 w3c-keyname: ^2.2.4 - checksum: 6038b199c3a649cf01e1665eaac99b1b50db249f6480461e2202ac253f2833910d2495b6b53a6e4313458bd85a139afdb8f2a3a99355b82aab997d591aec315f + checksum: da49d5541b137a812e1837709130b9a4502fac71b87c45d45384116a7a2b1dab556c283abb673946ba9d044a640ab9058727b85de9b7b576c44848dfbf0ed7bb languageName: node linkType: hard From 3b5ed2ed06db67a665be627ce432602c1146f0e0 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 12:49:38 +0200 Subject: [PATCH 107/207] refactor(search-react): set search page as default attachment point Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/search-react/src/alpha.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/search-react/src/alpha.tsx b/plugins/search-react/src/alpha.tsx index 4b5bb79669..5b44a7bbb5 100644 --- a/plugins/search-react/src/alpha.tsx +++ b/plugins/search-react/src/alpha.tsx @@ -65,7 +65,7 @@ export type SearchResultItemExtensionOptions< /** * The extension attachment point (e.g., search modal or page). */ - at: string; + at?: string; /** * Optional extension config schema. */ @@ -97,7 +97,7 @@ export function createSearchResultListItemExtension< ) as PortableSchema<TConfig>); return createExtension({ id: `plugin.search.result.item.${options.id}`, - at: options.at, + at: options.at ?? 'plugin.search.page/items', configSchema, output: { item: searchResultItemExtensionData, From f5eeefc6eaee9a5a361e20531244dbf412431a31 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 13:15:06 +0200 Subject: [PATCH 108/207] refactor(search-react): set search page as default attachment point Signed-off-by: Camila Belo <camilaibs@gmail.com> --- .changeset/eighty-teachers-melt.md | 5 +++++ plugins/search-react/alpha-api-report.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/eighty-teachers-melt.md diff --git a/.changeset/eighty-teachers-melt.md b/.changeset/eighty-teachers-melt.md new file mode 100644 index 0000000000..f03b0a12e9 --- /dev/null +++ b/.changeset/eighty-teachers-melt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +Use search page as default attachment point for result item extensions. diff --git a/plugins/search-react/alpha-api-report.md b/plugins/search-react/alpha-api-report.md index 163247bf5e..d62a0f1f0e 100644 --- a/plugins/search-react/alpha-api-report.md +++ b/plugins/search-react/alpha-api-report.md @@ -48,7 +48,7 @@ export type SearchResultItemExtensionOptions< }, > = { id: string; - at: string; + at?: string; configSchema?: PortableSchema<TConfig>; component: (options: { config: TConfig; From 5aa87b46cf167166eeca70ad79639117d44c68cd Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 13:15:32 +0200 Subject: [PATCH 109/207] fix(search): forward all result set properties to the component Signed-off-by: Camila Belo <camilaibs@gmail.com> --- .changeset/smooth-pillows-greet.md | 5 +++++ plugins/search/src/alpha.tsx | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 .changeset/smooth-pillows-greet.md diff --git a/.changeset/smooth-pillows-greet.md b/.changeset/smooth-pillows-greet.md new file mode 100644 index 0000000000..d943dde95e --- /dev/null +++ b/.changeset/smooth-pillows-greet.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Forward all result set properties to item components, like highlights, for example. diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index 2a9a714abd..6d74c85d49 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -200,14 +200,16 @@ export const SearchPage = createPageExtension({ <SearchResults> {({ results }) => results.map((result, index) => { + const { noTrack } = config; + const { document, ...rest } = result; const SearchResultListItem = getResultItemComponent(result); return ( <SearchResultListItem + {...rest} key={index} - rank={result.rank} - result={result.document} - noTrack={config.noTrack} + result={document} + noTrack={noTrack} /> ); }) From dc5b6b971badbf8135b6f1ff288999d710edfc92 Mon Sep 17 00:00:00 2001 From: vdizengremel <victor.dizengremel@octo.com> Date: Fri, 29 Sep 2023 13:10:02 +0200 Subject: [PATCH 110/207] fix(#20232): load relations to get children of children and fix the display of OwnershipCard with aggregated relations. Signed-off-by: vdizengremel <victor.dizengremel@octo.com> --- .changeset/cold-bees-jam.md | 6 ++++++ .../components/Cards/OwnershipCard/useGetEntities.test.ts | 8 ++++++++ .../src/components/Cards/OwnershipCard/useGetEntities.ts | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 .changeset/cold-bees-jam.md diff --git a/.changeset/cold-bees-jam.md b/.changeset/cold-bees-jam.md new file mode 100644 index 0000000000..3c6e652d2b --- /dev/null +++ b/.changeset/cold-bees-jam.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-org': patch +--- + +Fixed the display of OwnershipCard with aggregated relations by loading relations when getting children of entity. +This allows the already existing recursive method to work properly when children of entity have children themselves. diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts index 191bd10284..4b9389a7d4 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts @@ -110,6 +110,14 @@ describe('useGetEntities', () => { ); }); + it('given group entity should retrieve child with their relations', async () => { + await whenHookIsCalledWith(givenParentGroupEntity); + expect(catalogApiMock.getEntitiesByRefs).toHaveBeenCalledWith({ + entityRefs: [`group:default/${givenLeafGroup}`], + fields: ['kind', 'metadata.namespace', 'metadata.name', 'relations'], + }); + }); + it('given user entity should aggregate parent ownership and direct', async () => { await whenHookIsCalledWith(givenUserEntity); expect(catalogApiMock.getEntities).toHaveBeenCalledWith( diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts index 1ff01cd8e1..337e926971 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts @@ -90,7 +90,7 @@ const getChildOwnershipEntityRefs = async ( if (hasChildGroups) { const entityRefs = childGroups.map(r => stringifyEntityRef(r)); const childGroupResponse = await catalogApi.getEntitiesByRefs({ - fields: ['kind', 'metadata.namespace', 'metadata.name'], + fields: ['kind', 'metadata.namespace', 'metadata.name', 'relations'], entityRefs, }); const childGroupEntities = childGroupResponse.items.filter(isEntity); From 96a01bd464dfd0a3d9c994528431e32f52838197 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth <tudi2d@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:29:34 +0200 Subject: [PATCH 111/207] Update publishing.md Signed-off-by: Philipp Hugenroth <tudi2d@users.noreply.github.com> --- docs/publishing.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/publishing.md b/docs/publishing.md index 3ffc29e6df..72603a829f 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -15,8 +15,8 @@ PR is merged. This is typically done every Tuesday around noon CET. ## Next Line Release Process -- PR Checks: Ensure there are no outstanding PRs pending to be merged for this version. If there are any, reach out to maintainers and relevant owners of the affected code reminding them of the deadline for the release. -- [optional] Lock main branch +- PR Checks: Notify the teams & ensure there are no outstanding PRs pending to be merged for this version. This should be done in time to ensure a smoothe release day. If there are any, reach out to maintainers and relevant owners of the affected code reminding them of the deadline for the release. +- [optional] Lock main branch - Lock the main branch to prevent any new merges. - Note: Admin rights are required to lock the branch. If you lack the necessary permissions, contact a core maintainer to perform this action on your behalf. - Check [`Version Packages (next)` Pull Request](https://github.com/backstage/backstage/pulls?q=is%3Aopen+is%3Apr+in%3Atitle+%22Version+Packages+%28next%29%22) @@ -32,6 +32,22 @@ PR is merged. This is typically done every Tuesday around noon CET. Merging the `Version Packages (next)` Pull Request will trigger the deployment workflows. Follow along the [deployment workflow](https://github.com/backstage/backstage/actions/workflows/deploy_packages.yml). If you notice flakiness (e.g. if the build is flaky or if the release step runs into an error with releasing to npm) just restart the workflow. +## Main Line Release Process + +Additional steps for the main line release + +- [Switch Release Mode](#switching-release-modes) to exit pre-release mode. This can be done at any time after the last Next Line Release. +- Check [`Version Packages` Pull Request](https://github.com/backstage/backstage/pulls?q=is%3Aopen+is%3Apr+in%3Atitle+%22Version+Packages) + - Check for mentions of "major" & "breaking" and if they are expected in the current release + - Verify the version we are shipping is correct + - Check [`.changeset/pre.json`](https://github.com/backstage/backstage/blob/master/.changeset/pre.json) if the `mode` is set to `exit`. If you encounter `mode: "pre"` it indicates a next line release. +- Create Release Notes + - There exists a "Backstage Release Notes" template for creating the release notes. It can already be created after the last main line release to keep track of major changes during the month. + - The content is picked by relevancy for the community showcasing the work of the community during the month before the release. + - @0.1.0 + +- [Switch Release Mode](#switching-release-modes) to enter pre-release mode + Congratulations on the release! There should be now a post in the [`#announcements` channel](https://discord.com/channels/687207715902193673/705123584468582400) in Discord linking to the release tag - check if links & tag look as expected. Finally unlock the main branch again. Merging PRs in master directly after release should be done with caution as it potential complicates fixing issues introduced in the release. ## Switching Release Modes From 934fdc0ecfbd91dfbfc9ab9a9f66ee4c690bf358 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth <tudi2d@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:14:57 +0200 Subject: [PATCH 112/207] Update docs/publishing.md Co-authored-by: Camila Belo <camilaibs@gmail.com> Signed-off-by: Philipp Hugenroth <tudi2d@users.noreply.github.com> --- docs/publishing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/publishing.md b/docs/publishing.md index 72603a829f..558e1c9141 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -15,7 +15,7 @@ PR is merged. This is typically done every Tuesday around noon CET. ## Next Line Release Process -- PR Checks: Notify the teams & ensure there are no outstanding PRs pending to be merged for this version. This should be done in time to ensure a smoothe release day. If there are any, reach out to maintainers and relevant owners of the affected code reminding them of the deadline for the release. +- PR Checks: Notify the teams & ensure there are no outstanding PRs pending to be merged for this version. This should be done in time to ensure a smooth release day. If there are any, reach out to maintainers and relevant owners of the affected code reminding them of the deadline for the release. - [optional] Lock main branch - Lock the main branch to prevent any new merges. - Note: Admin rights are required to lock the branch. If you lack the necessary permissions, contact a core maintainer to perform this action on your behalf. From 812c1f4c1666a0ef9e61d24ad128b403ccf5ca32 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth <tudi2d@users.noreply.github.com> Date: Thu, 28 Sep 2023 14:51:11 +0200 Subject: [PATCH 113/207] Update publishing.md Signed-off-by: Philipp Hugenroth <tudi2d@users.noreply.github.com> --- docs/publishing.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/publishing.md b/docs/publishing.md index 558e1c9141..6563addc97 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -16,8 +16,9 @@ PR is merged. This is typically done every Tuesday around noon CET. ## Next Line Release Process - PR Checks: Notify the teams & ensure there are no outstanding PRs pending to be merged for this version. This should be done in time to ensure a smooth release day. If there are any, reach out to maintainers and relevant owners of the affected code reminding them of the deadline for the release. -- [optional] Lock main branch - - Lock the main branch to prevent any new merges. +- Lock main branch + - Lock the main branch to prevent any new merges by other maintainers. Do not unlock the main branch until the release was published successfully + - Core maintainers can still merge last PRs using their admin override including the Version Packages PR - Note: Admin rights are required to lock the branch. If you lack the necessary permissions, contact a core maintainer to perform this action on your behalf. - Check [`Version Packages (next)` Pull Request](https://github.com/backstage/backstage/pulls?q=is%3Aopen+is%3Apr+in%3Atitle+%22Version+Packages+%28next%29%22) - Verify the version we are shipping is correct, by looking at the version packages PR title. It should be "Version Packages (next)" @@ -32,23 +33,28 @@ PR is merged. This is typically done every Tuesday around noon CET. Merging the `Version Packages (next)` Pull Request will trigger the deployment workflows. Follow along the [deployment workflow](https://github.com/backstage/backstage/actions/workflows/deploy_packages.yml). If you notice flakiness (e.g. if the build is flaky or if the release step runs into an error with releasing to npm) just restart the workflow. +Congratulations on the release! There should be now a post in the [`#announcements` channel](https://discord.com/channels/687207715902193673/705123584468582400) in Discord linking to the release tag - check if links & tag look as expected. Once the notification has gone out on Discord you can unlock the main branch & the release is complete. + ## Main Line Release Process Additional steps for the main line release - [Switch Release Mode](#switching-release-modes) to exit pre-release mode. This can be done at any time after the last Next Line Release. + - Check [`.changeset/pre.json`](https://github.com/backstage/backstage/blob/master/.changeset/pre.json) if the `mode` is set to `exit`. If you encounter `mode: "pre"` it indicates a next line release. - Check [`Version Packages` Pull Request](https://github.com/backstage/backstage/pulls?q=is%3Aopen+is%3Apr+in%3Atitle+%22Version+Packages) - Check for mentions of "major" & "breaking" and if they are expected in the current release - Verify the version we are shipping is correct - - Check [`.changeset/pre.json`](https://github.com/backstage/backstage/blob/master/.changeset/pre.json) if the `mode` is set to `exit`. If you encounter `mode: "pre"` it indicates a next line release. - Create Release Notes - - There exists a "Backstage Release Notes" template for creating the release notes. It can already be created after the last main line release to keep track of major changes during the month. - - The content is picked by relevancy for the community showcasing the work of the community during the month before the release. - - @0.1.0 - -- [Switch Release Mode](#switching-release-modes) to enter pre-release mode + - There exists a "Backstage Release Notes" template for creating the release notes. It can already be created after the last main line release to keep track of major changes during the month + - The content is picked by relevancy showcasing the work of the community during the month of the release + - Mention newly added packages or features + - Mention any security fixes +- Create Release Notes PR + - Add the release note file as [`/docs/releases/vx.y.0.md`](https://github.com/backstage/backstage/tree/master/docs/releases) + - Add an entry to [`/microsite/sidebar.json`](https://github.com/backstage/backstage/blob/master/microsite/sidebars.json) for the release note + - Update the navigation bar item in [`/microsite/docusaurus.config.js`](https://github.com/backstage/backstage/blob/master/microsite/docusaurus.config.js) to point to the new release note -Congratulations on the release! There should be now a post in the [`#announcements` channel](https://discord.com/channels/687207715902193673/705123584468582400) in Discord linking to the release tag - check if links & tag look as expected. Finally unlock the main branch again. Merging PRs in master directly after release should be done with caution as it potential complicates fixing issues introduced in the release. +Once the release has been published edit the newly created release in the [GitHub repository](https://github.com/backstage/backstage/releases) and replace the text content with the release notes. ## Switching Release Modes From 085cfdb18087771edc4f119924497038bd34f2db Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Fri, 29 Sep 2023 13:51:46 +0200 Subject: [PATCH 114/207] docs/publishing: update release notes template link Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- docs/publishing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/publishing.md b/docs/publishing.md index 6563addc97..9a0df7215b 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -16,7 +16,7 @@ PR is merged. This is typically done every Tuesday around noon CET. ## Next Line Release Process - PR Checks: Notify the teams & ensure there are no outstanding PRs pending to be merged for this version. This should be done in time to ensure a smooth release day. If there are any, reach out to maintainers and relevant owners of the affected code reminding them of the deadline for the release. -- Lock main branch +- Lock main branch - Lock the main branch to prevent any new merges by other maintainers. Do not unlock the main branch until the release was published successfully - Core maintainers can still merge last PRs using their admin override including the Version Packages PR - Note: Admin rights are required to lock the branch. If you lack the necessary permissions, contact a core maintainer to perform this action on your behalf. @@ -45,7 +45,7 @@ Additional steps for the main line release - Check for mentions of "major" & "breaking" and if they are expected in the current release - Verify the version we are shipping is correct - Create Release Notes - - There exists a "Backstage Release Notes" template for creating the release notes. It can already be created after the last main line release to keep track of major changes during the month + - There exists a [release notes template](https://github.com/backstage/backstage/blob/master/docs/release-notes-template.md) for creating the release notes. It can already be created after the last main line release to keep track of major changes during the month - The content is picked by relevancy showcasing the work of the community during the month of the release - Mention newly added packages or features - Mention any security fixes From 1b51bf1f157cb75c6684f96f4dfebb83c7f55f9c Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 13:57:05 +0200 Subject: [PATCH 115/207] chore: remove alpha changesets Signed-off-by: Camila Belo <camilaibs@gmail.com> --- .changeset/eighty-teachers-melt.md | 5 ----- .changeset/smooth-pillows-greet.md | 5 ----- 2 files changed, 10 deletions(-) delete mode 100644 .changeset/eighty-teachers-melt.md delete mode 100644 .changeset/smooth-pillows-greet.md diff --git a/.changeset/eighty-teachers-melt.md b/.changeset/eighty-teachers-melt.md deleted file mode 100644 index f03b0a12e9..0000000000 --- a/.changeset/eighty-teachers-melt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-react': patch ---- - -Use search page as default attachment point for result item extensions. diff --git a/.changeset/smooth-pillows-greet.md b/.changeset/smooth-pillows-greet.md deleted file mode 100644 index d943dde95e..0000000000 --- a/.changeset/smooth-pillows-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Forward all result set properties to item components, like highlights, for example. From 7ca09dc447518d9df363c1db40d26f7ca3a35284 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 12:20:07 +0000 Subject: [PATCH 116/207] fix(deps): update dependency @mui/material to v5.14.11 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 72 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/yarn.lock b/yarn.lock index f7e19c3179..848f2b150d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13356,14 +13356,14 @@ __metadata: languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.16": - version: 5.0.0-beta.16 - resolution: "@mui/base@npm:5.0.0-beta.16" +"@mui/base@npm:5.0.0-beta.17": + version: 5.0.0-beta.17 + resolution: "@mui/base@npm:5.0.0-beta.17" dependencies: "@babel/runtime": ^7.22.15 "@floating-ui/react-dom": ^2.0.2 "@mui/types": ^7.2.4 - "@mui/utils": ^5.14.10 + "@mui/utils": ^5.14.11 "@popperjs/core": ^2.11.8 clsx: ^2.0.0 prop-types: ^15.8.1 @@ -13374,27 +13374,27 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: b21589888c62d406feaae4f8f903a70cc847d1c64c812cab0bbb37662bda6e6256e3a8a75957f9133e743f7ff8c4770c263579cfc80241c2c34b2bc6abb819da + checksum: 96ffb85864fc796783514e089c0011ebcc5174705082dc98197ab035dfb287427069c0338e662a4680951849dfbe7a5231f4f6f2aee710af05c07e8578f93310 languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.14.10": - version: 5.14.10 - resolution: "@mui/core-downloads-tracker@npm:5.14.10" - checksum: 3332de82d72a0900fc8eaacef388b28f740a5d0a1cd8f335a7e08ac451e56fc1f8eb5183d0e956c069ff0cdda30105e9af37784983f9d2e625ad6c930394783d +"@mui/core-downloads-tracker@npm:^5.14.11": + version: 5.14.11 + resolution: "@mui/core-downloads-tracker@npm:5.14.11" + checksum: f3e7594c93d4cf5e3649336eef2b57842c171f3deb6890c03be7eccb88d3ac276aac1ab3ad409d124d16468314018778e2dbb92a62ac34c7f44b2813c47f29fb languageName: node linkType: hard "@mui/material@npm:^5.12.2": - version: 5.14.10 - resolution: "@mui/material@npm:5.14.10" + version: 5.14.11 + resolution: "@mui/material@npm:5.14.11" dependencies: "@babel/runtime": ^7.22.15 - "@mui/base": 5.0.0-beta.16 - "@mui/core-downloads-tracker": ^5.14.10 - "@mui/system": ^5.14.10 + "@mui/base": 5.0.0-beta.17 + "@mui/core-downloads-tracker": ^5.14.11 + "@mui/system": ^5.14.11 "@mui/types": ^7.2.4 - "@mui/utils": ^5.14.10 + "@mui/utils": ^5.14.11 "@types/react-transition-group": ^4.4.6 clsx: ^2.0.0 csstype: ^3.1.2 @@ -13414,16 +13414,16 @@ __metadata: optional: true "@types/react": optional: true - checksum: a093affbf25826e0932c3a07483b4c335bb54a7d5e84f563ed2ca861e8e6fb3e6385164fc29a9c8e55ad59be65b1fda06ca7ce9c7221e1d2e84436ffae8415f6 + checksum: 350d642773d4b19d5b9deac956203dafe89cd005ba8cd6017d1ab0e97ba45ca230050249f34a17f0f00efe466162d47487f160159bebe3e52af1b34dd28579d0 languageName: node linkType: hard -"@mui/private-theming@npm:^5.14.10": - version: 5.14.10 - resolution: "@mui/private-theming@npm:5.14.10" +"@mui/private-theming@npm:^5.14.11": + version: 5.14.11 + resolution: "@mui/private-theming@npm:5.14.11" dependencies: "@babel/runtime": ^7.22.15 - "@mui/utils": ^5.14.10 + "@mui/utils": ^5.14.11 prop-types: ^15.8.1 peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 @@ -13431,13 +13431,13 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 09681e1ada52a8635327ab2c6ad2488225173475a305444e3c9e2f932116418207b803be28561ac11316047b43fded8f5ccd3de1ee9399da8d95af3586695ce7 + checksum: a5d461ae9679b1f3b79f529c51c055e03d84421812bb12110d735fbc5528ae188900488b32aa1b860cb978ac6dd0cb9f54a10e2ff214e853e969ef5c1ed87e84 languageName: node linkType: hard -"@mui/styled-engine@npm:^5.14.10": - version: 5.14.10 - resolution: "@mui/styled-engine@npm:5.14.10" +"@mui/styled-engine@npm:^5.14.11": + version: 5.14.11 + resolution: "@mui/styled-engine@npm:5.14.11" dependencies: "@babel/runtime": ^7.22.15 "@emotion/cache": ^11.11.0 @@ -13452,19 +13452,19 @@ __metadata: optional: true "@emotion/styled": optional: true - checksum: 6e650caaa5395ef0611028e6691808a2a73cd4e777227183a13ef72740c7dc1716bdff79d5c6033bf5b2611d16790f02aa99a72ab1843686cb5df918df88733d + checksum: 0a593f967ab56c32c611eae4a83bc23c4ab3a8931e76a6e553ed18230c2f4e9e912d519fe2f0a24970ff154c198634903f134eb54f00ceebde138a73b953622f languageName: node linkType: hard -"@mui/system@npm:^5.14.10": - version: 5.14.10 - resolution: "@mui/system@npm:5.14.10" +"@mui/system@npm:^5.14.11": + version: 5.14.11 + resolution: "@mui/system@npm:5.14.11" dependencies: "@babel/runtime": ^7.22.15 - "@mui/private-theming": ^5.14.10 - "@mui/styled-engine": ^5.14.10 + "@mui/private-theming": ^5.14.11 + "@mui/styled-engine": ^5.14.11 "@mui/types": ^7.2.4 - "@mui/utils": ^5.14.10 + "@mui/utils": ^5.14.11 clsx: ^2.0.0 csstype: ^3.1.2 prop-types: ^15.8.1 @@ -13480,7 +13480,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 16046084c125b52bcff38d4775bb2ed83ff39b46ee3b3c4b7dc9437f549ed2971343ee2035132f9bff7f5a198849622af2404ca674b2f3c142b6d343ab7f2d0e + checksum: c3d0e1a09a9638663a6467452a7725593e9de6f9620e199add1080db42a7affaca39f52a1b6a52fb75d708f3e30336946babb2a8d1d43fab81c6a1fe3e420b21 languageName: node linkType: hard @@ -13496,9 +13496,9 @@ __metadata: languageName: node linkType: hard -"@mui/utils@npm:^5.14.10": - version: 5.14.10 - resolution: "@mui/utils@npm:5.14.10" +"@mui/utils@npm:^5.14.11": + version: 5.14.11 + resolution: "@mui/utils@npm:5.14.11" dependencies: "@babel/runtime": ^7.22.15 "@types/prop-types": ^15.7.5 @@ -13510,7 +13510,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: ca2405da33bbbcaa01caebc7c9f3a7d55dd56ffb286f17362c93b2382326679cbc0d7f318ea9307907d669d359b2b01000e136557c7af9126f3849f324e73ea6 + checksum: 84e640dea3589ea7edb7d8f33748d83d561d4ef413c4d3e2216ddf9c0842d8b04d162e3fa5ea59f03846934f17fb446ed8464e318dd4e2e299e3b44b06637d76 languageName: node linkType: hard From 015cf13addf881bb794683a8ab7faf2e8ab66535 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 12:20:45 +0000 Subject: [PATCH 117/207] fix(deps): update dependency @roadiehq/backstage-plugin-buildkite to v2.1.15 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index f7e19c3179..84abe77e1c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14720,14 +14720,14 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-buildkite@npm:^2.0.8": - version: 2.1.14 - resolution: "@roadiehq/backstage-plugin-buildkite@npm:2.1.14" + version: 2.1.15 + resolution: "@roadiehq/backstage-plugin-buildkite@npm:2.1.15" dependencies: - "@backstage/catalog-model": ^1.4.1 - "@backstage/core-components": ^0.13.4 - "@backstage/core-plugin-api": ^1.5.3 - "@backstage/plugin-catalog-react": ^1.8.3 - "@backstage/theme": ^0.4.1 + "@backstage/catalog-model": ^1.4.2 + "@backstage/core-components": ^0.13.5 + "@backstage/core-plugin-api": ^1.6.0 + "@backstage/plugin-catalog-react": ^1.8.4 + "@backstage/theme": ^0.4.2 "@material-ui/core": ^4.12.1 "@material-ui/icons": ^4.11.2 "@material-ui/lab": 4.0.0-alpha.57 @@ -14739,7 +14739,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: 938fa38d6199a1c5199eb47851ddc0edb2f0d3064fa189baf104ff820096700cb95843c499353efc77b10c1fc721aa2a32b0146c1d3df1bea31f5af61dfd250b + checksum: 421a3e444b6c5945748d0842bc777efc9fe0e968dad3c59cdc0cbbcd841752bcf47d757f2fc307fa1245da884adfeb3e478cd23b2bb318f621e05ffa7c6ec21b languageName: node linkType: hard From f5bc022d0638782eede92ff7a45180e037e7a041 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 13:42:05 +0000 Subject: [PATCH 118/207] fix(deps): update dependency @roadiehq/backstage-plugin-github-insights to v2.3.21 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index f7e19c3179..f65af6bbbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4358,7 +4358,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-react@npm:^1.1.18": +"@backstage/integration-react@npm:^1.1.19": version: 1.1.19 resolution: "@backstage/integration-react@npm:1.1.19" dependencies: @@ -14744,15 +14744,15 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-github-insights@npm:^2.0.5": - version: 2.3.20 - resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.20" + version: 2.3.21 + resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.21" dependencies: - "@backstage/catalog-model": ^1.4.1 - "@backstage/core-components": ^0.13.4 - "@backstage/core-plugin-api": ^1.5.3 - "@backstage/integration-react": ^1.1.18 - "@backstage/plugin-catalog-react": ^1.8.3 - "@backstage/theme": ^0.4.1 + "@backstage/catalog-model": ^1.4.2 + "@backstage/core-components": ^0.13.5 + "@backstage/core-plugin-api": ^1.6.0 + "@backstage/integration-react": ^1.1.19 + "@backstage/plugin-catalog-react": ^1.8.4 + "@backstage/theme": ^0.4.2 "@date-io/core": 2.10.7 "@material-ui/core": ^4.11.0 "@material-ui/icons": ^4.9.1 @@ -14767,7 +14767,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: 187483c88f7a34757cb9cc6b9bac343bfd1853e634957f71049fe448b03a1e631456f1bc31be3aa91c41976a812ae24e522fc374faf33507e3db80fc1e54cdd2 + checksum: edb0ecee1778e0bacd1eff395aa723fef35338253a7f8e91ab93b5755b9ebac27e49e1768ee13163ade74edf0b0f620ab31b693674c746c3c1e35e1185f46636 languageName: node linkType: hard From ef91e31cee43d1c3ca83229162f3142c34d67149 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 13:42:38 +0000 Subject: [PATCH 119/207] fix(deps): update dependency @roadiehq/backstage-plugin-github-pull-requests to v2.5.16 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/yarn.lock b/yarn.lock index f7e19c3179..3f6d6eaa04 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7342,7 +7342,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-home@npm:^0.5.7": +"@backstage/plugin-home@npm:^0.5.8": version: 0.5.8 resolution: "@backstage/plugin-home@npm:0.5.8" dependencies: @@ -14772,14 +14772,14 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-github-pull-requests@npm:^2.2.7": - version: 2.5.15 - resolution: "@roadiehq/backstage-plugin-github-pull-requests@npm:2.5.15" + version: 2.5.16 + resolution: "@roadiehq/backstage-plugin-github-pull-requests@npm:2.5.16" dependencies: - "@backstage/catalog-model": ^1.4.1 - "@backstage/core-components": ^0.13.4 - "@backstage/core-plugin-api": ^1.5.3 - "@backstage/plugin-catalog-react": ^1.8.3 - "@backstage/plugin-home": ^0.5.7 + "@backstage/catalog-model": ^1.4.2 + "@backstage/core-components": ^0.13.5 + "@backstage/core-plugin-api": ^1.6.0 + "@backstage/plugin-catalog-react": ^1.8.4 + "@backstage/plugin-home": ^0.5.8 "@material-ui/core": ^4.11.0 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.60 @@ -14796,7 +14796,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: 3332a560f8741536ab12ff1e14567e739aa6f60767d8eb0a2e5b9873b54947b0cdaac7c44cb5bb3156dc8b2a7d88d33ee20191c8920bfe8f67b87857dfda2780 + checksum: cb35e64d4df6f81829cd238e3b06b84453ad9231a30a0a4698ebb9d408445af0bfeb59d27bcc5d818013735f2f4d44a89ff9824258ff1565274c524c3ae905cc languageName: node linkType: hard From 8143bac2a44544110446adac3b9a6a7d552af90d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 14:08:59 +0000 Subject: [PATCH 120/207] fix(deps): update dependency @roadiehq/backstage-plugin-travis-ci to v2.1.15 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index f7e19c3179..a79633dcd9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14801,14 +14801,14 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-travis-ci@npm:^2.0.5": - version: 2.1.14 - resolution: "@roadiehq/backstage-plugin-travis-ci@npm:2.1.14" + version: 2.1.15 + resolution: "@roadiehq/backstage-plugin-travis-ci@npm:2.1.15" dependencies: - "@backstage/catalog-model": ^1.4.1 - "@backstage/core-components": ^0.13.4 - "@backstage/core-plugin-api": ^1.5.3 - "@backstage/plugin-catalog-react": ^1.8.3 - "@backstage/theme": ^0.4.1 + "@backstage/catalog-model": ^1.4.2 + "@backstage/core-components": ^0.13.5 + "@backstage/core-plugin-api": ^1.6.0 + "@backstage/plugin-catalog-react": ^1.8.4 + "@backstage/theme": ^0.4.2 "@material-ui/core": ^4.11.3 "@material-ui/icons": ^4.11.2 "@material-ui/lab": 4.0.0-alpha.57 @@ -14822,7 +14822,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: f6e297460aa2dccd3ac5b639838a253017229ecf6ec03541702ccb33f93ec15327894e35f7dfa565bc58c137abfd94129a858d43b2b861283370a003b2685dda + checksum: f285fa074049bb1d03adc3e04467a3700c3651550fc3304038c9169438e1bd3e12790309be9a86cfb76a97f53925165d6b91ab4d81985ce5bb2faa97e5b10b00 languageName: node linkType: hard From d06334c977e736ada7ffce2e38b8fe16ed3f265a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 14:12:03 +0000 Subject: [PATCH 121/207] fix(deps): update dependency @swc/core to v1.3.90 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- microsite/yarn.lock | 104 ++++++++++++++++++++++++-------------------- storybook/yarn.lock | 104 ++++++++++++++++++++++++-------------------- yarn.lock | 104 ++++++++++++++++++++++++-------------------- 3 files changed, 168 insertions(+), 144 deletions(-) diff --git a/microsite/yarn.lock b/microsite/yarn.lock index d94e257c41..27b077b8da 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -2604,91 +2604,92 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-darwin-arm64@npm:1.3.87" +"@swc/core-darwin-arm64@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-darwin-arm64@npm:1.3.90" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-darwin-x64@npm:1.3.87" +"@swc/core-darwin-x64@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-darwin-x64@npm:1.3.90" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.87" +"@swc/core-linux-arm-gnueabihf@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.90" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.87" +"@swc/core-linux-arm64-gnu@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.90" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.87" +"@swc/core-linux-arm64-musl@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.90" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.87" +"@swc/core-linux-x64-gnu@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.90" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-x64-musl@npm:1.3.87" +"@swc/core-linux-x64-musl@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-x64-musl@npm:1.3.90" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.87" +"@swc/core-win32-arm64-msvc@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.90" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.87" +"@swc/core-win32-ia32-msvc@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.90" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.87" +"@swc/core-win32-x64-msvc@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.90" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.3.87 - resolution: "@swc/core@npm:1.3.87" + version: 1.3.90 + resolution: "@swc/core@npm:1.3.90" dependencies: - "@swc/core-darwin-arm64": 1.3.87 - "@swc/core-darwin-x64": 1.3.87 - "@swc/core-linux-arm-gnueabihf": 1.3.87 - "@swc/core-linux-arm64-gnu": 1.3.87 - "@swc/core-linux-arm64-musl": 1.3.87 - "@swc/core-linux-x64-gnu": 1.3.87 - "@swc/core-linux-x64-musl": 1.3.87 - "@swc/core-win32-arm64-msvc": 1.3.87 - "@swc/core-win32-ia32-msvc": 1.3.87 - "@swc/core-win32-x64-msvc": 1.3.87 - "@swc/types": ^0.1.4 + "@swc/core-darwin-arm64": 1.3.90 + "@swc/core-darwin-x64": 1.3.90 + "@swc/core-linux-arm-gnueabihf": 1.3.90 + "@swc/core-linux-arm64-gnu": 1.3.90 + "@swc/core-linux-arm64-musl": 1.3.90 + "@swc/core-linux-x64-gnu": 1.3.90 + "@swc/core-linux-x64-musl": 1.3.90 + "@swc/core-win32-arm64-msvc": 1.3.90 + "@swc/core-win32-ia32-msvc": 1.3.90 + "@swc/core-win32-x64-msvc": 1.3.90 + "@swc/counter": ^0.1.1 + "@swc/types": ^0.1.5 peerDependencies: "@swc/helpers": ^0.5.0 dependenciesMeta: @@ -2715,14 +2716,21 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: f10f0f22c7cbe1352482ccd05c95c39abb7ded8c9a04f4bf66b2a1977ba524b5b5174f6bc497665e0c6058078c8a9eca0e5035f4926d98f9dfea331032488270 + checksum: f8ced5187068dc73445c135065c6492f0ac559d0f7720c2482aa9663c87bd015f3d2abef6ee7b2f817280a5e8dd0946c59cce7e1499180644fbc948a9e3823ab languageName: node linkType: hard -"@swc/types@npm:^0.1.4": - version: 0.1.4 - resolution: "@swc/types@npm:0.1.4" - checksum: 9b09de7dca8e4b19bfb43f9e332c771855158cb761d26000807fe858447ecbc5342a6c257b26d9aa5497f7138fc58913693e2bee222e5042e0e8f57c2979ae66 +"@swc/counter@npm:^0.1.1": + version: 0.1.1 + resolution: "@swc/counter@npm:0.1.1" + checksum: bb974babd493ba01c0d4a95ab610c3fc15fbf609c08cb0342798e485f57ecc0950abbf84e07124e63c5fe610b492d9a8dd03701d3b9ef7329d9e8bf3cc44980f + languageName: node + linkType: hard + +"@swc/types@npm:^0.1.5": + version: 0.1.5 + resolution: "@swc/types@npm:0.1.5" + checksum: 6aee11f62d3d805a64848e0bd5f0e0e615f958e327a9e1260056c368d7d28764d89e38bd8005a536c9bf18afbcd303edd84099d60df34a2975d62540f61df13b languageName: node linkType: hard diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 1899c17db2..e0f77cd510 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -2840,91 +2840,92 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-darwin-arm64@npm:1.3.87" +"@swc/core-darwin-arm64@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-darwin-arm64@npm:1.3.90" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-darwin-x64@npm:1.3.87" +"@swc/core-darwin-x64@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-darwin-x64@npm:1.3.90" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.87" +"@swc/core-linux-arm-gnueabihf@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.90" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.87" +"@swc/core-linux-arm64-gnu@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.90" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.87" +"@swc/core-linux-arm64-musl@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.90" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.87" +"@swc/core-linux-x64-gnu@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.90" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-x64-musl@npm:1.3.87" +"@swc/core-linux-x64-musl@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-x64-musl@npm:1.3.90" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.87" +"@swc/core-win32-arm64-msvc@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.90" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.87" +"@swc/core-win32-ia32-msvc@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.90" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.87" +"@swc/core-win32-x64-msvc@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.90" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.3.87 - resolution: "@swc/core@npm:1.3.87" + version: 1.3.90 + resolution: "@swc/core@npm:1.3.90" dependencies: - "@swc/core-darwin-arm64": 1.3.87 - "@swc/core-darwin-x64": 1.3.87 - "@swc/core-linux-arm-gnueabihf": 1.3.87 - "@swc/core-linux-arm64-gnu": 1.3.87 - "@swc/core-linux-arm64-musl": 1.3.87 - "@swc/core-linux-x64-gnu": 1.3.87 - "@swc/core-linux-x64-musl": 1.3.87 - "@swc/core-win32-arm64-msvc": 1.3.87 - "@swc/core-win32-ia32-msvc": 1.3.87 - "@swc/core-win32-x64-msvc": 1.3.87 - "@swc/types": ^0.1.4 + "@swc/core-darwin-arm64": 1.3.90 + "@swc/core-darwin-x64": 1.3.90 + "@swc/core-linux-arm-gnueabihf": 1.3.90 + "@swc/core-linux-arm64-gnu": 1.3.90 + "@swc/core-linux-arm64-musl": 1.3.90 + "@swc/core-linux-x64-gnu": 1.3.90 + "@swc/core-linux-x64-musl": 1.3.90 + "@swc/core-win32-arm64-msvc": 1.3.90 + "@swc/core-win32-ia32-msvc": 1.3.90 + "@swc/core-win32-x64-msvc": 1.3.90 + "@swc/counter": ^0.1.1 + "@swc/types": ^0.1.5 peerDependencies: "@swc/helpers": ^0.5.0 dependenciesMeta: @@ -2951,14 +2952,21 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: f10f0f22c7cbe1352482ccd05c95c39abb7ded8c9a04f4bf66b2a1977ba524b5b5174f6bc497665e0c6058078c8a9eca0e5035f4926d98f9dfea331032488270 + checksum: f8ced5187068dc73445c135065c6492f0ac559d0f7720c2482aa9663c87bd015f3d2abef6ee7b2f817280a5e8dd0946c59cce7e1499180644fbc948a9e3823ab languageName: node linkType: hard -"@swc/types@npm:^0.1.4": - version: 0.1.4 - resolution: "@swc/types@npm:0.1.4" - checksum: 9b09de7dca8e4b19bfb43f9e332c771855158cb761d26000807fe858447ecbc5342a6c257b26d9aa5497f7138fc58913693e2bee222e5042e0e8f57c2979ae66 +"@swc/counter@npm:^0.1.1": + version: 0.1.1 + resolution: "@swc/counter@npm:0.1.1" + checksum: bb974babd493ba01c0d4a95ab610c3fc15fbf609c08cb0342798e485f57ecc0950abbf84e07124e63c5fe610b492d9a8dd03701d3b9ef7329d9e8bf3cc44980f + languageName: node + linkType: hard + +"@swc/types@npm:^0.1.5": + version: 0.1.5 + resolution: "@swc/types@npm:0.1.5" + checksum: 6aee11f62d3d805a64848e0bd5f0e0e615f958e327a9e1260056c368d7d28764d89e38bd8005a536c9bf18afbcd303edd84099d60df34a2975d62540f61df13b languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index f7e19c3179..ce2e60deb2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16484,91 +16484,92 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-darwin-arm64@npm:1.3.87" +"@swc/core-darwin-arm64@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-darwin-arm64@npm:1.3.90" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-darwin-x64@npm:1.3.87" +"@swc/core-darwin-x64@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-darwin-x64@npm:1.3.90" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.87" +"@swc/core-linux-arm-gnueabihf@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.90" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.87" +"@swc/core-linux-arm64-gnu@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.90" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.87" +"@swc/core-linux-arm64-musl@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.90" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.87" +"@swc/core-linux-x64-gnu@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.90" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-linux-x64-musl@npm:1.3.87" +"@swc/core-linux-x64-musl@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-linux-x64-musl@npm:1.3.90" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.87" +"@swc/core-win32-arm64-msvc@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.90" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.87" +"@swc/core-win32-ia32-msvc@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.90" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.87": - version: 1.3.87 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.87" +"@swc/core-win32-x64-msvc@npm:1.3.90": + version: 1.3.90 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.90" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.3.87 - resolution: "@swc/core@npm:1.3.87" + version: 1.3.90 + resolution: "@swc/core@npm:1.3.90" dependencies: - "@swc/core-darwin-arm64": 1.3.87 - "@swc/core-darwin-x64": 1.3.87 - "@swc/core-linux-arm-gnueabihf": 1.3.87 - "@swc/core-linux-arm64-gnu": 1.3.87 - "@swc/core-linux-arm64-musl": 1.3.87 - "@swc/core-linux-x64-gnu": 1.3.87 - "@swc/core-linux-x64-musl": 1.3.87 - "@swc/core-win32-arm64-msvc": 1.3.87 - "@swc/core-win32-ia32-msvc": 1.3.87 - "@swc/core-win32-x64-msvc": 1.3.87 - "@swc/types": ^0.1.4 + "@swc/core-darwin-arm64": 1.3.90 + "@swc/core-darwin-x64": 1.3.90 + "@swc/core-linux-arm-gnueabihf": 1.3.90 + "@swc/core-linux-arm64-gnu": 1.3.90 + "@swc/core-linux-arm64-musl": 1.3.90 + "@swc/core-linux-x64-gnu": 1.3.90 + "@swc/core-linux-x64-musl": 1.3.90 + "@swc/core-win32-arm64-msvc": 1.3.90 + "@swc/core-win32-ia32-msvc": 1.3.90 + "@swc/core-win32-x64-msvc": 1.3.90 + "@swc/counter": ^0.1.1 + "@swc/types": ^0.1.5 peerDependencies: "@swc/helpers": ^0.5.0 dependenciesMeta: @@ -16595,7 +16596,14 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: f10f0f22c7cbe1352482ccd05c95c39abb7ded8c9a04f4bf66b2a1977ba524b5b5174f6bc497665e0c6058078c8a9eca0e5035f4926d98f9dfea331032488270 + checksum: f8ced5187068dc73445c135065c6492f0ac559d0f7720c2482aa9663c87bd015f3d2abef6ee7b2f817280a5e8dd0946c59cce7e1499180644fbc948a9e3823ab + languageName: node + linkType: hard + +"@swc/counter@npm:^0.1.1": + version: 0.1.1 + resolution: "@swc/counter@npm:0.1.1" + checksum: bb974babd493ba01c0d4a95ab610c3fc15fbf609c08cb0342798e485f57ecc0950abbf84e07124e63c5fe610b492d9a8dd03701d3b9ef7329d9e8bf3cc44980f languageName: node linkType: hard @@ -16620,10 +16628,10 @@ __metadata: languageName: node linkType: hard -"@swc/types@npm:^0.1.4": - version: 0.1.4 - resolution: "@swc/types@npm:0.1.4" - checksum: 9b09de7dca8e4b19bfb43f9e332c771855158cb761d26000807fe858447ecbc5342a6c257b26d9aa5497f7138fc58913693e2bee222e5042e0e8f57c2979ae66 +"@swc/types@npm:^0.1.5": + version: 0.1.5 + resolution: "@swc/types@npm:0.1.5" + checksum: 6aee11f62d3d805a64848e0bd5f0e0e615f958e327a9e1260056c368d7d28764d89e38bd8005a536c9bf18afbcd303edd84099d60df34a2975d62540f61df13b languageName: node linkType: hard From f302e150803200dd189b61e6e49339a3ea2b2909 Mon Sep 17 00:00:00 2001 From: Christoph Jerolimov <jerolimov+github@redhat.com> Date: Fri, 29 Sep 2023 16:52:54 +0200 Subject: [PATCH 122/207] Update proxying.md Add endpoints to the proxy examples, as used in the sample app-config.yaml Signed-off-by: Christoph Jerolimov <jerolimov+github@redhat.com> --- docs/plugins/proxying.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/plugins/proxying.md b/docs/plugins/proxying.md index 442721a355..40d155e13b 100644 --- a/docs/plugins/proxying.md +++ b/docs/plugins/proxying.md @@ -36,13 +36,14 @@ Example: ```yaml # in app-config.yaml proxy: - /simple-example: http://simple.example.com:8080 - '/larger-example/v1': - target: http://larger.example.com:8080/svc.v1 - headers: - Authorization: ${EXAMPLE_AUTH_HEADER} - # ...or interpolating a value into part of a string, - # Authorization: Bearer ${EXAMPLE_AUTH_TOKEN} + endpoints: + /simple-example: http://simple.example.com:8080 + '/larger-example/v1': + target: http://larger.example.com:8080/svc.v1 + headers: + Authorization: ${EXAMPLE_AUTH_HEADER} + # ...or interpolating a value into part of a string, + # Authorization: Bearer ${EXAMPLE_AUTH_TOKEN} ``` Each key under the proxy configuration entry is a route to match, below the From 52366db5b36ac3d46e8075e69d5d8b893f48463c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Fri, 29 Sep 2023 15:31:52 +0200 Subject: [PATCH 123/207] frontend-*-api: add support for theme extensions Co-authored-by: Camila Belo <camilaibs@gmail.com> Co-authored-by: Vincenzo Scamporlino <vincenzos@spotify.com> Co-authored-by: Philipp Hugenroth <philipph@spotify.com> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/nervous-hounds-sleep.md | 5 +++ .changeset/silly-swans-invent.md | 5 +++ packages/frontend-app-api/package.json | 5 ++- .../src/extensions/themes.tsx | 44 +++++++++++++++++++ .../src/wiring/createApp.test.tsx | 37 ++++++++++++++-- .../frontend-app-api/src/wiring/createApp.tsx | 20 +++++++-- packages/frontend-plugin-api/api-report.md | 5 +++ .../src/extensions/createThemeExtension.ts | 32 ++++++++++++++ .../src/extensions/index.ts | 1 + .../src/wiring/coreExtensionData.ts | 2 + yarn.lock | 3 ++ 11 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 .changeset/nervous-hounds-sleep.md create mode 100644 .changeset/silly-swans-invent.md create mode 100644 packages/frontend-app-api/src/extensions/themes.tsx create mode 100644 packages/frontend-plugin-api/src/extensions/createThemeExtension.ts diff --git a/.changeset/nervous-hounds-sleep.md b/.changeset/nervous-hounds-sleep.md new file mode 100644 index 0000000000..530ff348f7 --- /dev/null +++ b/.changeset/nervous-hounds-sleep.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Make themes configurable through extensions, and switched default themes to use extensions instead. diff --git a/.changeset/silly-swans-invent.md b/.changeset/silly-swans-invent.md new file mode 100644 index 0000000000..68b094aba7 --- /dev/null +++ b/.changeset/silly-swans-invent.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Added `createThemeExtension` and `coreExtensionData.theme`. diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index 0982cb0157..6c45e9239a 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -25,7 +25,8 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1" + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3" }, "configSchema": "config.d.ts", "files": [ @@ -39,8 +40,10 @@ "@backstage/core-plugin-api": "workspace:^", "@backstage/frontend-plugin-api": "workspace:^", "@backstage/plugin-graphiql": "workspace:^", + "@backstage/theme": "workspace:^", "@backstage/types": "workspace:^", "@material-ui/core": "^4.12.4", + "@material-ui/icons": "^4.11.3", "@types/react": "^16.13.1 || ^17.0.0", "lodash": "^4.17.21" }, diff --git a/packages/frontend-app-api/src/extensions/themes.tsx b/packages/frontend-app-api/src/extensions/themes.tsx new file mode 100644 index 0000000000..ea11b6a638 --- /dev/null +++ b/packages/frontend-app-api/src/extensions/themes.tsx @@ -0,0 +1,44 @@ +/* + * 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 { + UnifiedThemeProvider, + themes as builtinThemes, +} from '@backstage/theme'; +import DarkIcon from '@material-ui/icons/Brightness2'; +import LightIcon from '@material-ui/icons/WbSunny'; +import { createThemeExtension } from '@backstage/frontend-plugin-api'; + +export const LightTheme = createThemeExtension({ + id: 'light', + title: 'Light Theme', + variant: 'light', + icon: <LightIcon />, + Provider: ({ children }) => ( + <UnifiedThemeProvider theme={builtinThemes.light} children={children} /> + ), +}); + +export const DarkTheme = createThemeExtension({ + id: 'dark', + title: 'Dark Theme', + variant: 'dark', + icon: <DarkIcon />, + Provider: ({ children }) => ( + <UnifiedThemeProvider theme={builtinThemes.dark} children={children} /> + ), +}); diff --git a/packages/frontend-app-api/src/wiring/createApp.test.tsx b/packages/frontend-app-api/src/wiring/createApp.test.tsx index 903b044ed3..f6172f5a4b 100644 --- a/packages/frontend-app-api/src/wiring/createApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.test.tsx @@ -18,10 +18,11 @@ import { createExtension, createPageExtension, createPlugin, + createThemeExtension, } from '@backstage/frontend-plugin-api'; -import { createInstances } from './createApp'; - -import { MockConfigApi } from '@backstage/test-utils'; +import { createApp, createInstances } from './createApp'; +import { screen } from '@testing-library/react'; +import { MockConfigApi, renderWithEffects } from '@backstage/test-utils'; import React from 'react'; import { createRouteRef } from '@backstage/core-plugin-api'; @@ -104,3 +105,33 @@ describe('createInstances', () => { ); }); }); + +describe('createApp', () => { + it('should allow themes to be installed', async () => { + const app = createApp({ + configLoader: async () => + new MockConfigApi({ + app: { + extensions: [{ 'themes.light': false }, { 'themes.dark': false }], + }, + }), + plugins: [ + createPlugin({ + id: 'test', + extensions: [ + createThemeExtension({ + id: 'derp', + title: 'Derp', + variant: 'dark', + Provider: () => <div>Derp</div>, + }), + ], + }), + ], + }); + + await renderWithEffects(app.createRoot()); + + await expect(screen.findByText('Derp')).resolves.toBeInTheDocument(); + }); +}); diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index dc7db79022..deb19d919d 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -50,6 +50,7 @@ import { attachComponentData, useRouteRef, identityApiRef, + AppTheme, } from '@backstage/core-plugin-api'; import { getAvailablePlugins } from './discovery'; import { @@ -77,10 +78,10 @@ import { apis as defaultApis, components as defaultComponents, icons as defaultIcons, - themes as defaultThemes, } from '../../../app-defaults/src/defaults'; import { BrowserRouter, Route } from 'react-router-dom'; import { SidebarItem } from '@backstage/core-components'; +import { DarkTheme, LightTheme } from '../extensions/themes'; /** @public */ export interface ExtensionTreeNode { @@ -171,7 +172,14 @@ export function createInstances(options: { plugins: BackstagePlugin[]; config: Config; }) { - const builtinExtensions = [Core, CoreRoutes, CoreNav, CoreLayout]; + const builtinExtensions = [ + Core, + CoreRoutes, + CoreNav, + CoreLayout, + LightTheme, + DarkTheme, + ]; // pull in default extension instance from discovered packages // apply config to adjust default extension instances and add more @@ -375,6 +383,12 @@ function createApiHolder( ?.map(e => e.getData(coreExtensionData.apiFactory)) .filter((x): x is AnyApiFactory => !!x) ?? []; + const themeExtensions = + coreExtension.attachments + .get('themes') + ?.map(e => e.getData(coreExtensionData.theme)) + .filter((x): x is AppTheme => !!x) ?? []; + for (const factory of [...defaultApis, ...pluginApis]) { factoryRegistry.register('default', factory); } @@ -422,7 +436,7 @@ function createApiHolder( api: appThemeApiRef, deps: {}, // TODO: add extension for registering themes - factory: () => AppThemeSelector.createWithStorage(defaultThemes), + factory: () => AppThemeSelector.createWithStorage(themeExtensions), }); factoryRegistry.register('static', { diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 5855976bc4..e28d7d5993 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -7,6 +7,7 @@ import { AnyApiFactory } from '@backstage/core-plugin-api'; import { AnyApiRef } from '@backstage/core-plugin-api'; +import { AppTheme } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { JSX as JSX_2 } from 'react'; @@ -71,6 +72,7 @@ export const coreExtensionData: { apiFactory: ConfigurableExtensionDataRef<AnyApiFactory, {}>; routeRef: ConfigurableExtensionDataRef<RouteRef, {}>; navTarget: ConfigurableExtensionDataRef<NavTarget, {}>; + theme: ConfigurableExtensionDataRef<AppTheme, {}>; }; // @public (undocumented) @@ -199,6 +201,9 @@ export function createSchemaFromZod<TOutput, TInput>( schemaCreator: (zImpl: typeof z) => ZodSchema<TOutput, ZodTypeDef, TInput>, ): PortableSchema<TOutput>; +// @public (undocumented) +export function createThemeExtension(theme: AppTheme): Extension<never>; + // @public (undocumented) export interface Extension<TConfig> { // (undocumented) diff --git a/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts b/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts new file mode 100644 index 0000000000..5c13dd199e --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts @@ -0,0 +1,32 @@ +/* + * 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 { createExtension, coreExtensionData } from '../wiring'; +import { AppTheme } from '@backstage/core-plugin-api'; + +/** @public */ +export function createThemeExtension(theme: AppTheme) { + return createExtension({ + id: `themes.${theme.id}`, + at: 'core/themes', + output: { + theme: coreExtensionData.theme, + }, + factory({ bind }) { + bind({ theme }); + }, + }); +} diff --git a/packages/frontend-plugin-api/src/extensions/index.ts b/packages/frontend-plugin-api/src/extensions/index.ts index 0ec0cdf652..00cf4f919c 100644 --- a/packages/frontend-plugin-api/src/extensions/index.ts +++ b/packages/frontend-plugin-api/src/extensions/index.ts @@ -17,3 +17,4 @@ export { createApiExtension } from './createApiExtension'; export { createPageExtension } from './createPageExtension'; export { createNavItemExtension } from './createNavItemExtension'; +export { createThemeExtension } from './createThemeExtension'; diff --git a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts index 079d5bcb18..6913501907 100644 --- a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts +++ b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts @@ -17,6 +17,7 @@ import { JSX } from 'react'; import { AnyApiFactory, + AppTheme, IconComponent, RouteRef, } from '@backstage/core-plugin-api'; @@ -36,4 +37,5 @@ export const coreExtensionData = { apiFactory: createExtensionDataRef<AnyApiFactory>('core.api.factory'), routeRef: createExtensionDataRef<RouteRef>('core.routing.ref'), navTarget: createExtensionDataRef<NavTarget>('core.nav.target'), + theme: createExtensionDataRef<AppTheme>('core.theme'), }; diff --git a/yarn.lock b/yarn.lock index f7e19c3179..3dd3f6315b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4307,9 +4307,12 @@ __metadata: "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-graphiql": "workspace:^" "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" "@backstage/types": "workspace:^" "@material-ui/core": ^4.12.4 + "@material-ui/icons": ^4.11.3 "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 "@types/react": ^16.13.1 || ^17.0.0 lodash: ^4.17.21 peerDependencies: From 19e9b4d4ef291d8cbf3626d05bda6b8c2b087a8b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Fri, 29 Sep 2023 18:08:59 +0200 Subject: [PATCH 124/207] docs/publishing: update to use relative URLs Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- docs/publishing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/publishing.md b/docs/publishing.md index 9a0df7215b..2424bc1352 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -45,12 +45,12 @@ Additional steps for the main line release - Check for mentions of "major" & "breaking" and if they are expected in the current release - Verify the version we are shipping is correct - Create Release Notes - - There exists a [release notes template](https://github.com/backstage/backstage/blob/master/docs/release-notes-template.md) for creating the release notes. It can already be created after the last main line release to keep track of major changes during the month + - There exists a [release notes template](./release-notes-template.md) for creating the release notes. It can already be created after the last main line release to keep track of major changes during the month - The content is picked by relevancy showcasing the work of the community during the month of the release - Mention newly added packages or features - Mention any security fixes - Create Release Notes PR - - Add the release note file as [`/docs/releases/vx.y.0.md`](https://github.com/backstage/backstage/tree/master/docs/releases) + - Add the release note file as [`/docs/releases/vx.y.0.md`](./releases) - Add an entry to [`/microsite/sidebar.json`](https://github.com/backstage/backstage/blob/master/microsite/sidebars.json) for the release note - Update the navigation bar item in [`/microsite/docusaurus.config.js`](https://github.com/backstage/backstage/blob/master/microsite/docusaurus.config.js) to point to the new release note From ca957d7a7d7fc6dcc6e85ead6e332524c40bd8d2 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Thu, 28 Sep 2023 21:22:49 +0200 Subject: [PATCH 125/207] feat(adr): create search result item extension Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/adr/alpha-api-report.md | 12 +++++++ plugins/adr/package.json | 5 +-- plugins/adr/src/alpha.ts | 16 --------- plugins/adr/src/alpha.tsx | 58 +++++++++++++++++++++++++++++++++ yarn.lock | 1 + 5 files changed, 74 insertions(+), 18 deletions(-) delete mode 100644 plugins/adr/src/alpha.ts create mode 100644 plugins/adr/src/alpha.tsx diff --git a/plugins/adr/alpha-api-report.md b/plugins/adr/alpha-api-report.md index 7ce9f6f055..9d0bd071b1 100644 --- a/plugins/adr/alpha-api-report.md +++ b/plugins/adr/alpha-api-report.md @@ -3,8 +3,16 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { Extension } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; +// @alpha (undocumented) +export const AdrSearchResultListItemExtension: Extension<{ + lineClamp: number; + noTrack: boolean; +}>; + // @alpha (undocumented) export const adrTranslationRef: TranslationRef< 'adr', @@ -15,5 +23,9 @@ export const adrTranslationRef: TranslationRef< } >; +// @alpha (undocumented) +const _default: BackstagePlugin; +export default _default; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/adr/package.json b/plugins/adr/package.json index dd1e736f8a..d0db1a4ff2 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -6,13 +6,13 @@ "license": "Apache-2.0", "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", + "./alpha": "./src/alpha.tsx", "./package.json": "./package.json" }, "typesVersions": { "*": { "alpha": [ - "src/alpha.ts" + "src/alpha.tsx" ], "package.json": [ "package.json" @@ -45,6 +45,7 @@ "@backstage/catalog-model": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/integration-react": "workspace:^", "@backstage/plugin-adr-common": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", diff --git a/plugins/adr/src/alpha.ts b/plugins/adr/src/alpha.ts deleted file mode 100644 index 587cfce3d6..0000000000 --- a/plugins/adr/src/alpha.ts +++ /dev/null @@ -1,16 +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. - */ -export * from './translations'; diff --git a/plugins/adr/src/alpha.tsx b/plugins/adr/src/alpha.tsx new file mode 100644 index 0000000000..1f6fa0711d --- /dev/null +++ b/plugins/adr/src/alpha.tsx @@ -0,0 +1,58 @@ +/* + * 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 { + createPlugin, + createSchemaFromZod, +} from '@backstage/frontend-plugin-api'; +import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; +import { AdrDocument } from '@backstage/plugin-adr-common'; + +export * from './translations'; + +function isAdrDocument(result: any): result is AdrDocument { + return result.entityRef; +} + +/** @alpha */ +export const AdrSearchResultListItemExtension = + createSearchResultListItemExtension({ + id: 'adr', + configSchema: createSchemaFromZod(z => + z.object({ + // TODO: Define how the icon can be configurable + noTrack: z.boolean().default(false), + lineClamp: z.number().default(5), + }), + ), + predicate: result => result.type === 'adr', + component: async ({ config }) => { + const { AdrSearchResultListItem } = await import( + './search/AdrSearchResultListItem' + ); + return ({ result, ...rest }) => + isAdrDocument(result) ? ( + <AdrSearchResultListItem {...rest} {...config} result={result} /> + ) : null; + }, + }); + +/** @alpha */ +export default createPlugin({ + id: 'adr', + extensions: [AdrSearchResultListItemExtension], +}); diff --git a/yarn.lock b/yarn.lock index 3dd3f6315b..8fd8bbe045 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4501,6 +4501,7 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/integration-react": "workspace:^" "@backstage/plugin-adr-common": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" From 1204e7628e0a43bf2dcf14508adedf9d25d8652a Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Thu, 28 Sep 2023 21:29:40 +0200 Subject: [PATCH 126/207] chore: add chanset file Signed-off-by: Camila Belo <camilaibs@gmail.com> --- .changeset/strong-falcons-tickle.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/strong-falcons-tickle.md diff --git a/.changeset/strong-falcons-tickle.md b/.changeset/strong-falcons-tickle.md new file mode 100644 index 0000000000..d6fa0eb565 --- /dev/null +++ b/.changeset/strong-falcons-tickle.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-adr': patch +--- + +Create an experimental `AdrSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. From 350c97dee8e7322b61700f388b02c8e355bd10b5 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 29 Sep 2023 23:08:01 +0200 Subject: [PATCH 127/207] feat: added blog post Signed-off-by: blam <ben@blam.sh> --- ...ago-traiding-company-adopter-spotlight.mdx | 64 ++++++++++++++++++ microsite/blog/assets/2023-09-29/header.png | Bin 0 -> 60288 bytes 2 files changed, 64 insertions(+) create mode 100644 microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx create mode 100644 microsite/blog/assets/2023-09-29/header.png diff --git a/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx b/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx new file mode 100644 index 0000000000..fbf4fa89e8 --- /dev/null +++ b/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx @@ -0,0 +1,64 @@ +--- +# prettier-ignore +title: "Adopter Spotlight: How Chicago Trading Company saved 18 months of developer effort with Backstage" +author: Tiffany Cox, Spotify +--- + +![backstage header](assets/2023-09-29/header.png) + +**_TL;DR [Chicago Trading Company](https://www.chicagotrading.com/) (CTC) adopted Backstage ten months ago to help reduce onboarding frictions with their new cloud-based DevOps Kubernetes platform. Through templatization and open feedback loops, the team has conservatively saved 18 months of developer time to date with Backstage. We spoke with CTC DevOps engineer [Scott Kausler](https://github.com/scott-kausler) who shared the details of their onboarding journey, lessons learned, and insights for other Backstage adopters._** + +{/* truncate */} + +## Templates or the cluster didn't happen + +While mid-activation on a new cloud-based DevOps Kubernetes platform, Scott's team received early feedback that it was difficult to onboard teams onto this platform due to the breadth of requirements and new tools developers needed — from dependency management tools (such as Gradle, Conan, and Conda) to Docker/Kubernetes, Helm/FluxCD, and Vault. Not only were CTC developers required to learn new systems to build, package, and deploy their apps, in several cases even the code needed to be changed. There were also significant modifications required to existing tools such as Jenkins. + +Scott's team quickly recognized that this friction could lead to lower adoption and longer onboarding times to the new platform. So he started investigating solutions that would allow him to templatize these new services and create turnkey onboarding with less reference knowledge required. + +After exploring several service routes from managed to in-house/owned, CTC opted to use Backstage — already in POC for use of the [Software Catalog](https://backstage.io/docs/features/software-catalog/) — due to the [Software Templates](https://backstage.io/docs/features/software-templates/) plugin form-based input, UI/json-schema-form abilities, and its extensibility. Scott's team felt Backstage provided the most sustainable solution for growth amongst the multiple developer portal and templation options vetted and would help bridge the gap between UI-driven deployment and GitOps. + + +## Early wins on documentation and onboarding + +The CTC DevOps team created a small special interest group to champion the developer portal build and quickly delved into the big issues impacting their developer experience. From there, the team began creating tasks and templates within Backstage. + +To start, Scott worked with end-user teams outside DevOps early in the process of documenting migration to the new DevOps Kubernetes platform services. When Scott wrote the onboarding documentation, he made it a point to pair with a developer on another team that would be using it. This approach provided him with a quality sounding board, great instantaneous feedback, and a sort of "beta developer" to test V1 documentation clarity., A few weeks later, another colleague on the same end-user team followed the documentation and she didn't reach out to Scott at all. + +After this early win, the team was ready for broad distribution. Partnering with the senior leadership team, Scott's team began onboarding teams to the new DevOps Kubernetes platform using the templates his team created in Backstage. At CTC, their Backstage instance is set up to automatically scan for deployments in Kubernetes; so if you're in Kubernetes, you're onboarded to Backstage. + +"Backstage made onboarding [to the new DevOps platform] not scary,"" Scott said. "Because now — all of a sudden — you have this recipe for how to do it, you don't have to jump through these hoops, the templates are there and ready for you. You choose what you want based on these templates we have available, and you're off and running on your own."" + +Scott's team monitored progress against their onboarding goals partially by how often the DevOps team was getting pinged for support and found that it has made support smoother. They can easily refer people to templates and repo standards instead of making them create something ad hoc. + +"It's really been cool seeing how that progressed. I even have a few teams that didn't talk to DevOps at all. They used a [template] and they have a service ready. We were actually pretty excited about that, because that means now we have a scalable tool able to onboard others onto our platform."" said Scott. + +Another exciting win for CTC was template additions generated outside the initial toolkit, which has eased the burden substantially for the DevOps team. They were able to create new templates to deploy against best practices such as a template for creating a brand-new Terraform module and Git repo or — Scott's favorite — ​​a template that creates a Java repository along with Jenkins jobs for CI and the Flux CD config for deployment. + +"The template builds and auto-deploys a Docker image, so if you make a change to your mainline branch, then it will automatically build a new Docker image and deploy it to a Kubernetes cluster."" Scott said. "So within basically 10 minutes of you filling out a form, you actually have something deployed out to a Kubernetes cluster."" + +This process eased flows for both end-user devs and DevOps teams overall. + + +## Measuring Backstage impact at CTC + +To calculate the impact of Backstage, Scott began with reviewing template types and assigning a weighted value to each based upon their perceived workload. + +At CTC, some templates create a repo, some templates create a repo with some code, some templates even go as far as creating a repo with code and all the prerequisites to deploy to Flux and Jenkins jobs. To be conservative, the highest weight Scott assigned to a template would be saving three days of developer time. Even with that conservative estimate, the figure came out to be a savings of 18 months in developer effort since Backstage was deployed ten months ago. + +For CTC, the journey with Backstage has just begun. They're now looking to drive more Catalog adoption and determine what custom plugins they need to build to better support their workflows. + + +## The power of partnership (and good docs!) + +When asked about advice he has for other Backstage adopters, Scott talked about the DevOps team's comms strategy and ensuring end-user developers had pathways to provide feedback. In addition to the focus on templates for the new services, having both a dedicated Slack channel and open-door communication with the DevOps team helped reduce onboarding friction to the DevOps Kubernetes platform. + +Outside of that, he believes the approach to documentation is paramount. "Write your documentation from the perspective of, 'Hey, you have this task assigned to you to write a template, here are the exact steps you have to follow.'"" Scott said. "Think of it as a recipe. Removing your familiarity bias will help make this tool more useful for less familiar teams."" + +Finally, don't be afraid to step outside the core use cases when it comes to the Backstage framework and finding solutions to meet your needs. + +"Backstage gives you a lot of really easy to use features right out of the box. And one of the great things about open source is you can look at the code and see exactly what the behavior is and work within that behavior. But we've also developed our own processes for custom tasks because — at the end of the day — our platform has some very custom aspects to it."" Scott said. + +Interested in more stories from Backstage adopters? Check out these recent posts from [Stash](https://backstage.io/blog/2023/07/08/stash-adopter-post) and [Expedia Group](https://backstage.io/blog/2023/08/17/expedia-proof-of-value-metrics-2). + +Want to learn more about Backstage? Join our weekly [Office Hours](https://info.backstage.spotify.com/office-hours) and bring your burning questions. diff --git a/microsite/blog/assets/2023-09-29/header.png b/microsite/blog/assets/2023-09-29/header.png new file mode 100644 index 0000000000000000000000000000000000000000..fbc48954c30b27f4b162ca6dcb742f8a9628f90c GIT binary patch literal 60288 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 literal 0 HcmV?d00001 From d58c324777bf90eddc43d0aa8c5668f7a14a5f9b Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 09:21:40 +0200 Subject: [PATCH 128/207] chore(techdocs): configure alpha subpath Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/techdocs/package.json | 19 ++++++++++++++++--- plugins/techdocs/src/alpha.tsx | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 plugins/techdocs/src/alpha.tsx diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 7a34577f01..058e838fe6 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -6,9 +6,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.tsx", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.tsx" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "frontend-plugin" diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx new file mode 100644 index 0000000000..eb2f165350 --- /dev/null +++ b/plugins/techdocs/src/alpha.tsx @@ -0,0 +1,15 @@ +/* + * 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. + */ From 2718c8d4cbba8ec601ddf0a028da14e859ed937d Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 09:38:13 +0200 Subject: [PATCH 129/207] feat(techdocs): migrate search result item extension Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/techdocs/package.json | 1 + plugins/techdocs/src/alpha.tsx | 36 ++++++++++++++++++++++++++++++++++ yarn.lock | 1 + 3 files changed, 38 insertions(+) diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 058e838fe6..80951ed400 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -52,6 +52,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/integration-react": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx index eb2f165350..bea4b7ab34 100644 --- a/plugins/techdocs/src/alpha.tsx +++ b/plugins/techdocs/src/alpha.tsx @@ -13,3 +13,39 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import React from 'react'; +import { + createPlugin, + createSchemaFromZod, +} from '@backstage/frontend-plugin-api'; +import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; + +/** @alpha */ +export const TechDocsSearchResultListItemExtension = + createSearchResultListItemExtension({ + id: 'techdocs', + configSchema: createSchemaFromZod(z => + z.object({ + // TODO: Define how the icon can be configurable + title: z.string().optional(), + lineClamp: z.number().default(5), + asLink: z.boolean().default(true), + asListItem: z.boolean().default(true), + noTrack: z.boolean().default(false), + }), + ), + predicate: result => result.type === 'techdocs', + component: async ({ config }) => { + const { TechDocsSearchResultListItem } = await import( + './search/components/TechDocsSearchResultListItem' + ); + return props => <TechDocsSearchResultListItem {...props} {...config} />; + }, + }); + +/** @alpha */ +export default createPlugin({ + id: 'techdocs', + extensions: [TechDocsSearchResultListItemExtension], +}); diff --git a/yarn.lock b/yarn.lock index 3dd3f6315b..655acc26ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9739,6 +9739,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/integration-react": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" From 34e1d285bd4cd0f1cba9ef07e99e7d3561d27c41 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 09:39:47 +0200 Subject: [PATCH 130/207] docs(techdocs): update api reports Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/techdocs/alpha-api-report.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 plugins/techdocs/alpha-api-report.md diff --git a/plugins/techdocs/alpha-api-report.md b/plugins/techdocs/alpha-api-report.md new file mode 100644 index 0000000000..30d208865c --- /dev/null +++ b/plugins/techdocs/alpha-api-report.md @@ -0,0 +1,23 @@ +## API Report File for "@backstage/plugin-techdocs" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { Extension } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +const _default: BackstagePlugin; +export default _default; + +// @alpha (undocumented) +export const TechDocsSearchResultListItemExtension: Extension<{ + lineClamp: number; + noTrack: boolean; + asListItem: boolean; + asLink: boolean; + title?: string | undefined; +}>; + +// (No @packageDocumentation comment for this package) +``` From 4918f65ab23a949d42e39157ebd5129cbbb86121 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 09:41:45 +0200 Subject: [PATCH 131/207] chore: add changeset file Signed-off-by: Camila Belo <camilaibs@gmail.com> --- .changeset/fair-frogs-enjoy.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fair-frogs-enjoy.md diff --git a/.changeset/fair-frogs-enjoy.md b/.changeset/fair-frogs-enjoy.md new file mode 100644 index 0000000000..12eb57489e --- /dev/null +++ b/.changeset/fair-frogs-enjoy.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Create an experimental `TechDocsSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. From 9eb82dbaac1edd901fd5ab2fe0e4d05aadb90cb1 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 10:13:05 +0200 Subject: [PATCH 132/207] chore(explore): configure alpha subpath Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/explore/package.json | 19 ++++++++++++++++--- plugins/explore/src/alpha.tsx | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 plugins/explore/src/alpha.tsx diff --git a/plugins/explore/package.json b/plugins/explore/package.json index e1b210fb37..63e59dd9a8 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -6,9 +6,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.tsx", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.tsx" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "frontend-plugin" diff --git a/plugins/explore/src/alpha.tsx b/plugins/explore/src/alpha.tsx new file mode 100644 index 0000000000..eb2f165350 --- /dev/null +++ b/plugins/explore/src/alpha.tsx @@ -0,0 +1,15 @@ +/* + * 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. + */ From 6d5a060d1fe292b3fce06bd67d4348114887b801 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 11:59:17 +0200 Subject: [PATCH 133/207] feat(explore): migrate search result item extension Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/explore/package.json | 1 + plugins/explore/src/alpha.tsx | 20 ++++++++++++++++++++ yarn.lock | 1 + 3 files changed, 22 insertions(+) diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 63e59dd9a8..dcf0b75577 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -50,6 +50,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-explore-common": "workspace:^", "@backstage/plugin-explore-react": "workspace:^", diff --git a/plugins/explore/src/alpha.tsx b/plugins/explore/src/alpha.tsx index eb2f165350..1825af5ddb 100644 --- a/plugins/explore/src/alpha.tsx +++ b/plugins/explore/src/alpha.tsx @@ -13,3 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import { createPlugin } from '@backstage/frontend-plugin-api'; +import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; + +/** @alpha */ +export const ExploreSearchResultListItemExtension = + createSearchResultListItemExtension({ + id: 'explore', + predicate: result => result.type === 'tools', + component: () => + import('./components/ToolSearchResultListItem').then( + m => m.ToolSearchResultListItem, + ), + }); + +/** @alpha */ +export default createPlugin({ + id: 'explore', + extensions: [ExploreSearchResultListItemExtension], +}); diff --git a/yarn.lock b/yarn.lock index 3dd3f6315b..c2909aaec2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6811,6 +6811,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-catalog": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-explore-common": "workspace:^" From ab98569836459dbbd11335997118b39b6c5e7433 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 12:06:34 +0200 Subject: [PATCH 134/207] docs(explore): update api reports Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/explore/alpha-api-report.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 plugins/explore/alpha-api-report.md diff --git a/plugins/explore/alpha-api-report.md b/plugins/explore/alpha-api-report.md new file mode 100644 index 0000000000..3d6e527629 --- /dev/null +++ b/plugins/explore/alpha-api-report.md @@ -0,0 +1,19 @@ +## API Report File for "@backstage/plugin-explore" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { Extension } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +const _default: BackstagePlugin; +export default _default; + +// @alpha (undocumented) +export const ExploreSearchResultListItemExtension: Extension<{ + noTrack?: boolean | undefined; +}>; + +// (No @packageDocumentation comment for this package) +``` From 0f10c53a05199a4f7ecb416c00d7f7b25630c085 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 12:08:49 +0200 Subject: [PATCH 135/207] chore: add changeset file Signed-off-by: Camila Belo <camilaibs@gmail.com> --- .changeset/warm-drinks-argue.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/warm-drinks-argue.md diff --git a/.changeset/warm-drinks-argue.md b/.changeset/warm-drinks-argue.md new file mode 100644 index 0000000000..5bd4fa63f1 --- /dev/null +++ b/.changeset/warm-drinks-argue.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-explore': patch +--- + +Create an experimental `ExploreSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. From 4ec503f7d5a8316e0e62a1e0ea257eb6eb8bb65d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 22:04:14 +0000 Subject: [PATCH 136/207] fix(deps): update dependency @types/express to v4.17.18 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index f50a474608..159e89271a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17414,14 +17414,14 @@ __metadata: linkType: hard "@types/express@npm:*, @types/express@npm:^4.17.13, @types/express@npm:^4.17.17, @types/express@npm:^4.17.6": - version: 4.17.17 - resolution: "@types/express@npm:4.17.17" + version: 4.17.18 + resolution: "@types/express@npm:4.17.18" dependencies: "@types/body-parser": "*" "@types/express-serve-static-core": ^4.17.33 "@types/qs": "*" "@types/serve-static": "*" - checksum: 0196dacc275ac3ce89d7364885cb08e7fb61f53ca101f65886dbf1daf9b7eb05c0943e2e4bbd01b0cc5e50f37e0eea7e4cbe97d0304094411ac73e1b7998f4da + checksum: 8c178da4f0edff1f006d871fbdc3f849620986ff10bad252f3dfd45b57554e26aaa28c602285df028930d5216e257a06fbaf795070f8bb42f7d87e3b689cba50 languageName: node linkType: hard From 5c31049f445b8808deee7287181f0586340f97dd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 12:28:11 +0000 Subject: [PATCH 137/207] fix(deps): update dependency @types/passport to v1.0.13 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index aa6979df97..4e4e68cb34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3673,7 +3673,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.1, @backstage/catalog-model@^1.4.2, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.2, @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: @@ -4019,7 +4019,7 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.13.4, @backstage/core-components@npm:^0.13.5": +"@backstage/core-components@npm:^0.13.5": version: 0.13.5 resolution: "@backstage/core-components@npm:0.13.5" dependencies: @@ -4150,7 +4150,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.5.3, @backstage/core-plugin-api@npm:^1.6.0": +"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.6.0": version: 1.6.0 resolution: "@backstage/core-plugin-api@npm:1.6.0" dependencies: @@ -5900,7 +5900,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.3, @backstage/plugin-catalog-react@npm:^1.8.4": +"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.4": version: 1.8.4 resolution: "@backstage/plugin-catalog-react@npm:1.8.4" dependencies: @@ -10073,7 +10073,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.4.1, @backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: @@ -18108,11 +18108,11 @@ __metadata: linkType: hard "@types/passport@npm:*, @types/passport@npm:^1.0.3": - version: 1.0.12 - resolution: "@types/passport@npm:1.0.12" + version: 1.0.13 + resolution: "@types/passport@npm:1.0.13" dependencies: "@types/express": "*" - checksum: 2bce41b248566d8c2aeafcb38f105e3521d42a572e92da9edc5eb669f1b3cb02e5911c9d124191f67d432b677562a885b6ad7f56320c712df1e87ba7619eb8a4 + checksum: 84330bedb330302ffd92b009b9b88eb20d3c66b659b383badb9aa3035612b40b47052153858b2498a95d9979d668443bdee3182345819cb18635dfb7f24c109c languageName: node linkType: hard From 6c7f6888c9c69e4a8f78165370a488b8af225058 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 12:28:42 +0000 Subject: [PATCH 138/207] fix(deps): update dependency @types/react-sparklines to v1.7.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index aa6979df97..f1539409d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3673,7 +3673,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.1, @backstage/catalog-model@^1.4.2, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.2, @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: @@ -4019,7 +4019,7 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.13.4, @backstage/core-components@npm:^0.13.5": +"@backstage/core-components@npm:^0.13.5": version: 0.13.5 resolution: "@backstage/core-components@npm:0.13.5" dependencies: @@ -4150,7 +4150,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.5.3, @backstage/core-plugin-api@npm:^1.6.0": +"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.6.0": version: 1.6.0 resolution: "@backstage/core-plugin-api@npm:1.6.0" dependencies: @@ -5900,7 +5900,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.3, @backstage/plugin-catalog-react@npm:^1.8.4": +"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.4": version: 1.8.4 resolution: "@backstage/plugin-catalog-react@npm:1.8.4" dependencies: @@ -10073,7 +10073,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.4.1, @backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: @@ -18227,11 +18227,11 @@ __metadata: linkType: hard "@types/react-sparklines@npm:^1.7.0": - version: 1.7.2 - resolution: "@types/react-sparklines@npm:1.7.2" + version: 1.7.3 + resolution: "@types/react-sparklines@npm:1.7.3" dependencies: "@types/react": "*" - checksum: e0e8479c256731c3fe9405a5d3061f81838f8708bc585203afa89ff81f266f06f5b497b1db77e6a488d6073de623c4093afd9cbf3626bb7c89f996632749c281 + checksum: 4bcdc526ba2bab1354c8add8a01e10c42203950edfeda70d304a50b51f299c27432a8c8a7bbfce1a860a2b72bbfaf867bafe1b01f877cdaaae54e4ed209554f0 languageName: node linkType: hard From 7a2e2924c701c102f0b1be64d9c6f9ffbeb50b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Sat, 30 Sep 2023 14:46:15 +0200 Subject: [PATCH 139/207] Deprecated LocationEntityProcessor, added doc comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .changeset/four-pans-sin.md | 5 ++++ .changeset/heavy-forks-tie.md | 5 ++++ plugins/catalog-backend/api-report.md | 4 +-- .../modules/core/LocationEntityProcessor.ts | 18 +++++++++++-- .../catalog-node/src/api/processingResult.ts | 27 +++++++++++++++++++ 5 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 .changeset/four-pans-sin.md create mode 100644 .changeset/heavy-forks-tie.md diff --git a/.changeset/four-pans-sin.md b/.changeset/four-pans-sin.md new file mode 100644 index 0000000000..46d31c242c --- /dev/null +++ b/.changeset/four-pans-sin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Marked the `LocationEntityProcessor` as deprecated, as it is no longer used internally since way back and can even be harmful at this point. diff --git a/.changeset/heavy-forks-tie.md b/.changeset/heavy-forks-tie.md new file mode 100644 index 0000000000..f5af5975b7 --- /dev/null +++ b/.changeset/heavy-forks-tie.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-node': patch +--- + +Added docs to `processingResult` diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 345874d919..e426ca1d75 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -365,7 +365,7 @@ export type LocationAnalyzer = { ): Promise<AnalyzeLocationResponse>; }; -// @public (undocumented) +// @public @deprecated export class LocationEntityProcessor implements CatalogProcessor_2 { constructor(options: LocationEntityProcessorOptions); // (undocumented) @@ -378,7 +378,7 @@ export class LocationEntityProcessor implements CatalogProcessor_2 { ): Promise<Entity>; } -// @public (undocumented) +// @public @deprecated (undocumented) export type LocationEntityProcessorOptions = { integrations: ScmIntegrationRegistry; }; diff --git a/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.ts b/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.ts index 1db74b3b56..7bfd7f33cd 100644 --- a/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.ts +++ b/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.ts @@ -42,12 +42,26 @@ export function toAbsoluteUrl( } } -/** @public */ +/** + * @public + * @deprecated This processor should no longer be used + */ export type LocationEntityProcessorOptions = { integrations: ScmIntegrationRegistry; }; -/** @public */ +/** + * Legacy processor, should not be used. + * + * @remarks + * + * In the old catalog architecture, this processor translated Location entities + * into URLs that should be fetched. This is no longer needed since the engine + * handles this internally. + * + * @public + * @deprecated This processor should no longer be used + */ export class LocationEntityProcessor implements CatalogProcessor { constructor(private readonly options: LocationEntityProcessorOptions) {} diff --git a/plugins/catalog-node/src/api/processingResult.ts b/plugins/catalog-node/src/api/processingResult.ts index d8b6f3ae02..0d4341fcb7 100644 --- a/plugins/catalog-node/src/api/processingResult.ts +++ b/plugins/catalog-node/src/api/processingResult.ts @@ -26,6 +26,9 @@ import { LocationSpec } from '@backstage/plugin-catalog-common'; * @public */ export const processingResult = Object.freeze({ + /** + * Associates a NotFoundError with the processing state of the current entity. + */ notFoundError( atLocation: LocationSpec, message: string, @@ -37,6 +40,9 @@ export const processingResult = Object.freeze({ }; }, + /** + * Associates an InputError with the processing state of the current entity. + */ inputError( atLocation: LocationSpec, message: string, @@ -48,6 +54,9 @@ export const processingResult = Object.freeze({ }; }, + /** + * Associates a general Error with the processing state of the current entity. + */ generalError( atLocation: LocationSpec, message: string, @@ -55,18 +64,36 @@ export const processingResult = Object.freeze({ return { type: 'error', location: atLocation, error: new Error(message) }; }, + /** + * Emits a location. In effect, this is analogous to emitting a Location kind + * child entity. This is commonly used in discovery processors. Do not use + * this while processing Location entities. + */ location(newLocation: LocationSpec): CatalogProcessorResult { return { type: 'location', location: newLocation }; }, + /** + * Emits a child of the current entity, associated with a certain location. + */ entity(atLocation: LocationSpec, newEntity: Entity): CatalogProcessorResult { return { type: 'entity', location: atLocation, entity: newEntity }; }, + /** + * Emits a relation owned by the current entity. The relation does not have to + * start or end at the current entity. The relation only lives for as long as + * the current entity lives. + */ relation(spec: EntityRelationSpec): CatalogProcessorResult { return { type: 'relation', relation: spec }; }, + /** + * Associates the given refresh key with the current entity. The effect of + * this is that the entity will be marked for refresh when such requests are + * made. + */ refresh(key: string): CatalogProcessorResult { return { type: 'refresh', key }; }, From 1d6267a96476d5173ca9921378d0a31c528e2d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Sat, 30 Sep 2023 14:54:27 +0200 Subject: [PATCH 140/207] unclean yarn.lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index aa6979df97..16d1e39149 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3673,7 +3673,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.1, @backstage/catalog-model@^1.4.2, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.2, @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: @@ -4019,7 +4019,7 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.13.4, @backstage/core-components@npm:^0.13.5": +"@backstage/core-components@npm:^0.13.5": version: 0.13.5 resolution: "@backstage/core-components@npm:0.13.5" dependencies: @@ -4150,7 +4150,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.5.3, @backstage/core-plugin-api@npm:^1.6.0": +"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.6.0": version: 1.6.0 resolution: "@backstage/core-plugin-api@npm:1.6.0" dependencies: @@ -5900,7 +5900,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.3, @backstage/plugin-catalog-react@npm:^1.8.4": +"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.4": version: 1.8.4 resolution: "@backstage/plugin-catalog-react@npm:1.8.4" dependencies: @@ -10073,7 +10073,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.4.1, @backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: From f28be0f837a83041c405f381f7abed6bcf5aa448 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 15:24:09 +0000 Subject: [PATCH 141/207] fix(deps): update dependency @types/react-text-truncate to v0.14.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index aa6979df97..b18b2bdbdd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3673,7 +3673,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.1, @backstage/catalog-model@^1.4.2, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.2, @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: @@ -4019,7 +4019,7 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.13.4, @backstage/core-components@npm:^0.13.5": +"@backstage/core-components@npm:^0.13.5": version: 0.13.5 resolution: "@backstage/core-components@npm:0.13.5" dependencies: @@ -4150,7 +4150,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.5.3, @backstage/core-plugin-api@npm:^1.6.0": +"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.6.0": version: 1.6.0 resolution: "@backstage/core-plugin-api@npm:1.6.0" dependencies: @@ -5900,7 +5900,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.3, @backstage/plugin-catalog-react@npm:^1.8.4": +"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.4": version: 1.8.4 resolution: "@backstage/plugin-catalog-react@npm:1.8.4" dependencies: @@ -10073,7 +10073,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.4.1, @backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: @@ -18245,11 +18245,11 @@ __metadata: linkType: hard "@types/react-text-truncate@npm:^0.14.0": - version: 0.14.1 - resolution: "@types/react-text-truncate@npm:0.14.1" + version: 0.14.2 + resolution: "@types/react-text-truncate@npm:0.14.2" dependencies: "@types/react": "*" - checksum: 6b5ffb04b41fbe88c63ff7e8ff815fa7e3e52d128a5ccbc134fc412da6b6904dc55a34891aa4769cb5f9b958f48288475f500281cc1f3d74450610a3ec657491 + checksum: 714b8dade2cd149b3a353c6914065f8aaf2e8d01c21fc1e92afe9e9cf19b037c6a9c34c9100a8009848a6d8747fbd0f4c3b2fe4676b0afa35e347b2fecc92811 languageName: node linkType: hard From 91bd401835b93945691541e9be97ae014c255ac3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 19:45:44 +0000 Subject: [PATCH 142/207] fix(deps): update dependency cron to v2.4.4 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index aa6979df97..1f0a103979 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3673,7 +3673,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.1, @backstage/catalog-model@^1.4.2, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.2, @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: @@ -4019,7 +4019,7 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.13.4, @backstage/core-components@npm:^0.13.5": +"@backstage/core-components@npm:^0.13.5": version: 0.13.5 resolution: "@backstage/core-components@npm:0.13.5" dependencies: @@ -4150,7 +4150,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.5.3, @backstage/core-plugin-api@npm:^1.6.0": +"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.6.0": version: 1.6.0 resolution: "@backstage/core-plugin-api@npm:1.6.0" dependencies: @@ -5900,7 +5900,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.3, @backstage/plugin-catalog-react@npm:^1.8.4": +"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.4": version: 1.8.4 resolution: "@backstage/plugin-catalog-react@npm:1.8.4" dependencies: @@ -10073,7 +10073,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.4.1, @backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: @@ -22651,12 +22651,12 @@ __metadata: linkType: hard "cron@npm:^2.0.0": - version: 2.4.3 - resolution: "cron@npm:2.4.3" + version: 2.4.4 + resolution: "cron@npm:2.4.4" dependencies: "@types/luxon": ~3.3.0 luxon: ~3.3.0 - checksum: cb0ad49653b37ba125f8670ca92150ce515493512b1b8a5e08086d22bec9c54dc6d8926fcdb49ea5783f6699862ca5fdc532a440ce33c3228f9b3d565010db2f + checksum: e7dbc39c7c747b4fb198c3e62737bcc049ec8edb2b150eee17d39256982c6688f48b50b72e9b869b18feb186ab5081bcd8b82ad1ef79d9b7a13df499aaa77084 languageName: node linkType: hard From f4a3ccd8250419c0c1961d8dc2375cb9f07e5666 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Sep 2023 22:18:47 +0000 Subject: [PATCH 143/207] fix(deps): update dependency graphql-ws to v5.14.1 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index aa6979df97..fb4e63252c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3673,7 +3673,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.1, @backstage/catalog-model@^1.4.2, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@^1.1.5, @backstage/catalog-model@^1.4.2, @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: @@ -4019,7 +4019,7 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.13.4, @backstage/core-components@npm:^0.13.5": +"@backstage/core-components@npm:^0.13.5": version: 0.13.5 resolution: "@backstage/core-components@npm:0.13.5" dependencies: @@ -4150,7 +4150,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.5.3, @backstage/core-plugin-api@npm:^1.6.0": +"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.6.0": version: 1.6.0 resolution: "@backstage/core-plugin-api@npm:1.6.0" dependencies: @@ -5900,7 +5900,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.3, @backstage/plugin-catalog-react@npm:^1.8.4": +"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.4": version: 1.8.4 resolution: "@backstage/plugin-catalog-react@npm:1.8.4" dependencies: @@ -10073,7 +10073,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.4.1, @backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@^0.4.2, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: @@ -27438,11 +27438,11 @@ __metadata: linkType: hard "graphql-ws@npm:^5.4.1, graphql-ws@npm:^5.9.0": - version: 5.14.0 - resolution: "graphql-ws@npm:5.14.0" + version: 5.14.1 + resolution: "graphql-ws@npm:5.14.1" peerDependencies: graphql: ">=0.11 <=16" - checksum: 7b622944823fa12a77ea490656121a77e1a1daf08114a6a0b027922113f4481d95f4fe380a5de369a51657ef777d35757dc31f63e41071c21f3e97ca47e4205a + checksum: bf6aa9446496f11e74d5fea17672050fb02f0303c6a7bf1e2692b7ea88059a18837f437e2ec8ba3cf7bb5bc2a18dddeebe9a8c6e6036914c3776297c48c1a398 languageName: node linkType: hard From afa48341fbd636c64c741a5e439c0b70231843da Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Sat, 30 Sep 2023 17:15:14 +0200 Subject: [PATCH 144/207] backend-dev-utils: fix ipc response race Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/itchy-monkeys-reply.md | 5 ++ packages/backend-dev-utils/src/ipcClient.ts | 60 +++++++++++---------- 2 files changed, 36 insertions(+), 29 deletions(-) create mode 100644 .changeset/itchy-monkeys-reply.md diff --git a/.changeset/itchy-monkeys-reply.md b/.changeset/itchy-monkeys-reply.md new file mode 100644 index 0000000000..3773fe3ff8 --- /dev/null +++ b/.changeset/itchy-monkeys-reply.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-dev-utils': patch +--- + +Fix an issue where early IPC responses would be lost. diff --git a/packages/backend-dev-utils/src/ipcClient.ts b/packages/backend-dev-utils/src/ipcClient.ts index 87c1596a39..d9ec7821de 100644 --- a/packages/backend-dev-utils/src/ipcClient.ts +++ b/packages/backend-dev-utils/src/ipcClient.ts @@ -38,6 +38,8 @@ type Response = const requestType = '@backstage/cli/channel/request'; const responseType = '@backstage/cli/channel/response'; +const IPC_TIMEOUT_MS = 5000; + /** * The client side of an IPC communication channel. * @@ -78,43 +80,43 @@ export class BackstageIpcClient { body, }; - this.#sendMessage(request, (e: Error) => { - if (e) { - reject(e); + let timeout: NodeJS.Timeout | undefined = undefined; + + const messageHandler = (response: Response) => { + if (response?.type !== responseType) { + return; + } + if (response.id !== id) { return; } - let timeout: NodeJS.Timeout | undefined = undefined; + clearTimeout(timeout); + timeout = undefined; + process.removeListener('message', messageHandler); - const messageHandler = (response: Response) => { - if (response?.type !== responseType) { - return; - } - if (response.id !== id) { - return; + if ('error' in response) { + const error = new Error(response.error.message); + if (response.error.name) { + error.name = response.error.name; } + reject(error); + } else { + resolve(response.body as TResponseBody); + } + }; - if ('error' in response) { - const error = new Error(response.error.message); - if (response.error.name) { - error.name = response.error.name; - } - reject(error); - } else { - resolve(response.body as TResponseBody); - } + timeout = setTimeout(() => { + reject(new Error(`IPC request '${method}' with ID ${id} timed out`)); + process.removeListener('message', messageHandler); + }, IPC_TIMEOUT_MS); + timeout.unref(); - clearTimeout(timeout); - process.removeListener('message', messageHandler); - }; + process.addListener('message', messageHandler as () => void); - timeout = setTimeout(() => { - reject(new Error(`IPC request '${method}' with ID ${id} timed out`)); - process.removeListener('message', messageHandler); - }, 5000); - timeout.unref(); - - process.addListener('message', messageHandler as () => void); + this.#sendMessage(request, (e: Error) => { + if (e) { + reject(e); + } }); }); } From d0f26cfa4fc82fecf1ec58f3898c6bc6e5d7675a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Sun, 1 Oct 2023 15:35:04 +0200 Subject: [PATCH 145/207] cli: gracefully shut down child process on windows Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/red-bees-try.md | 5 +++++ packages/cli/package.json | 1 + .../cli/src/lib/experimental/startBackendExperimental.ts | 7 ++++++- yarn.lock | 8 ++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 .changeset/red-bees-try.md diff --git a/.changeset/red-bees-try.md b/.changeset/red-bees-try.md new file mode 100644 index 0000000000..de7eacfe14 --- /dev/null +++ b/.changeset/red-bees-try.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows. diff --git a/packages/cli/package.json b/packages/cli/package.json index e49c649e8c..2f9f6109f0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -78,6 +78,7 @@ "cross-fetch": "^3.1.5", "cross-spawn": "^7.0.3", "css-loader": "^6.5.1", + "ctrlc-windows": "^2.1.0", "diff": "^5.0.0", "esbuild": "^0.19.0", "esbuild-loader": "^2.18.0", diff --git a/packages/cli/src/lib/experimental/startBackendExperimental.ts b/packages/cli/src/lib/experimental/startBackendExperimental.ts index 1272ba9e66..578fd1c747 100644 --- a/packages/cli/src/lib/experimental/startBackendExperimental.ts +++ b/packages/cli/src/lib/experimental/startBackendExperimental.ts @@ -18,6 +18,7 @@ import { FSWatcher, watch } from 'chokidar'; import { BackendServeOptions } from '../bundler/types'; import type { ChildProcess } from 'child_process'; +import { ctrlc } from 'ctrlc-windows'; import { IpcServer } from './IpcServer'; import { ServerDataStore } from './ServerDataStore'; import debounce from 'lodash/debounce'; @@ -57,7 +58,11 @@ export async function startBackendExperimental(options: BackendServeOptions) { if (child && !child.killed && child.exitCode === null) { // We always wait for the existing process to exit, to make sure we don't get IPC conflicts shutdownPromise = new Promise(resolve => child!.once('exit', resolve)); - child.kill(); + if (process.platform === 'win32' && child.pid) { + ctrlc(child.pid); + } else { + child.kill(); + } await shutdownPromise; shutdownPromise = undefined; } diff --git a/yarn.lock b/yarn.lock index 16d1e39149..12bc38b450 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3795,6 +3795,7 @@ __metadata: cross-fetch: ^3.1.5 cross-spawn: ^7.0.3 css-loader: ^6.5.1 + ctrlc-windows: ^2.1.0 del: ^7.0.0 diff: ^5.0.0 esbuild: ^0.19.0 @@ -23048,6 +23049,13 @@ __metadata: languageName: node linkType: hard +"ctrlc-windows@npm:^2.1.0": + version: 2.1.0 + resolution: "ctrlc-windows@npm:2.1.0" + checksum: 0f0582ba9516290d3e90ea7b91710f8b9b110e1ed29b7c84ebd44c16368b2553722b86a17226120ca3ea0ef679ac3596f48104cc113cfb7c3d07260f6c92e38b + languageName: node + linkType: hard + "d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:^3.1.6": version: 3.2.3 resolution: "d3-array@npm:3.2.3" From f41099bb31ec1d9b6dd33563f9e9223fe840dd2e Mon Sep 17 00:00:00 2001 From: Yevhenii Huselietov <yevhenii.huselietov@gmail.com> Date: Fri, 29 Sep 2023 16:33:34 +0300 Subject: [PATCH 146/207] Display meaningful error to the output if Gitlab namespace not found inside publish:gitlab Signed-off-by: Yevhenii Huselietov <yevhenii.huselietov@gmail.com> --- .changeset/lazy-doors-wink.md | 5 +++++ .../actions/builtin/publish/gitlab.test.ts | 17 ++++++++++++++ .../actions/builtin/publish/gitlab.ts | 22 ++++++++++++++----- 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 .changeset/lazy-doors-wink.md diff --git a/.changeset/lazy-doors-wink.md b/.changeset/lazy-doors-wink.md new file mode 100644 index 0000000000..aafbb3500e --- /dev/null +++ b/.changeset/lazy-doors-wink.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 994d1c580a..1174276672 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -393,4 +393,21 @@ describe('publish:gitlab', () => { visibility: 'private', }); }); + + it('should show proper error message when token has insufficient permissions or namespace not found', async () => { + mockGitlabClient.Namespaces.show.mockRejectedValue({ + message: '404 Namespace Not Found', + }); + const owner = 'infrastructure/devex'; + const repoName = 'backstage'; + + await expect( + action.handler({ + ...mockContext, + input: { repoUrl: `gitlab.com?owner=${owner}&repo=${repoName}` }, + }), + ).rejects.toThrow( + `The namespace ${owner} is not found or the user doesn't have permissions to access it`, + ); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index dbab7b11b8..2b782f2d75 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -174,20 +174,30 @@ export function createPublishGitlabAction(options: { [tokenType]: token, }); - let { id: targetNamespace } = (await client.Namespaces.show(owner)) as { - id: number; - }; + let targetNamespaceId; + + try { + const namespaceResponse = (await client.Namespaces.show(owner)) as { + id: number; + }; + + targetNamespaceId = namespaceResponse.id; + } catch (e) { + throw new InputError( + `The namespace ${owner} is not found or the user doesn't have permissions to access it`, + ); + } const { id: userId } = (await client.Users.current()) as { id: number; }; - if (!targetNamespace) { - targetNamespace = userId; + if (!targetNamespaceId) { + targetNamespaceId = userId; } const { id: projectId, http_url_to_repo } = await client.Projects.create({ - namespace_id: targetNamespace, + namespace_id: targetNamespaceId, name: repo, visibility: repoVisibility, ...(topics.length ? { topics } : {}), From a8a749e4c42a782c62de8c3b85713f410a7b6638 Mon Sep 17 00:00:00 2001 From: Yevhenii Huselietov <yevhenii.huselietov@gmail.com> Date: Sun, 1 Oct 2023 16:51:11 +0300 Subject: [PATCH 147/207] Throw only on 404 responses Signed-off-by: Yevhenii Huselietov <yevhenii.huselietov@gmail.com> --- .../src/scaffolder/actions/builtin/publish/gitlab.test.ts | 4 +++- .../src/scaffolder/actions/builtin/publish/gitlab.ts | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 1174276672..dc8e3eb0ee 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -396,7 +396,9 @@ describe('publish:gitlab', () => { it('should show proper error message when token has insufficient permissions or namespace not found', async () => { mockGitlabClient.Namespaces.show.mockRejectedValue({ - message: '404 Namespace Not Found', + response: { + statusCode: 404, + }, }); const owner = 'infrastructure/devex'; const repoName = 'backstage'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 2b782f2d75..a7da0555e2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -183,9 +183,11 @@ export function createPublishGitlabAction(options: { targetNamespaceId = namespaceResponse.id; } catch (e) { - throw new InputError( - `The namespace ${owner} is not found or the user doesn't have permissions to access it`, - ); + if (e.response && e.response.statusCode === 404) { + throw new InputError( + `The namespace ${owner} is not found or the user doesn't have permissions to access it`, + ); + } } const { id: userId } = (await client.Users.current()) as { From f062a60986ee3b80042f6e95a21afe5058406ec1 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Mon, 2 Oct 2023 10:06:26 +0200 Subject: [PATCH 148/207] chore: make pretty Signed-off-by: blam <ben@blam.sh> --- ...ago-traiding-company-adopter-spotlight.mdx | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx b/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx index fbf4fa89e8..8b4f332d54 100644 --- a/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx +++ b/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx @@ -18,47 +18,44 @@ Scott's team quickly recognized that this friction could lead to lower adoption After exploring several service routes from managed to in-house/owned, CTC opted to use Backstage — already in POC for use of the [Software Catalog](https://backstage.io/docs/features/software-catalog/) — due to the [Software Templates](https://backstage.io/docs/features/software-templates/) plugin form-based input, UI/json-schema-form abilities, and its extensibility. Scott's team felt Backstage provided the most sustainable solution for growth amongst the multiple developer portal and templation options vetted and would help bridge the gap between UI-driven deployment and GitOps. - -## Early wins on documentation and onboarding +## Early wins on documentation and onboarding The CTC DevOps team created a small special interest group to champion the developer portal build and quickly delved into the big issues impacting their developer experience. From there, the team began creating tasks and templates within Backstage. -To start, Scott worked with end-user teams outside DevOps early in the process of documenting migration to the new DevOps Kubernetes platform services. When Scott wrote the onboarding documentation, he made it a point to pair with a developer on another team that would be using it. This approach provided him with a quality sounding board, great instantaneous feedback, and a sort of "beta developer" to test V1 documentation clarity., A few weeks later, another colleague on the same end-user team followed the documentation and she didn't reach out to Scott at all. +To start, Scott worked with end-user teams outside DevOps early in the process of documenting migration to the new DevOps Kubernetes platform services. When Scott wrote the onboarding documentation, he made it a point to pair with a developer on another team that would be using it. This approach provided him with a quality sounding board, great instantaneous feedback, and a sort of "beta developer" to test V1 documentation clarity., A few weeks later, another colleague on the same end-user team followed the documentation and she didn't reach out to Scott at all. After this early win, the team was ready for broad distribution. Partnering with the senior leadership team, Scott's team began onboarding teams to the new DevOps Kubernetes platform using the templates his team created in Backstage. At CTC, their Backstage instance is set up to automatically scan for deployments in Kubernetes; so if you're in Kubernetes, you're onboarded to Backstage. "Backstage made onboarding [to the new DevOps platform] not scary,"" Scott said. "Because now — all of a sudden — you have this recipe for how to do it, you don't have to jump through these hoops, the templates are there and ready for you. You choose what you want based on these templates we have available, and you're off and running on your own."" -Scott's team monitored progress against their onboarding goals partially by how often the DevOps team was getting pinged for support and found that it has made support smoother. They can easily refer people to templates and repo standards instead of making them create something ad hoc. +Scott's team monitored progress against their onboarding goals partially by how often the DevOps team was getting pinged for support and found that it has made support smoother. They can easily refer people to templates and repo standards instead of making them create something ad hoc. "It's really been cool seeing how that progressed. I even have a few teams that didn't talk to DevOps at all. They used a [template] and they have a service ready. We were actually pretty excited about that, because that means now we have a scalable tool able to onboard others onto our platform."" said Scott. -Another exciting win for CTC was template additions generated outside the initial toolkit, which has eased the burden substantially for the DevOps team. They were able to create new templates to deploy against best practices such as a template for creating a brand-new Terraform module and Git repo or — Scott's favorite — ​​a template that creates a Java repository along with Jenkins jobs for CI and the Flux CD config for deployment. +Another exciting win for CTC was template additions generated outside the initial toolkit, which has eased the burden substantially for the DevOps team. They were able to create new templates to deploy against best practices such as a template for creating a brand-new Terraform module and Git repo or — Scott's favorite — ​​a template that creates a Java repository along with Jenkins jobs for CI and the Flux CD config for deployment. -"The template builds and auto-deploys a Docker image, so if you make a change to your mainline branch, then it will automatically build a new Docker image and deploy it to a Kubernetes cluster."" Scott said. "So within basically 10 minutes of you filling out a form, you actually have something deployed out to a Kubernetes cluster."" - -This process eased flows for both end-user devs and DevOps teams overall. +"The template builds and auto-deploys a Docker image, so if you make a change to your mainline branch, then it will automatically build a new Docker image and deploy it to a Kubernetes cluster."" Scott said. "So within basically 10 minutes of you filling out a form, you actually have something deployed out to a Kubernetes cluster."" +This process eased flows for both end-user devs and DevOps teams overall. ## Measuring Backstage impact at CTC -To calculate the impact of Backstage, Scott began with reviewing template types and assigning a weighted value to each based upon their perceived workload. +To calculate the impact of Backstage, Scott began with reviewing template types and assigning a weighted value to each based upon their perceived workload. At CTC, some templates create a repo, some templates create a repo with some code, some templates even go as far as creating a repo with code and all the prerequisites to deploy to Flux and Jenkins jobs. To be conservative, the highest weight Scott assigned to a template would be saving three days of developer time. Even with that conservative estimate, the figure came out to be a savings of 18 months in developer effort since Backstage was deployed ten months ago. -For CTC, the journey with Backstage has just begun. They're now looking to drive more Catalog adoption and determine what custom plugins they need to build to better support their workflows. +For CTC, the journey with Backstage has just begun. They're now looking to drive more Catalog adoption and determine what custom plugins they need to build to better support their workflows. - -## The power of partnership (and good docs!) +## The power of partnership (and good docs!) When asked about advice he has for other Backstage adopters, Scott talked about the DevOps team's comms strategy and ensuring end-user developers had pathways to provide feedback. In addition to the focus on templates for the new services, having both a dedicated Slack channel and open-door communication with the DevOps team helped reduce onboarding friction to the DevOps Kubernetes platform. Outside of that, he believes the approach to documentation is paramount. "Write your documentation from the perspective of, 'Hey, you have this task assigned to you to write a template, here are the exact steps you have to follow.'"" Scott said. "Think of it as a recipe. Removing your familiarity bias will help make this tool more useful for less familiar teams."" -Finally, don't be afraid to step outside the core use cases when it comes to the Backstage framework and finding solutions to meet your needs. +Finally, don't be afraid to step outside the core use cases when it comes to the Backstage framework and finding solutions to meet your needs. -"Backstage gives you a lot of really easy to use features right out of the box. And one of the great things about open source is you can look at the code and see exactly what the behavior is and work within that behavior. But we've also developed our own processes for custom tasks because — at the end of the day — our platform has some very custom aspects to it."" Scott said. +"Backstage gives you a lot of really easy to use features right out of the box. And one of the great things about open source is you can look at the code and see exactly what the behavior is and work within that behavior. But we've also developed our own processes for custom tasks because — at the end of the day — our platform has some very custom aspects to it."" Scott said. -Interested in more stories from Backstage adopters? Check out these recent posts from [Stash](https://backstage.io/blog/2023/07/08/stash-adopter-post) and [Expedia Group](https://backstage.io/blog/2023/08/17/expedia-proof-of-value-metrics-2). +Interested in more stories from Backstage adopters? Check out these recent posts from [Stash](https://backstage.io/blog/2023/07/08/stash-adopter-post) and [Expedia Group](https://backstage.io/blog/2023/08/17/expedia-proof-of-value-metrics-2). -Want to learn more about Backstage? Join our weekly [Office Hours](https://info.backstage.spotify.com/office-hours) and bring your burning questions. +Want to learn more about Backstage? Join our weekly [Office Hours](https://info.backstage.spotify.com/office-hours) and bring your burning questions. From b20dadf0f0c8ee8a7062553863e078f4b8cb2972 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Fri, 29 Sep 2023 17:26:44 +0200 Subject: [PATCH 149/207] catalog: update new alpha setup to include starred entities API Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- plugins/catalog/alpha-api-report.md | 3 +++ plugins/catalog/src/alpha.ts | 34 ++++++++++++++++++----------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/alpha-api-report.md index 631c43e73c..060baeccbf 100644 --- a/plugins/catalog/alpha-api-report.md +++ b/plugins/catalog/alpha-api-report.md @@ -23,5 +23,8 @@ export const catalogTranslationRef: TranslationRef< const _default: BackstagePlugin; export default _default; +// @alpha (undocumented) +export const StarredEntitiesApi: Extension<{}>; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog/src/alpha.ts b/plugins/catalog/src/alpha.ts index d9c2af338d..82e592d5b7 100644 --- a/plugins/catalog/src/alpha.ts +++ b/plugins/catalog/src/alpha.ts @@ -17,38 +17,46 @@ export * from './translation'; import { - DiscoveryApi, - FetchApi, + createApiFactory, discoveryApiRef, fetchApiRef, + storageApiRef, } from '@backstage/core-plugin-api'; import { CatalogClient } from '@backstage/catalog-client'; import { createApiExtension, createPlugin, } from '@backstage/frontend-plugin-api'; -import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { + catalogApiRef, + starredEntitiesApiRef, +} from '@backstage/plugin-catalog-react'; +import { DefaultStarredEntitiesApi } from './apis'; /** @alpha */ export const CatalogApi = createApiExtension({ - factory: { + factory: createApiFactory({ api: catalogApiRef, deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef, }, - factory: ({ - discoveryApi, - fetchApi, - }: { - discoveryApi: DiscoveryApi; - fetchApi: FetchApi; - }) => new CatalogClient({ discoveryApi, fetchApi }), - }, + factory: ({ discoveryApi, fetchApi }) => + new CatalogClient({ discoveryApi, fetchApi }), + }), +}); + +/** @alpha */ +export const StarredEntitiesApi = createApiExtension({ + factory: createApiFactory({ + api: starredEntitiesApiRef, + deps: { storageApi: storageApiRef }, + factory: ({ storageApi }) => new DefaultStarredEntitiesApi({ storageApi }), + }), }); /** @alpha */ export default createPlugin({ id: 'catalog', - extensions: [CatalogApi], + extensions: [CatalogApi, StarredEntitiesApi], }); From be5853235aafd378c52fa957b5b3fe17f748843c Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Tue, 19 Sep 2023 14:31:24 +0200 Subject: [PATCH 150/207] doc(home-plugin): Adds documentation on <HomePageVisitedByType/> usage (#19688) * doc(home-plugin): Adds documentation on <HomePageVisitedByType/> usage Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> * Update plugins/home/README.md Co-authored-by: Adam Harvey <33203301+adamdmharvey@users.noreply.github.com> Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> * Update plugins/home/README.md Co-authored-by: Camila Belo <camilaibs@gmail.com> Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --------- Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> Co-authored-by: Adam Harvey <33203301+adamdmharvey@users.noreply.github.com> Co-authored-by: Camila Belo <camilaibs@gmail.com> --- plugins/home/README.md | 79 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/plugins/home/README.md b/plugins/home/README.md index e147cdfbdf..f6a223701b 100644 --- a/plugins/home/README.md +++ b/plugins/home/README.md @@ -242,6 +242,85 @@ const defaultConfig = [ <CustomHomepageGrid config={defaultConfig}> ``` +## Page visit homepage component (HomePageVisitedByType) + +This component shows the homepage user a view for "Recently visited" or "Top visited". +Being provided by the `<HomePageVisitedByType/>` component, see it in use on a homepage example below: + +```tsx +// packages/app/src/components/home/HomePage.tsx +import React from 'react'; +import Grid from '@material-ui/core/Grid'; +import { HomePageVisitedByType } from '@backstage/plugin-home'; + +export const homePage = ( + <Grid container spacing={3}> + <Grid item xs={12} md={4}> + <HomePageVisitedByType kind="top" /> + </Grid> + <Grid item xs={12} md={4}> + <HomePageVisitedByType kind="recent" /> + </Grid> + </Grid> +); +``` + +There are some requirements to provide its functionality, so please ensure the following: + +These components need an API to handle visit data, please refer to the [utility-apis](../../docs/api/utility-apis.md) +documentation for more information. Bellow you can see an example for two options: + +```ts +// packages/app/src/apis.ts +// ... +import { + CoreStorageVisitsApi, + LocalStoreVisitsApi, + visitsApiRef, +} from '@backstage/plugin-home'; +// ... +export const apis: AnyApiFactory[] = [ + // Implementation that relies on the integration with storageApi + createApiFactory({ + api: visitsApiRef, + deps: { + storageApi: storageApiRef, + identityApi: identityApiRef, + }, + factory: ({ storageApi, identityApi }) => + CoreStorageVisitsApi.create({ storageApi, identityApi }), + }), + + // Or a local data implementation, relies on the browser's window.localStorage + createApiFactory({ + api: visitsApiRef, + deps: { + identityApi: identityApiRef, + }, + factory: ({ identityApi }) => LocalStoreVisitsApi.create({ identityApi }), + }), + // ... +``` + +To monitor page visit activity and save it on behalf of the user a component is provided, please add it to your app. +See the example usage: + +```ts +// packages/app/src/App.tsx +import { VisitsListener } from '@backstage/plugin-home'; +// ... +export default app.createRoot( + <> + <AlertDisplay /> + <OAuthRequestDialog /> + <AppRouter> + <VisitsListener /> + <Root>{routes}</Root> + </AppRouter> + </>, +); +``` + ## Contributing ### Homepage Components From ec7fce2d41f94e0ff2c958ae575c30da4e8a84e8 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Wed, 16 Aug 2023 10:52:29 +0200 Subject: [PATCH 151/207] feature(home-plugin): Bootstrap <RecentlyVisited/> skeleton. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- .../RecentlyVisited/Content.tsx | 24 +++++++++++++ .../RecentlyVisited.stories.tsx | 36 +++++++++++++++++++ .../RecentlyVisited/RecentlyVisited.test.tsx | 26 ++++++++++++++ .../RecentlyVisited/RecentlyVisited.tsx | 24 +++++++++++++ .../RecentlyVisited/index.ts | 17 +++++++++ plugins/home/src/plugin.ts | 11 ++++++ 6 files changed, 138 insertions(+) create mode 100644 plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx create mode 100644 plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx create mode 100644 plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.test.tsx create mode 100644 plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx create mode 100644 plugins/home/src/homePageComponents/RecentlyVisited/index.ts diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx new file mode 100644 index 0000000000..4d06751e22 --- /dev/null +++ b/plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx @@ -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. + */ + +import React from 'react'; +import { RecentlyVisited } from './RecentlyVisited'; + +/** + * Display recently visited pages for the homepage + * @public + */ +export const Content = () => <RecentlyVisited />; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx new file mode 100644 index 0000000000..bb04a1ebc7 --- /dev/null +++ b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx @@ -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. + */ + +import React from 'react'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { ComponentType, PropsWithChildren } from 'react'; +import { Grid } from '@material-ui/core'; +import { HomePageRecentlyVisited } from '../../plugin'; + +export default { + title: 'Plugins/Home/Components/RecentlyVisited', + decorators: [ + (Story: ComponentType<PropsWithChildren<{}>>) => wrapInTestApp(<Story />), + ], +}; + +export const Default = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageRecentlyVisited /> + </Grid> + ); +}; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.test.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.test.tsx new file mode 100644 index 0000000000..5ccab63fa8 --- /dev/null +++ b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.test.tsx @@ -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. + */ + +import React from 'react'; +import { RecentlyVisited } from './RecentlyVisited'; +import { renderInTestApp } from '@backstage/test-utils'; + +describe('<RecentlyVisited/>', () => { + it('should render', async () => { + const { getByText } = await renderInTestApp(<RecentlyVisited />); + expect(getByText('RecentlyVisited')).toBeInTheDocument(); + }); +}); diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx new file mode 100644 index 0000000000..6f2abe3b60 --- /dev/null +++ b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx @@ -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. + */ + +import React from 'react'; +import Typography from '@material-ui/core/Typography'; + +/** + * Display recently visited pages for the homepage + * @public + */ +export const RecentlyVisited = () => <Typography>RecentlyVisited</Typography>; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/index.ts b/plugins/home/src/homePageComponents/RecentlyVisited/index.ts new file mode 100644 index 0000000000..f1cdf3734f --- /dev/null +++ b/plugins/home/src/homePageComponents/RecentlyVisited/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 { Content } from './Content'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index 74a1c11390..20cfddc724 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -172,3 +172,14 @@ export const HeaderWorldClock = homePlugin.provide( }, }), ); + +/** + * Display recently visited pages for the homepage + * @public + */ +export const HomePageRecentlyVisited = homePlugin.provide( + createCardExtension({ + name: 'HomePageRecentlyVisited', + components: () => import('./homePageComponents/RecentlyVisited'), + }), +); From 46aa692057bbeee57aea03c54f96ce962ede6549 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Mon, 21 Aug 2023 14:47:05 +0200 Subject: [PATCH 152/207] feature(home-plugin): Recently Visited presentation use cases This patch adds all the presentation use cases for Recently Visited. Handling loading, few items, custom list sizes etc. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 96 ++++++++++++--- plugins/home/package.json | 2 + plugins/home/src/api/VisitsApi.ts | 106 +++++++++++++++++ plugins/home/src/api/index.ts | 17 +++ .../src/components/VisitList/ItemCategory.tsx | 79 ++++++++++++ .../src/components/VisitList/ItemDetail.tsx | 56 +++++++++ .../src/components/VisitList/ItemName.tsx | 41 +++++++ .../src/components/VisitList/VisitList.tsx | 102 ++++++++++++++++ .../components/VisitList/VisitListEmpty.tsx | 30 +++++ .../src/components/VisitList/VisitListFew.tsx | 26 ++++ .../components/VisitList/VisitListItem.tsx | 55 +++++++++ .../VisitList/VisitListSkeleton.tsx | 79 ++++++++++++ .../home/src/components/VisitList/index.ts | 17 +++ .../RecentlyVisited/Actions.tsx | 37 ++++++ .../RecentlyVisited/Content.tsx | 62 +++++++++- .../RecentlyVisited/Context.tsx | 92 ++++++++++++++ .../RecentlyVisited.stories.tsx | 112 +++++++++++++++++- .../RecentlyVisited/RecentlyVisited.tsx | 21 +++- .../RecentlyVisited/index.ts | 3 + plugins/home/src/homePageComponents/index.ts | 1 + plugins/home/src/index.ts | 1 + plugins/home/src/plugin.ts | 7 +- yarn.lock | 2 + 23 files changed, 1020 insertions(+), 24 deletions(-) create mode 100644 plugins/home/src/api/VisitsApi.ts create mode 100644 plugins/home/src/api/index.ts create mode 100644 plugins/home/src/components/VisitList/ItemCategory.tsx create mode 100644 plugins/home/src/components/VisitList/ItemDetail.tsx create mode 100644 plugins/home/src/components/VisitList/ItemName.tsx create mode 100644 plugins/home/src/components/VisitList/VisitList.tsx create mode 100644 plugins/home/src/components/VisitList/VisitListEmpty.tsx create mode 100644 plugins/home/src/components/VisitList/VisitListFew.tsx create mode 100644 plugins/home/src/components/VisitList/VisitListItem.tsx create mode 100644 plugins/home/src/components/VisitList/VisitListSkeleton.tsx create mode 100644 plugins/home/src/components/VisitList/index.ts create mode 100644 plugins/home/src/homePageComponents/RecentlyVisited/Actions.tsx create mode 100644 plugins/home/src/homePageComponents/RecentlyVisited/Context.tsx diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 497b11224d..3ea2b23df1 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -5,6 +5,7 @@ ```ts /// <reference types="react" /> +import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { CardConfig as CardConfig_2 } from '@backstage/plugin-home-react'; import { CardExtensionProps as CardExtensionProps_2 } from '@backstage/plugin-home-react'; @@ -13,7 +14,7 @@ import { CardSettings as CardSettings_2 } from '@backstage/plugin-home-react'; import { ComponentParts as ComponentParts_2 } from '@backstage/plugin-home-react'; import { ComponentRenderer as ComponentRenderer_2 } from '@backstage/plugin-home-react'; import { createCardExtension as createCardExtension_2 } from '@backstage/plugin-home-react'; -import { JSX as JSX_2 } from 'react'; +import { JsonValue } from '@backstage/types'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; @@ -49,7 +50,7 @@ export const ComponentAccordion: (props: { Actions?: (() => JSX.Element) | undefined; Settings?: (() => JSX.Element) | undefined; ContextProvider?: ((props: any) => JSX.Element) | undefined; -}) => JSX_2.Element; +}) => JSX.Element; // @public @deprecated (undocumented) export type ComponentParts = ComponentParts_2; @@ -62,7 +63,7 @@ export const ComponentTab: (props: { title: string; Content: () => JSX.Element; ContextProvider?: ((props: any) => JSX.Element) | undefined; -}) => JSX_2.Element; +}) => JSX.Element; // @public (undocumented) export const ComponentTabs: (props: { @@ -71,7 +72,7 @@ export const ComponentTabs: (props: { label: string; Component: () => JSX.Element; }[]; -}) => JSX_2.Element; +}) => JSX.Element; // @public @deprecated (undocumented) export const createCardExtension: typeof createCardExtension_2; @@ -79,7 +80,7 @@ export const createCardExtension: typeof createCardExtension_2; // @public export const CustomHomepageGrid: ( props: CustomHomepageGridProps, -) => React_2.JSX.Element; +) => JSX.Element; // @public export type CustomHomepageGridProps = { @@ -101,36 +102,41 @@ export type CustomHomepageGridProps = { export const HeaderWorldClock: (props: { clockConfigs: ClockConfig[]; customTimeFormat?: Intl.DateTimeFormatOptions | undefined; -}) => JSX_2.Element | null; +}) => JSX.Element | null; // @public export const HomePageCompanyLogo: (props: { logo?: ReactNode; className?: string | undefined; -}) => JSX_2.Element; +}) => JSX.Element; // @public (undocumented) export const HomepageCompositionRoot: (props: { title?: string | undefined; children?: ReactNode; -}) => JSX_2.Element; +}) => JSX.Element; // @public (undocumented) export const HomePageRandomJoke: ( props: CardExtensionProps_2<{ defaultCategory?: 'any' | 'programming' | undefined; }>, -) => JSX_2.Element; +) => JSX.Element; // @public export const HomePageStarredEntities: ( props: CardExtensionProps_2<unknown>, -) => JSX_2.Element; +) => JSX.Element; // @public export const HomePageToolkit: ( props: CardExtensionProps_2<ToolkitContentProps>, -) => JSX_2.Element; +) => JSX.Element; + +// @public +export const HomePageVisitedByType: ( + props: CardExtensionProps_2<VisitedByTypeProps>, +) => JSX.Element; // @public (undocumented) export const homePlugin: BackstagePlugin< @@ -161,7 +167,7 @@ export const SettingsModal: (props: { close: Function; componentName?: string | undefined; children: JSX.Element; -}) => JSX_2.Element; +}) => JSX.Element; // @public (undocumented) export const TemplateBackstageLogo: (props: { @@ -169,10 +175,10 @@ export const TemplateBackstageLogo: (props: { svg: string; path: string; }; -}) => React_2.JSX.Element; +}) => JSX.Element; // @public (undocumented) -export const TemplateBackstageLogoIcon: () => React_2.JSX.Element; +export const TemplateBackstageLogoIcon: () => JSX.Element; // @public (undocumented) export type Tool = { @@ -186,13 +192,73 @@ export type ToolkitContentProps = { tools: Tool[]; }; +// Warning: (ae-missing-release-tag) "Visit" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type Visit = { + id: string; + name: string; + pathname: string; + hits: number; + timestamp: number; + entityRef?: string; +}; + +// Warning: (ae-missing-release-tag) "VisitedByTypeProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type VisitedByTypeProps = { + visits?: Array<Visit>; + numVisitsOpen?: number; + numVisitsTotal?: number; + loading?: boolean; + kind: VisitedByTypeKind; +}; + +// Warning: (ae-missing-release-tag) "VisitFilter" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type VisitFilter = { + field: string; + operator: '<' | '<=' | '==' | '>' | '>=' | 'contains'; + value: JsonValue; +}; + +// Warning: (ae-missing-release-tag) "VisitsApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface VisitsApi { + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + listUserVisits(queryParams: VisitsApiQueryParams): Promise<Visit[]>; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + saveVisit(pageVisit: Omit<Visit, 'id' | 'hits' | 'timestamp'>): Promise<void>; +} + +// Warning: (ae-missing-release-tag) "VisitsApiQueryParams" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type VisitsApiQueryParams = { + limit?: number; + orderBy?: Record<string, 'asc' | 'desc'>; + filterBy?: VisitFilter[]; +}; + +// Warning: (ae-missing-release-tag) "visitsApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const visitsApiRef: ApiRef<VisitsApi>; + // @public export const WelcomeTitle: ({ language, -}: WelcomeTitleLanguageProps) => JSX_2.Element; +}: WelcomeTitleLanguageProps) => JSX.Element; // @public (undocumented) export type WelcomeTitleLanguageProps = { language?: string[]; }; + +// Warnings were encountered during analysis: +// +// src/homePageComponents/VisitedByType/Content.d.ts:9:5 - (ae-forgotten-export) The symbol "VisitedByTypeKind" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/home/package.json b/plugins/home/package.json index bba62e9706..9a692557b1 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -41,6 +41,7 @@ "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-home-react": "workspace:^", "@backstage/theme": "workspace:^", + "@backstage/types": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", @@ -49,6 +50,7 @@ "@rjsf/utils": "5.13.0", "@rjsf/validator-ajv8": "5.13.0", "@types/react": "^16.13.1 || ^17.0.0", + "date-fns": "^2.30.0", "lodash": "^4.17.21", "react-grid-layout": "^1.3.4", "react-resizable": "^3.0.4", diff --git a/plugins/home/src/api/VisitsApi.ts b/plugins/home/src/api/VisitsApi.ts new file mode 100644 index 0000000000..a00897fb78 --- /dev/null +++ b/plugins/home/src/api/VisitsApi.ts @@ -0,0 +1,106 @@ +/* + * 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'; +import { JsonValue } from '@backstage/types'; + +/** + @experimental + * Model for a visit entity. + */ +export type Visit = { + /** + * The auto-generated visit identification. + */ + id: string; + /** + * The visited entity, usually an entity id. + */ + name: string; + /** + * The visited url pathname, usually the entity route. + */ + pathname: string; + /** + * An individual view count. + */ + hits: number; + /** + * Last date and time of visit. Format: unix epoch in ms. + */ + timestamp: number; + /** + * Optional entity reference. See stringifyEntityRef from catalog-model. + */ + entityRef?: string; +}; + +export type VisitFilter = { + field: string; + operator: '<' | '<=' | '==' | '>' | '>=' | 'contains'; + value: JsonValue; +}; + +/** + @experimental + * This data structure represents the parameters associated with search queries for visits. + */ +export type VisitsApiQueryParams = { + /** + * Limits the number of results returned. The default is 8. + */ + limit?: number; + /** + * A record for which the key is a field name to sort on, and the value is the sort direction. + * For a multi-field sorting query, add multi entries to the record. + * @example + * Sort ascending by the timestamp field. + * ``` + * { orderBy: { timestamp: 'asc' } } + * ``` + */ + orderBy?: Record<string, 'asc' | 'desc'>; + /** + * Allows filtering visits on number of hits, timestamp and/or entityRef attributes. + * @example + * Most popular docs on the past 7 days + * ``` + * { orderBy: { hits: 'desc' }, filterBy: [{ field: 'timestamp', operator: '>=', value: <date> }, { field: 'entityRef', operator: 'contains', value: 'docs' }] } + * ``` + */ + filterBy?: VisitFilter[]; +}; + +/** + * @experimental + * Visits API public contract. + */ +export interface VisitsApi { + /** + * Persist a new visit. + * @param pageVisit | a new visit data. + */ + saveVisit(pageVisit: Omit<Visit, 'id' | 'hits' | 'timestamp'>): Promise<void>; + /** + * Get the logged user visits. + * @param queryParams | optional search query params. + */ + listUserVisits(queryParams: VisitsApiQueryParams): Promise<Visit[]>; +} + +export const visitsApiRef = createApiRef<VisitsApi>({ + id: 'homepage.visits', +}); diff --git a/plugins/home/src/api/index.ts b/plugins/home/src/api/index.ts new file mode 100644 index 0000000000..29a8fb5468 --- /dev/null +++ b/plugins/home/src/api/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 * from './VisitsApi'; diff --git a/plugins/home/src/components/VisitList/ItemCategory.tsx b/plugins/home/src/components/VisitList/ItemCategory.tsx new file mode 100644 index 0000000000..0f9636ce31 --- /dev/null +++ b/plugins/home/src/components/VisitList/ItemCategory.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 React from 'react'; +import { Chip, makeStyles } from '@material-ui/core'; +import { colorVariants } from '@backstage/theme'; +import { Visit } from '../../api/VisitsApi'; +import { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model'; + +const useStyles = makeStyles(theme => ({ + chip: { + color: theme.palette.common.white, + fontWeight: 'bold', + margin: 0, + }, +})); +const maybeEntity = (visit: Visit): CompoundEntityRef | undefined => { + try { + return parseEntityRef(visit?.entityRef ?? ''); + } catch (e) { + return undefined; + } +}; +const getColorByIndex = (index: number) => { + const variants = Object.keys(colorVariants); + const variantIndex = index % variants.length; + return colorVariants[variants[variantIndex]][0]; +}; +const getChipColor = (entity: CompoundEntityRef | undefined): string => { + const defaultColor = getColorByIndex(0); + if (!entity) return defaultColor; + + // IDEA: Use or replicate useAllKinds hook thus supporting all software catalog + // registered kinds. See: + // plugins/catalog-react/src/components/EntityKindPicker/kindFilterUtils.ts + // Provide extension point to register your own color code. + const entityKinds = [ + 'component', + 'template', + 'api', + 'group', + 'user', + 'resource', + 'system', + 'domain', + 'location', + ]; + const foundIndex = entityKinds.indexOf( + entity.kind.toLocaleLowerCase('en-US'), + ); + return foundIndex === -1 ? defaultColor : getColorByIndex(foundIndex + 1); +}; + +export const ItemCategory = ({ visit }: { visit: Visit }) => { + const classes = useStyles(); + const entity = maybeEntity(visit); + + return ( + <Chip + size="small" + className={classes.chip} + label={(entity?.kind ?? 'Other').toLocaleLowerCase('en-US')} + style={{ background: getChipColor(entity) }} + /> + ); +}; diff --git a/plugins/home/src/components/VisitList/ItemDetail.tsx b/plugins/home/src/components/VisitList/ItemDetail.tsx new file mode 100644 index 0000000000..5bdbdc0db4 --- /dev/null +++ b/plugins/home/src/components/VisitList/ItemDetail.tsx @@ -0,0 +1,56 @@ +/* + * 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 { Typography } from '@material-ui/core'; +import { Visit } from '../../api/VisitsApi'; +import { format, formatDistance, formatISO, isToday } from 'date-fns'; + +const ItemDetailHits = ({ visit }: { visit: Visit }) => ( + <Typography component="span" variant="caption" color="textSecondary"> + {visit.hits} time{visit.hits > 1 ? 's' : ''} + </Typography> +); + +const ItemDetailTimeAgo = ({ visit }: { visit: Visit }) => ( + <Typography + component="time" + variant="caption" + color="textSecondary" + dateTime={formatISO(visit.timestamp)} + > + {isToday(visit.timestamp) + ? format(visit.timestamp, 'HH:mm') + : formatDistance(visit.timestamp, Date.now(), { + addSuffix: true, + })} + </Typography> +); + +export type ItemDetailType = 'time-ago' | 'hits'; + +export const ItemDetail = ({ + visit, + type, +}: { + visit: Visit; + type: ItemDetailType; +}) => + type === 'time-ago' ? ( + <ItemDetailTimeAgo visit={visit} /> + ) : ( + <ItemDetailHits visit={visit} /> + ); diff --git a/plugins/home/src/components/VisitList/ItemName.tsx b/plugins/home/src/components/VisitList/ItemName.tsx new file mode 100644 index 0000000000..965ad80d5e --- /dev/null +++ b/plugins/home/src/components/VisitList/ItemName.tsx @@ -0,0 +1,41 @@ +/* + * 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 { Typography, makeStyles } from '@material-ui/core'; +import { Visit } from '../../api/VisitsApi'; +import { Link } from '@backstage/core-components'; + +const useStyles = makeStyles(_theme => ({ + name: { + marginLeft: '0.8rem', + marginRight: '0.8rem', + }, +})); +export const ItemName = ({ visit }: { visit: Visit }) => { + const classes = useStyles(); + + return ( + <Typography + component={Link} + to={visit.pathname} + noWrap + className={classes.name} + > + {visit.name} + </Typography> + ); +}; diff --git a/plugins/home/src/components/VisitList/VisitList.tsx b/plugins/home/src/components/VisitList/VisitList.tsx new file mode 100644 index 0000000000..e118058857 --- /dev/null +++ b/plugins/home/src/components/VisitList/VisitList.tsx @@ -0,0 +1,102 @@ +/* + * 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 { Collapse, List, Typography, makeStyles } from '@material-ui/core'; +import { Visit } from '../../api/VisitsApi'; +import { VisitListItem } from './VisitListItem'; +import { ItemDetailType } from './ItemDetail'; +import { VisitListEmpty } from './VisitListEmpty'; +import { VisitListFew } from './VisitListFew'; +import { VisitListSkeleton } from './VisitListSkeleton'; + +const useStyles = makeStyles(_theme => ({ + title: { + marginBottom: '2rem', + }, +})); + +export const VisitList = ({ + visits, + title, + detailType, + numVisitsOpen = 3, + numVisitsTotal = 8, + collapsed = true, + loading = false, +}: { + visits: Array<Visit>; + title: string; + detailType: ItemDetailType; + numVisitsOpen?: number; + numVisitsTotal?: number; + collapsed: boolean; + loading: boolean; +}) => { + const classes = useStyles(); + + let listBody: React.ReactElement = <></>; + if (loading) { + listBody = ( + <VisitListSkeleton + numVisitsOpen={numVisitsOpen} + numVisitsTotal={numVisitsTotal} + collapsed={collapsed} + /> + ); + } else if (visits.length === 0) { + listBody = <VisitListEmpty />; + } else if (visits.length < numVisitsOpen) { + listBody = ( + <> + {visits.map((visit, index) => ( + <VisitListItem visit={visit} key={index} detailType={detailType} /> + ))} + <VisitListFew /> + </> + ); + } else { + listBody = ( + <> + {visits.slice(0, numVisitsOpen).map((visit, index) => ( + <VisitListItem visit={visit} key={index} detailType={detailType} /> + ))} + {visits.length > numVisitsOpen && ( + <Collapse in={!collapsed}> + {visits.slice(numVisitsOpen, numVisitsTotal).map((visit, index) => ( + <VisitListItem + visit={visit} + key={index} + detailType={detailType} + /> + ))} + </Collapse> + )} + </> + ); + } + + return ( + <> + <Typography variant="h5" className={classes.title}> + {title} + </Typography> + <List dense disablePadding> + {listBody} + </List> + </> + ); +}; diff --git a/plugins/home/src/components/VisitList/VisitListEmpty.tsx b/plugins/home/src/components/VisitList/VisitListEmpty.tsx new file mode 100644 index 0000000000..3996f0f863 --- /dev/null +++ b/plugins/home/src/components/VisitList/VisitListEmpty.tsx @@ -0,0 +1,30 @@ +/* + * 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 { Typography } from '@material-ui/core'; + +export const VisitListEmpty = () => ( + <> + <Typography variant="body2" color="textSecondary"> + There are no visits to show yet. + </Typography> + <Typography variant="body2" color="textSecondary"> + Once you start using Backstage, your visits will appear here as a quick + link to carry on where you left off. + </Typography> + </> +); diff --git a/plugins/home/src/components/VisitList/VisitListFew.tsx b/plugins/home/src/components/VisitList/VisitListFew.tsx new file mode 100644 index 0000000000..c28f1af931 --- /dev/null +++ b/plugins/home/src/components/VisitList/VisitListFew.tsx @@ -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. + */ + +import React from 'react'; +import { Typography } from '@material-ui/core'; + +export const VisitListFew = () => ( + <> + <Typography variant="body2" color="textSecondary"> + The more pages you visit, the more pages will appear here. + </Typography> + </> +); diff --git a/plugins/home/src/components/VisitList/VisitListItem.tsx b/plugins/home/src/components/VisitList/VisitListItem.tsx new file mode 100644 index 0000000000..20087c884a --- /dev/null +++ b/plugins/home/src/components/VisitList/VisitListItem.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 React from 'react'; +import { + ListItem, + ListItemAvatar, + ListItemText, + makeStyles, +} from '@material-ui/core'; +import { Visit } from '../../api/VisitsApi'; +import { ItemName } from './ItemName'; +import { ItemDetail, ItemDetailType } from './ItemDetail'; +import { ItemCategory } from './ItemCategory'; + +const useStyles = makeStyles(_theme => ({ + avatar: { + minWidth: 0, + }, +})); +export const VisitListItem = ({ + visit, + detailType, +}: { + visit: Visit; + detailType: ItemDetailType; +}) => { + const classes = useStyles(); + + return ( + <ListItem disableGutters> + <ListItemAvatar className={classes.avatar}> + <ItemCategory visit={visit} /> + </ListItemAvatar> + <ListItemText + primary={<ItemName visit={visit} />} + secondary={<ItemDetail visit={visit} type={detailType} />} + disableTypography + /> + </ListItem> + ); +}; diff --git a/plugins/home/src/components/VisitList/VisitListSkeleton.tsx b/plugins/home/src/components/VisitList/VisitListSkeleton.tsx new file mode 100644 index 0000000000..94ba840d9d --- /dev/null +++ b/plugins/home/src/components/VisitList/VisitListSkeleton.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 React from 'react'; +import { + Collapse, + ListItem, + ListItemAvatar, + ListItemText, + makeStyles, +} from '@material-ui/core'; +import { Skeleton } from '@material-ui/lab'; + +const useStyles = makeStyles(_theme => ({ + skeleton: { + borderRadius: 30, + }, +})); + +const VisitListItemSkeleton = () => { + const classes = useStyles(); + + return ( + <ListItem disableGutters> + <ListItemAvatar> + <Skeleton + className={classes.skeleton} + variant="rect" + width={50} + height={24} + /> + </ListItemAvatar> + <ListItemText + primary={<Skeleton variant="text" width="100%" height={28} />} + disableTypography + /> + </ListItem> + ); +}; + +export const VisitListSkeleton = ({ + numVisitsOpen, + numVisitsTotal, + collapsed, +}: { + numVisitsOpen: number; + numVisitsTotal: number; + collapsed: boolean; +}) => ( + <> + {Array(numVisitsOpen) + .fill(null) + .map((_e, index) => ( + <VisitListItemSkeleton key={index} /> + ))} + {numVisitsTotal > numVisitsOpen && ( + <Collapse in={!collapsed}> + {Array(numVisitsTotal - numVisitsOpen) + .fill(null) + .map((_e, index) => ( + <VisitListItemSkeleton key={index} /> + ))} + </Collapse> + )} + </> +); diff --git a/plugins/home/src/components/VisitList/index.ts b/plugins/home/src/components/VisitList/index.ts new file mode 100644 index 0000000000..2d9513893b --- /dev/null +++ b/plugins/home/src/components/VisitList/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 { VisitList } from './VisitList'; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/Actions.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/Actions.tsx new file mode 100644 index 0000000000..45e67802c9 --- /dev/null +++ b/plugins/home/src/homePageComponents/RecentlyVisited/Actions.tsx @@ -0,0 +1,37 @@ +/* + * 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, { useCallback } from 'react'; +import { Button } from '@material-ui/core'; +import { useContext } from './Context'; + +export const Actions = () => { + const { collapsed, setCollapsed, visits, numVisitsOpen, loading } = + useContext(); + const onClick = useCallback( + () => setCollapsed(prevCollapsed => !prevCollapsed), + [setCollapsed], + ); + const label = collapsed ? 'View More' : 'View Less'; + + if (!loading && visits.length <= numVisitsOpen) return <></>; + + return ( + <Button variant="text" onClick={onClick}> + {label} + </Button> + ); +}; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx index 4d06751e22..d9b6128cc4 100644 --- a/plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx +++ b/plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx @@ -14,11 +14,69 @@ * limitations under the License. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { RecentlyVisited } from './RecentlyVisited'; +import { Visit, visitsApiRef } from '../../api/VisitsApi'; +import { useContext } from './Context'; +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; + +export type RecentlyVisitedProps = { + visits?: Array<Visit>; + numVisitsOpen?: number; + numVisitsTotal?: number; + loading?: boolean; +}; /** * Display recently visited pages for the homepage * @public */ -export const Content = () => <RecentlyVisited />; +export const Content = ({ + visits, + numVisitsOpen, + numVisitsTotal, + loading, +}: RecentlyVisitedProps) => { + const { setVisits, setNumVisitsOpen, setNumVisitsTotal, setLoading } = + useContext(); + // Allows behavior override from properties + useEffect(() => { + if (visits) { + setVisits(visits); + setLoading(false); + } else if (loading) { + setLoading(loading); + } + if (numVisitsOpen) setNumVisitsOpen(numVisitsOpen); + if (numVisitsTotal) setNumVisitsTotal(numVisitsTotal); + }, [ + visits, + numVisitsOpen, + numVisitsTotal, + loading, + setVisits, + setNumVisitsOpen, + setNumVisitsTotal, + setLoading, + ]); + // Fetches data from visitsApi in case visits and loading are not provided + const visitsApi = useApi(visitsApiRef); + const { loading: reqLoading } = useAsync(async () => { + if (!visits && !loading) { + await visitsApi + .listUserVisits({ + limit: numVisitsTotal ?? 8, + orderBy: { timestamp: 'desc' }, + }) + .then(setVisits); + } + }, [visitsApi, visits, loading, setVisits]); + useEffect(() => { + if (!loading) { + setLoading(reqLoading); + } + }, [loading, setLoading, reqLoading]); + + return <RecentlyVisited />; +}; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/Context.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/Context.tsx new file mode 100644 index 0000000000..44c8fe322b --- /dev/null +++ b/plugins/home/src/homePageComponents/RecentlyVisited/Context.tsx @@ -0,0 +1,92 @@ +/* + * 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, { createContext } from 'react'; +import { Visit } from '../../api/VisitsApi'; + +export type ContextValue = { + collapsed: boolean; + setCollapsed: React.Dispatch<React.SetStateAction<boolean>>; + numVisitsOpen: number; + setNumVisitsOpen: React.Dispatch<React.SetStateAction<number>>; + numVisitsTotal: number; + setNumVisitsTotal: React.Dispatch<React.SetStateAction<number>>; + visits: Array<Visit>; + setVisits: React.Dispatch<React.SetStateAction<Array<Visit>>>; + loading: boolean; + setLoading: React.Dispatch<boolean>; +}; + +const defaultContextValue = { + collapsed: true, + setCollapsed: () => {}, + numVisitsOpen: 3, + setNumVisitsOpen: () => {}, + numVisitsTotal: 8, + setNumVisitsTotal: () => {}, + visits: [], + setVisits: () => {}, + loading: true, + setLoading: () => {}, +}; + +const Context = createContext<ContextValue>(defaultContextValue); + +export const ContextProvider = ({ children }: { children: JSX.Element }) => { + const [collapsed, setCollapsed] = React.useState( + defaultContextValue.collapsed, + ); + const [numVisitsOpen, setNumVisitsOpen] = React.useState( + defaultContextValue.numVisitsOpen, + ); + const [numVisitsTotal, setNumVisitsTotal] = React.useState( + defaultContextValue.numVisitsTotal, + ); + const [visits, setVisits] = React.useState<Array<Visit>>( + defaultContextValue.visits, + ); + const [loading, setLoading] = React.useState<boolean>( + defaultContextValue.loading, + ); + + const value: ContextValue = { + collapsed, + setCollapsed, + numVisitsOpen, + setNumVisitsOpen, + numVisitsTotal, + setNumVisitsTotal, + visits, + setVisits, + loading, + setLoading, + }; + + return <Context.Provider value={value}>{children}</Context.Provider>; +}; + +export const useContext = () => { + const value = React.useContext(Context); + + if (value === undefined) + throw new Error( + 'RecentlyVisited useContext found undefined ContextValue, <ContextProvider/> could be missing', + ); + + return value; +}; + +export default Context; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx index bb04a1ebc7..cd3db0eb7b 100644 --- a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx +++ b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx @@ -15,15 +15,91 @@ */ import React from 'react'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { TestApiProvider, wrapInTestApp } from '@backstage/test-utils'; import { ComponentType, PropsWithChildren } from 'react'; import { Grid } from '@material-ui/core'; import { HomePageRecentlyVisited } from '../../plugin'; +import { Visit, visitsApiRef } from '../../api/VisitsApi'; + +const visits: Array<Visit> = [ + { + id: 'explore', + name: 'Explore Backstage', + pathname: '/explore', + hits: 35, + timestamp: Date.now() - 86400_000 * 1, + }, + { + id: 'user-1', + name: 'Guest', + pathname: '/catalog/default/user/guest', + hits: 30, + timestamp: Date.now() - 86400_000 * 2, + entityRef: 'User:default/guest', + }, + { + id: 'audio-playback', + name: 'Audio Playback', + pathname: '/catalog/default/system/audio-playback', + hits: 25, + timestamp: Date.now() - 86400_000 * 3, + entityRef: 'System:default/audio-playback', + }, + { + id: 'team-a', + name: 'Team A', + pathname: '/catalog/default/group/team-a', + hits: 20, + timestamp: Date.now() - 86400_000 * 4, + entityRef: 'Group:default/team-a', + }, + { + id: 'playback-order', + name: 'Playback Order', + pathname: '/catalog/default/component/playback-order', + hits: 15, + timestamp: Date.now() - 86400_000 * 5, + entityRef: 'Component:default/playback-order', + }, + { + id: 'playback', + name: 'Playback', + pathname: '/catalog/default/domain/playback', + hits: 10, + timestamp: Date.now() - 86400_000 * 6, + entityRef: 'Domain:default/playback', + }, + { + id: 'hello-world', + name: 'Hello World gRPC', + pathname: '/catalog/default/api/hello-world', + hits: 5, + timestamp: Date.now() - 86400_000 * 7, + entityRef: 'API:default/hello-world', + }, + { + id: 'tech-radar', + name: 'Tech Radar', + pathname: '/tech-radar', + hits: 1, + timestamp: Date.now() - 360_000, + }, +]; + +const mockVisitsApi = { + saveVisit: async () => {}, + listUserVisits: async () => visits, +}; export default { title: 'Plugins/Home/Components/RecentlyVisited', decorators: [ - (Story: ComponentType<PropsWithChildren<{}>>) => wrapInTestApp(<Story />), + (Story: ComponentType<PropsWithChildren<{}>>) => + wrapInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <Story /> + </TestApiProvider>, + ), ], }; @@ -34,3 +110,35 @@ export const Default = () => { </Grid> ); }; + +export const Empty = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageRecentlyVisited visits={[]} /> + </Grid> + ); +}; + +export const FewItems = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageRecentlyVisited visits={visits.slice(0, 1)} /> + </Grid> + ); +}; + +export const MoreItems = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageRecentlyVisited numVisitsOpen={5} numVisitsTotal={6} /> + </Grid> + ); +}; + +export const Loading = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageRecentlyVisited numVisitsOpen={5} numVisitsTotal={6} loading /> + </Grid> + ); +}; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx index 6f2abe3b60..121d15b1d2 100644 --- a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx +++ b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx @@ -15,10 +15,25 @@ */ import React from 'react'; -import Typography from '@material-ui/core/Typography'; - +import { VisitList } from '../../components/VisitList'; +import { useContext } from './Context'; /** * Display recently visited pages for the homepage * @public */ -export const RecentlyVisited = () => <Typography>RecentlyVisited</Typography>; +export const RecentlyVisited = () => { + const { collapsed, numVisitsOpen, numVisitsTotal, visits, loading } = + useContext(); + + return ( + <VisitList + visits={visits} + title="Recently visited" + detailType="time-ago" + collapsed={collapsed} + numVisitsOpen={numVisitsOpen} + numVisitsTotal={numVisitsTotal} + loading={loading} + /> + ); +}; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/index.ts b/plugins/home/src/homePageComponents/RecentlyVisited/index.ts index f1cdf3734f..8caf533ab1 100644 --- a/plugins/home/src/homePageComponents/RecentlyVisited/index.ts +++ b/plugins/home/src/homePageComponents/RecentlyVisited/index.ts @@ -15,3 +15,6 @@ */ export { Content } from './Content'; +export { Actions } from './Actions'; +export { ContextProvider } from './Context'; +export type { RecentlyVisitedProps } from './Content'; diff --git a/plugins/home/src/homePageComponents/index.ts b/plugins/home/src/homePageComponents/index.ts index 36d2335afe..026f068d3f 100644 --- a/plugins/home/src/homePageComponents/index.ts +++ b/plugins/home/src/homePageComponents/index.ts @@ -17,3 +17,4 @@ export type { ToolkitContentProps, Tool } from './Toolkit'; export type { ClockConfig } from './HeaderWorldClock'; export type { WelcomeTitleLanguageProps } from './WelcomeTitle'; +export type { RecentlyVisitedProps } from './RecentlyVisited'; diff --git a/plugins/home/src/index.ts b/plugins/home/src/index.ts index 63407c8531..e133ad49b5 100644 --- a/plugins/home/src/index.ts +++ b/plugins/home/src/index.ts @@ -37,3 +37,4 @@ export * from './components'; export * from './assets'; export * from './homePageComponents'; export * from './deprecated'; +export * from './api'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index 20cfddc724..90ac5c3519 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -20,7 +20,10 @@ import { createRoutableExtension, } from '@backstage/core-plugin-api'; import { createCardExtension } from '@backstage/plugin-home-react'; -import { ToolkitContentProps } from './homePageComponents'; +import { + ToolkitContentProps, + RecentlyVisitedProps, +} from './homePageComponents'; import { rootRouteRef } from './routes'; /** @public */ @@ -178,7 +181,7 @@ export const HeaderWorldClock = homePlugin.provide( * @public */ export const HomePageRecentlyVisited = homePlugin.provide( - createCardExtension({ + createCardExtension<RecentlyVisitedProps>({ name: 'HomePageRecentlyVisited', components: () => import('./homePageComponents/RecentlyVisited'), }), diff --git a/yarn.lock b/yarn.lock index 5a115047db..65ba1a0ec0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7395,6 +7395,7 @@ __metadata: "@backstage/plugin-home-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" + "@backstage/types": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 @@ -7408,6 +7409,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/react-grid-layout": ^1.3.2 + date-fns: ^2.30.0 lodash: ^4.17.21 msw: ^1.0.0 react-grid-layout: ^1.3.4 From 160761b049b22ad16807ea0636322057e54f80ad Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Wed, 23 Aug 2023 16:13:39 +0200 Subject: [PATCH 153/207] feature(home-plugin): Rename component to VisitedByType This renaming is to enable Top Visited and Recently Visited to be served by the same component. This is to reduce code duplication. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 54 +++--- plugins/home/src/api/VisitsApi.ts | 14 +- .../components/VisitList/VisitList.test.tsx | 160 ++++++++++++++++++ .../src/components/VisitList/VisitList.tsx | 8 +- .../RecentlyVisited/Context.tsx | 92 ---------- .../RecentlyVisited/RecentlyVisited.test.tsx | 26 --- .../Actions.tsx | 0 .../VisitedByType/Content.test.tsx | 136 +++++++++++++++ .../Content.tsx | 57 ++++--- .../VisitedByType/Context.tsx | 121 +++++++++++++ .../HomePageVisitedByType.stories.tsx} | 94 +++++++--- .../VisitedByType/VisitedByType.test.tsx | 89 ++++++++++ .../VisitedByType.tsx} | 13 +- .../index.ts | 2 +- plugins/home/src/homePageComponents/index.ts | 2 +- plugins/home/src/index.ts | 1 + plugins/home/src/plugin.ts | 15 +- 17 files changed, 659 insertions(+), 225 deletions(-) create mode 100644 plugins/home/src/components/VisitList/VisitList.test.tsx delete mode 100644 plugins/home/src/homePageComponents/RecentlyVisited/Context.tsx delete mode 100644 plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.test.tsx rename plugins/home/src/homePageComponents/{RecentlyVisited => VisitedByType}/Actions.tsx (100%) create mode 100644 plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx rename plugins/home/src/homePageComponents/{RecentlyVisited => VisitedByType}/Content.tsx (59%) create mode 100644 plugins/home/src/homePageComponents/VisitedByType/Context.tsx rename plugins/home/src/homePageComponents/{RecentlyVisited/RecentlyVisited.stories.tsx => VisitedByType/HomePageVisitedByType.stories.tsx} (65%) create mode 100644 plugins/home/src/homePageComponents/VisitedByType/VisitedByType.test.tsx rename plugins/home/src/homePageComponents/{RecentlyVisited/RecentlyVisited.tsx => VisitedByType/VisitedByType.tsx} (85%) rename plugins/home/src/homePageComponents/{RecentlyVisited => VisitedByType}/index.ts (90%) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 3ea2b23df1..536032a8eb 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -15,6 +15,7 @@ import { ComponentParts as ComponentParts_2 } from '@backstage/plugin-home-react import { ComponentRenderer as ComponentRenderer_2 } from '@backstage/plugin-home-react'; import { createCardExtension as createCardExtension_2 } from '@backstage/plugin-home-react'; import { JsonValue } from '@backstage/types'; +import { JSX as JSX_2 } from 'react'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; @@ -50,7 +51,7 @@ export const ComponentAccordion: (props: { Actions?: (() => JSX.Element) | undefined; Settings?: (() => JSX.Element) | undefined; ContextProvider?: ((props: any) => JSX.Element) | undefined; -}) => JSX.Element; +}) => JSX_2.Element; // @public @deprecated (undocumented) export type ComponentParts = ComponentParts_2; @@ -63,7 +64,7 @@ export const ComponentTab: (props: { title: string; Content: () => JSX.Element; ContextProvider?: ((props: any) => JSX.Element) | undefined; -}) => JSX.Element; +}) => JSX_2.Element; // @public (undocumented) export const ComponentTabs: (props: { @@ -72,7 +73,7 @@ export const ComponentTabs: (props: { label: string; Component: () => JSX.Element; }[]; -}) => JSX.Element; +}) => JSX_2.Element; // @public @deprecated (undocumented) export const createCardExtension: typeof createCardExtension_2; @@ -80,7 +81,7 @@ export const createCardExtension: typeof createCardExtension_2; // @public export const CustomHomepageGrid: ( props: CustomHomepageGridProps, -) => JSX.Element; +) => React_2.JSX.Element; // @public export type CustomHomepageGridProps = { @@ -102,41 +103,41 @@ export type CustomHomepageGridProps = { export const HeaderWorldClock: (props: { clockConfigs: ClockConfig[]; customTimeFormat?: Intl.DateTimeFormatOptions | undefined; -}) => JSX.Element | null; +}) => JSX_2.Element | null; // @public export const HomePageCompanyLogo: (props: { logo?: ReactNode; className?: string | undefined; -}) => JSX.Element; +}) => JSX_2.Element; // @public (undocumented) export const HomepageCompositionRoot: (props: { title?: string | undefined; children?: ReactNode; -}) => JSX.Element; +}) => JSX_2.Element; // @public (undocumented) export const HomePageRandomJoke: ( props: CardExtensionProps_2<{ defaultCategory?: 'any' | 'programming' | undefined; }>, -) => JSX.Element; +) => JSX_2.Element; // @public export const HomePageStarredEntities: ( props: CardExtensionProps_2<unknown>, -) => JSX.Element; +) => JSX_2.Element; // @public export const HomePageToolkit: ( props: CardExtensionProps_2<ToolkitContentProps>, -) => JSX.Element; +) => JSX_2.Element; // @public export const HomePageVisitedByType: ( props: CardExtensionProps_2<VisitedByTypeProps>, -) => JSX.Element; +) => JSX_2.Element; // @public (undocumented) export const homePlugin: BackstagePlugin< @@ -167,7 +168,7 @@ export const SettingsModal: (props: { close: Function; componentName?: string | undefined; children: JSX.Element; -}) => JSX.Element; +}) => JSX_2.Element; // @public (undocumented) export const TemplateBackstageLogo: (props: { @@ -175,10 +176,10 @@ export const TemplateBackstageLogo: (props: { svg: string; path: string; }; -}) => JSX.Element; +}) => React_2.JSX.Element; // @public (undocumented) -export const TemplateBackstageLogoIcon: () => JSX.Element; +export const TemplateBackstageLogoIcon: () => React_2.JSX.Element; // @public (undocumented) export type Tool = { @@ -192,8 +193,6 @@ export type ToolkitContentProps = { tools: Tool[]; }; -// Warning: (ae-missing-release-tag) "Visit" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type Visit = { id: string; @@ -204,8 +203,9 @@ export type Visit = { entityRef?: string; }; -// Warning: (ae-missing-release-tag) "VisitedByTypeProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public (undocumented) +export type VisitedByTypeKind = 'recent' | 'top'; + // @public (undocumented) export type VisitedByTypeProps = { visits?: Array<Visit>; @@ -215,8 +215,6 @@ export type VisitedByTypeProps = { kind: VisitedByTypeKind; }; -// Warning: (ae-missing-release-tag) "VisitFilter" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type VisitFilter = { field: string; @@ -224,18 +222,12 @@ export type VisitFilter = { value: JsonValue; }; -// Warning: (ae-missing-release-tag) "VisitsApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface VisitsApi { - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - listUserVisits(queryParams: VisitsApiQueryParams): Promise<Visit[]>; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + listUserVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; saveVisit(pageVisit: Omit<Visit, 'id' | 'hits' | 'timestamp'>): Promise<void>; } -// Warning: (ae-missing-release-tag) "VisitsApiQueryParams" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type VisitsApiQueryParams = { limit?: number; @@ -243,22 +235,16 @@ export type VisitsApiQueryParams = { filterBy?: VisitFilter[]; }; -// Warning: (ae-missing-release-tag) "visitsApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const visitsApiRef: ApiRef<VisitsApi>; // @public export const WelcomeTitle: ({ language, -}: WelcomeTitleLanguageProps) => JSX.Element; +}: WelcomeTitleLanguageProps) => JSX_2.Element; // @public (undocumented) export type WelcomeTitleLanguageProps = { language?: string[]; }; - -// Warnings were encountered during analysis: -// -// src/homePageComponents/VisitedByType/Content.d.ts:9:5 - (ae-forgotten-export) The symbol "VisitedByTypeKind" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/home/src/api/VisitsApi.ts b/plugins/home/src/api/VisitsApi.ts index a00897fb78..8d5ae3f8cb 100644 --- a/plugins/home/src/api/VisitsApi.ts +++ b/plugins/home/src/api/VisitsApi.ts @@ -18,7 +18,7 @@ import { createApiRef } from '@backstage/core-plugin-api'; import { JsonValue } from '@backstage/types'; /** - @experimental + * @public * Model for a visit entity. */ export type Visit = { @@ -48,6 +48,7 @@ export type Visit = { entityRef?: string; }; +/** @public */ export type VisitFilter = { field: string; operator: '<' | '<=' | '==' | '>' | '>=' | 'contains'; @@ -55,7 +56,7 @@ export type VisitFilter = { }; /** - @experimental + * @public * This data structure represents the parameters associated with search queries for visits. */ export type VisitsApiQueryParams = { @@ -85,22 +86,23 @@ export type VisitsApiQueryParams = { }; /** - * @experimental + * @public * Visits API public contract. */ export interface VisitsApi { /** * Persist a new visit. - * @param pageVisit | a new visit data. + * @param pageVisit - a new visit data */ saveVisit(pageVisit: Omit<Visit, 'id' | 'hits' | 'timestamp'>): Promise<void>; /** * Get the logged user visits. - * @param queryParams | optional search query params. + * @param queryParams - optional search query params. */ - listUserVisits(queryParams: VisitsApiQueryParams): Promise<Visit[]>; + listUserVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; } +/** @public */ export const visitsApiRef = createApiRef<VisitsApi>({ id: 'homepage.visits', }); diff --git a/plugins/home/src/components/VisitList/VisitList.test.tsx b/plugins/home/src/components/VisitList/VisitList.test.tsx new file mode 100644 index 0000000000..077c428706 --- /dev/null +++ b/plugins/home/src/components/VisitList/VisitList.test.tsx @@ -0,0 +1,160 @@ +/* + * 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 { VisitList } from './VisitList'; +import { render } from '@testing-library/react'; +import { BrowserRouter } from 'react-router-dom'; + +describe('<VisitList/>', () => { + it('renders with mandatory parameters', async () => { + const { getByText } = await render( + <VisitList title="My title" detailType="time-ago" />, + ); + expect(getByText('My title')).toBeInTheDocument(); + }); + + it('renders skeleton when loading is true', async () => { + const { container } = await render( + <VisitList title="My title" detailType="time-ago" loading />, + ); + expect(container.querySelectorAll('li')).toHaveLength(8); + expect(container.querySelectorAll('.MuiSkeleton-root')).toHaveLength(16); + }); + + it('renders specified amount of items', async () => { + const { container } = await render( + <VisitList + title="My title" + detailType="time-ago" + loading + numVisitsOpen={1} + numVisitsTotal={2} + />, + ); + expect(container.querySelectorAll('li')).toHaveLength(2); + }); + + it('renders some items hidden', async () => { + const { container } = await render( + <VisitList + title="My title" + detailType="time-ago" + loading + numVisitsOpen={1} + numVisitsTotal={2} + />, + ); + expect(container.querySelectorAll('li')[0]).toBeVisible(); + expect(container.querySelectorAll('li')[1]).not.toBeVisible(); + }); + + it('renders all items when not collapsed', async () => { + const { container } = await render( + <VisitList + title="My title" + detailType="time-ago" + loading + collapsed={false} + numVisitsOpen={1} + numVisitsTotal={2} + />, + ); + expect(container.querySelectorAll('li')[0]).toBeVisible(); + expect(container.querySelectorAll('li')[1]).toBeVisible(); + }); + + it('renders visit with time-ago', async () => { + const { container, getByText } = await render( + <BrowserRouter> + <VisitList + title="My title" + detailType="time-ago" + visits={[ + { + id: 'explore', + name: 'Explore Backstage', + pathname: '/explore', + hits: 35, + timestamp: Date.now() - 86400_000, + }, + ]} + /> + , + </BrowserRouter>, + ); + expect(container.querySelectorAll('li')).toHaveLength(1); + expect(getByText('Explore Backstage')).toBeInTheDocument(); + expect(getByText('1 day ago')).toBeInTheDocument(); + }); + + it('renders visit with hits', async () => { + const { container, getByText } = await render( + <BrowserRouter> + <VisitList + title="My title" + detailType="hits" + visits={[ + { + id: 'explore', + name: 'Explore Backstage', + pathname: '/explore', + hits: 35, + timestamp: Date.now() - 86400_000, + }, + ]} + /> + , + </BrowserRouter>, + ); + expect(container.querySelectorAll('li')).toHaveLength(1); + expect(getByText('Explore Backstage')).toBeInTheDocument(); + expect(getByText('35 times')).toBeInTheDocument(); + }); + + it('renders text warning about few items', async () => { + const { getByText } = await render( + <BrowserRouter> + <VisitList + title="My title" + detailType="hits" + visits={[ + { + id: 'explore', + name: 'Explore Backstage', + pathname: '/explore', + hits: 35, + timestamp: Date.now() - 86400_000, + }, + ]} + /> + , + </BrowserRouter>, + ); + expect( + getByText('The more pages you visit, the more pages will appear here.'), + ).toBeInTheDocument(); + }); + + it('renders text warning about no items', async () => { + const { getByText } = await render( + <BrowserRouter> + <VisitList title="My title" detailType="hits" visits={[]} />, + </BrowserRouter>, + ); + expect(getByText('There are no visits to show yet.')).toBeInTheDocument(); + }); +}); diff --git a/plugins/home/src/components/VisitList/VisitList.tsx b/plugins/home/src/components/VisitList/VisitList.tsx index e118058857..f1dc855d9d 100644 --- a/plugins/home/src/components/VisitList/VisitList.tsx +++ b/plugins/home/src/components/VisitList/VisitList.tsx @@ -30,21 +30,21 @@ const useStyles = makeStyles(_theme => ({ })); export const VisitList = ({ - visits, title, detailType, + visits = [], numVisitsOpen = 3, numVisitsTotal = 8, collapsed = true, loading = false, }: { - visits: Array<Visit>; title: string; detailType: ItemDetailType; + visits?: Visit[]; numVisitsOpen?: number; numVisitsTotal?: number; - collapsed: boolean; - loading: boolean; + collapsed?: boolean; + loading?: boolean; }) => { const classes = useStyles(); diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/Context.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/Context.tsx deleted file mode 100644 index 44c8fe322b..0000000000 --- a/plugins/home/src/homePageComponents/RecentlyVisited/Context.tsx +++ /dev/null @@ -1,92 +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 React, { createContext } from 'react'; -import { Visit } from '../../api/VisitsApi'; - -export type ContextValue = { - collapsed: boolean; - setCollapsed: React.Dispatch<React.SetStateAction<boolean>>; - numVisitsOpen: number; - setNumVisitsOpen: React.Dispatch<React.SetStateAction<number>>; - numVisitsTotal: number; - setNumVisitsTotal: React.Dispatch<React.SetStateAction<number>>; - visits: Array<Visit>; - setVisits: React.Dispatch<React.SetStateAction<Array<Visit>>>; - loading: boolean; - setLoading: React.Dispatch<boolean>; -}; - -const defaultContextValue = { - collapsed: true, - setCollapsed: () => {}, - numVisitsOpen: 3, - setNumVisitsOpen: () => {}, - numVisitsTotal: 8, - setNumVisitsTotal: () => {}, - visits: [], - setVisits: () => {}, - loading: true, - setLoading: () => {}, -}; - -const Context = createContext<ContextValue>(defaultContextValue); - -export const ContextProvider = ({ children }: { children: JSX.Element }) => { - const [collapsed, setCollapsed] = React.useState( - defaultContextValue.collapsed, - ); - const [numVisitsOpen, setNumVisitsOpen] = React.useState( - defaultContextValue.numVisitsOpen, - ); - const [numVisitsTotal, setNumVisitsTotal] = React.useState( - defaultContextValue.numVisitsTotal, - ); - const [visits, setVisits] = React.useState<Array<Visit>>( - defaultContextValue.visits, - ); - const [loading, setLoading] = React.useState<boolean>( - defaultContextValue.loading, - ); - - const value: ContextValue = { - collapsed, - setCollapsed, - numVisitsOpen, - setNumVisitsOpen, - numVisitsTotal, - setNumVisitsTotal, - visits, - setVisits, - loading, - setLoading, - }; - - return <Context.Provider value={value}>{children}</Context.Provider>; -}; - -export const useContext = () => { - const value = React.useContext(Context); - - if (value === undefined) - throw new Error( - 'RecentlyVisited useContext found undefined ContextValue, <ContextProvider/> could be missing', - ); - - return value; -}; - -export default Context; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.test.tsx b/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.test.tsx deleted file mode 100644 index 5ccab63fa8..0000000000 --- a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.test.tsx +++ /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. - */ - -import React from 'react'; -import { RecentlyVisited } from './RecentlyVisited'; -import { renderInTestApp } from '@backstage/test-utils'; - -describe('<RecentlyVisited/>', () => { - it('should render', async () => { - const { getByText } = await renderInTestApp(<RecentlyVisited />); - expect(getByText('RecentlyVisited')).toBeInTheDocument(); - }); -}); diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/Actions.tsx b/plugins/home/src/homePageComponents/VisitedByType/Actions.tsx similarity index 100% rename from plugins/home/src/homePageComponents/RecentlyVisited/Actions.tsx rename to plugins/home/src/homePageComponents/VisitedByType/Actions.tsx diff --git a/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx b/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx new file mode 100644 index 0000000000..329bf4e845 --- /dev/null +++ b/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx @@ -0,0 +1,136 @@ +/* + * 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 { Content } from './Content'; +import { TestApiProvider, renderInTestApp } from '@backstage/test-utils'; +import { visitsApiRef } from '../../api'; +import { ContextProvider } from './Context'; +import { waitFor } from '@testing-library/react'; + +const visits = [ + { + id: 'explore', + name: 'Explore Backstage', + pathname: '/explore', + hits: 35, + timestamp: Date.now() - 86400_000, + }, +]; + +const mockVisitsApi = { + saveVisit: async () => {}, + listUserVisits: async () => visits, +}; + +describe('<Content kind="recent"/>', () => { + it('renders', async () => { + const { getByText } = await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <ContextProvider> + <Content kind="recent" /> + </ContextProvider> + </TestApiProvider>, + ); + expect(getByText('Recently Visited')).toBeInTheDocument(); + await waitFor(() => + expect(getByText('Explore Backstage')).toBeInTheDocument(), + ); + }); + + it('allows visits to be overridden', async () => { + const { getByText } = await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <ContextProvider> + <Content + kind="recent" + visits={[ + { + id: 'tech-radar', + name: 'Tech Radar', + pathname: '/tech-radar', + hits: 40, + timestamp: Date.now() - 360_000, + }, + ]} + /> + </ContextProvider> + </TestApiProvider>, + ); + expect(getByText('Recently Visited')).toBeInTheDocument(); + await waitFor(() => expect(getByText('Tech Radar')).toBeInTheDocument()); + }); + + it('allows loading to be overridden', async () => { + const { container } = await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <ContextProvider> + <Content kind="recent" loading /> + </ContextProvider> + </TestApiProvider>, + ); + expect(container.querySelector('.MuiSkeleton-root')).toBeInTheDocument(); + }); + + it('allows number of items to be specified', async () => { + const { container } = await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <ContextProvider> + <Content + kind="recent" + visits={[ + { + id: 'explore', + name: 'Explore Backstage', + pathname: '/explore', + hits: 35, + timestamp: Date.now() - 86400_000, + }, + { + id: 'tech-radar', + name: 'Tech Radar', + pathname: '/tech-radar', + hits: 40, + timestamp: Date.now() - 360_000, + }, + ]} + numVisitsOpen={1} + numVisitsTotal={2} + /> + </ContextProvider> + </TestApiProvider>, + ); + expect(container.querySelectorAll('li')).toHaveLength(2); + expect(container.querySelectorAll('li')[0]).toBeVisible(); + expect(container.querySelectorAll('li')[1]).not.toBeVisible(); + }); +}); + +describe('<Content kind="top"/>', () => { + it('renders', async () => { + const { getByText } = await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <ContextProvider> + <Content kind="top" /> + </ContextProvider> + </TestApiProvider>, + ); + expect(getByText('Top Visited')).toBeInTheDocument(); + await waitFor(() => + expect(getByText('Explore Backstage')).toBeInTheDocument(), + ); + }); +}); diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx b/plugins/home/src/homePageComponents/VisitedByType/Content.tsx similarity index 59% rename from plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx rename to plugins/home/src/homePageComponents/VisitedByType/Content.tsx index d9b6128cc4..62b0de0d7d 100644 --- a/plugins/home/src/homePageComponents/RecentlyVisited/Content.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/Content.tsx @@ -15,17 +15,22 @@ */ import React, { useEffect } from 'react'; -import { RecentlyVisited } from './RecentlyVisited'; +import { VisitedByType } from './VisitedByType'; import { Visit, visitsApiRef } from '../../api/VisitsApi'; -import { useContext } from './Context'; +import { ContextValueOnly, useContext } from './Context'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; -export type RecentlyVisitedProps = { +/** @public */ +export type VisitedByTypeKind = 'recent' | 'top'; + +/** @public */ +export type VisitedByTypeProps = { visits?: Array<Visit>; numVisitsOpen?: number; numVisitsTotal?: number; loading?: boolean; + kind: VisitedByTypeKind; }; /** @@ -37,40 +42,44 @@ export const Content = ({ numVisitsOpen, numVisitsTotal, loading, -}: RecentlyVisitedProps) => { - const { setVisits, setNumVisitsOpen, setNumVisitsTotal, setLoading } = - useContext(); + kind, +}: VisitedByTypeProps) => { + const { setContext, setVisits, setLoading } = useContext(); // Allows behavior override from properties useEffect(() => { + const context: Partial<ContextValueOnly> = {}; + context.kind = kind; if (visits) { - setVisits(visits); - setLoading(false); + context.visits = visits; + context.loading = false; } else if (loading) { - setLoading(loading); + context.loading = loading; } - if (numVisitsOpen) setNumVisitsOpen(numVisitsOpen); - if (numVisitsTotal) setNumVisitsTotal(numVisitsTotal); - }, [ - visits, - numVisitsOpen, - numVisitsTotal, - loading, - setVisits, - setNumVisitsOpen, - setNumVisitsTotal, - setLoading, - ]); + if (numVisitsOpen) context.numVisitsOpen = numVisitsOpen; + if (numVisitsTotal) context.numVisitsTotal = numVisitsTotal; + setContext(state => ({ ...state, ...context })); + }, [setContext, kind, visits, loading, numVisitsOpen, numVisitsTotal]); + // Fetches data from visitsApi in case visits and loading are not provided const visitsApi = useApi(visitsApiRef); const { loading: reqLoading } = useAsync(async () => { - if (!visits && !loading) { - await visitsApi + if (!visits && !loading && kind === 'recent') { + return await visitsApi .listUserVisits({ limit: numVisitsTotal ?? 8, orderBy: { timestamp: 'desc' }, }) .then(setVisits); } + if (!visits && !loading && kind === 'top') { + return await visitsApi + .listUserVisits({ + limit: numVisitsTotal ?? 8, + orderBy: { hits: 'desc' }, + }) + .then(setVisits); + } + return undefined; }, [visitsApi, visits, loading, setVisits]); useEffect(() => { if (!loading) { @@ -78,5 +87,5 @@ export const Content = ({ } }, [loading, setLoading, reqLoading]); - return <RecentlyVisited />; + return <VisitedByType />; }; diff --git a/plugins/home/src/homePageComponents/VisitedByType/Context.tsx b/plugins/home/src/homePageComponents/VisitedByType/Context.tsx new file mode 100644 index 0000000000..0d1c2100f2 --- /dev/null +++ b/plugins/home/src/homePageComponents/VisitedByType/Context.tsx @@ -0,0 +1,121 @@ +/* + * 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, { Dispatch, SetStateAction, createContext, useMemo } from 'react'; +import { Visit } from '../../api/VisitsApi'; +import { VisitedByTypeKind } from './Content'; + +export type ContextValueOnly = { + collapsed: boolean; + numVisitsOpen: number; + numVisitsTotal: number; + visits: Array<Visit>; + loading: boolean; + kind: VisitedByTypeKind; +}; + +export type ContextValue = ContextValueOnly & { + setCollapsed: Dispatch<SetStateAction<boolean>>; + setNumVisitsOpen: Dispatch<SetStateAction<number>>; + setNumVisitsTotal: Dispatch<SetStateAction<number>>; + setVisits: Dispatch<SetStateAction<Array<Visit>>>; + setLoading: Dispatch<SetStateAction<boolean>>; + setKind: Dispatch<SetStateAction<VisitedByTypeKind>>; + setContext: Dispatch<SetStateAction<ContextValueOnly>>; +}; + +const defaultContextValueOnly: ContextValueOnly = { + collapsed: true, + numVisitsOpen: 3, + numVisitsTotal: 8, + visits: [], + loading: true, + kind: 'recent', +}; + +export const defaultContextValue: ContextValue = { + ...defaultContextValueOnly, + setCollapsed: () => {}, + setNumVisitsOpen: () => {}, + setNumVisitsTotal: () => {}, + setVisits: () => {}, + setLoading: () => {}, + setKind: () => {}, + setContext: () => {}, +}; + +export const Context = createContext<ContextValue>(defaultContextValue); + +const getFilteredSet = + ( + setContext: Dispatch<SetStateAction<ContextValueOnly>>, + contextKey: keyof ContextValueOnly, + ) => + (e: SetStateAction<any>) => + setContext(state => ({ + ...state, + [contextKey]: typeof e === 'function' ? e(state[contextKey]) : e, + })); + +export const ContextProvider = ({ children }: { children: JSX.Element }) => { + const [context, setContext] = React.useState<ContextValueOnly>( + defaultContextValueOnly, + ); + const { + setCollapsed, + setNumVisitsOpen, + setNumVisitsTotal, + setVisits, + setLoading, + setKind, + } = useMemo( + () => ({ + setCollapsed: getFilteredSet(setContext, 'collapsed'), + setNumVisitsOpen: getFilteredSet(setContext, 'numVisitsOpen'), + setNumVisitsTotal: getFilteredSet(setContext, 'numVisitsTotal'), + setVisits: getFilteredSet(setContext, 'visits'), + setLoading: getFilteredSet(setContext, 'loading'), + setKind: getFilteredSet(setContext, 'kind'), + }), + [setContext], + ); + + const value: ContextValue = { + ...context, + setContext, + setCollapsed, + setNumVisitsOpen, + setNumVisitsTotal, + setVisits, + setLoading, + setKind, + }; + + return <Context.Provider value={value}>{children}</Context.Provider>; +}; + +export const useContext = () => { + const value = React.useContext(Context); + + if (value === undefined) + throw new Error( + 'VisitedByType useContext found undefined ContextValue, <ContextProvider/> could be missing', + ); + + return value; +}; + +export default Context; diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx b/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx similarity index 65% rename from plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx rename to plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx index cd3db0eb7b..64698da921 100644 --- a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.stories.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx @@ -18,10 +18,17 @@ import React from 'react'; import { TestApiProvider, wrapInTestApp } from '@backstage/test-utils'; import { ComponentType, PropsWithChildren } from 'react'; import { Grid } from '@material-ui/core'; -import { HomePageRecentlyVisited } from '../../plugin'; +import { HomePageVisitedByType } from '../../plugin'; import { Visit, visitsApiRef } from '../../api/VisitsApi'; const visits: Array<Visit> = [ + { + id: 'tech-radar', + name: 'Tech Radar', + pathname: '/tech-radar', + hits: 40, + timestamp: Date.now() - 360_000, + }, { id: 'explore', name: 'Explore Backstage', @@ -73,17 +80,10 @@ const visits: Array<Visit> = [ id: 'hello-world', name: 'Hello World gRPC', pathname: '/catalog/default/api/hello-world', - hits: 5, + hits: 1, timestamp: Date.now() - 86400_000 * 7, entityRef: 'API:default/hello-world', }, - { - id: 'tech-radar', - name: 'Tech Radar', - pathname: '/tech-radar', - hits: 1, - timestamp: Date.now() - 360_000, - }, ]; const mockVisitsApi = { @@ -92,7 +92,7 @@ const mockVisitsApi = { }; export default { - title: 'Plugins/Home/Components/RecentlyVisited', + title: 'Plugins/Home/Components/VisitedByType', decorators: [ (Story: ComponentType<PropsWithChildren<{}>>) => wrapInTestApp( @@ -103,42 +103,96 @@ export default { ], }; -export const Default = () => { +export const RecentlyDefault = () => { return ( <Grid item xs={12} md={6}> - <HomePageRecentlyVisited /> + <HomePageVisitedByType kind="recent" /> </Grid> ); }; -export const Empty = () => { +export const RecentlyEmpty = () => { return ( <Grid item xs={12} md={6}> - <HomePageRecentlyVisited visits={[]} /> + <HomePageVisitedByType kind="recent" visits={[]} /> </Grid> ); }; -export const FewItems = () => { +export const RecentlyFewItems = () => { return ( <Grid item xs={12} md={6}> - <HomePageRecentlyVisited visits={visits.slice(0, 1)} /> + <HomePageVisitedByType kind="recent" visits={visits.slice(0, 1)} /> </Grid> ); }; -export const MoreItems = () => { +export const RecentlyMoreItems = () => { return ( <Grid item xs={12} md={6}> - <HomePageRecentlyVisited numVisitsOpen={5} numVisitsTotal={6} /> + <HomePageVisitedByType + kind="recent" + numVisitsOpen={5} + numVisitsTotal={6} + /> </Grid> ); }; -export const Loading = () => { +export const RecentlyLoading = () => { return ( <Grid item xs={12} md={6}> - <HomePageRecentlyVisited numVisitsOpen={5} numVisitsTotal={6} loading /> + <HomePageVisitedByType + kind="recent" + numVisitsOpen={5} + numVisitsTotal={6} + loading + /> + </Grid> + ); +}; + +export const TopDefault = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageVisitedByType kind="top" /> + </Grid> + ); +}; + +export const TopEmpty = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageVisitedByType kind="top" visits={[]} /> + </Grid> + ); +}; + +export const TopFewItems = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageVisitedByType kind="top" visits={visits.slice(0, 1)} /> + </Grid> + ); +}; + +export const TopMoreItems = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageVisitedByType kind="top" numVisitsOpen={5} numVisitsTotal={6} /> + </Grid> + ); +}; + +export const TopLoading = () => { + return ( + <Grid item xs={12} md={6}> + <HomePageVisitedByType + kind="top" + numVisitsOpen={5} + numVisitsTotal={6} + loading + /> </Grid> ); }; diff --git a/plugins/home/src/homePageComponents/VisitedByType/VisitedByType.test.tsx b/plugins/home/src/homePageComponents/VisitedByType/VisitedByType.test.tsx new file mode 100644 index 0000000000..9e363f55aa --- /dev/null +++ b/plugins/home/src/homePageComponents/VisitedByType/VisitedByType.test.tsx @@ -0,0 +1,89 @@ +/* + * 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 { VisitedByType } from './VisitedByType'; +import { Context, defaultContextValue } from './Context'; +import { renderInTestApp } from '@backstage/test-utils'; +import { waitFor } from '@testing-library/react'; + +describe('<VisitedByType/> kind="top"', () => { + it('should render', async () => { + const { getByText } = await renderInTestApp( + <Context.Provider value={{ ...defaultContextValue, kind: 'top' }}> + <VisitedByType /> + </Context.Provider>, + ); + expect(getByText('Top Visited')).toBeInTheDocument(); + }); + it('should display hits', async () => { + const { getByText } = await renderInTestApp( + <Context.Provider + value={{ + ...defaultContextValue, + kind: 'top', + loading: false, + visits: [ + { + id: 'tech-radar', + name: 'Tech Radar', + pathname: '/tech-radar', + hits: 40, + timestamp: Date.now() - 360_000, + }, + ], + }} + > + <VisitedByType /> + </Context.Provider>, + ); + await waitFor(() => expect(getByText('40 times')).toBeInTheDocument()); + }); +}); + +describe('<VisitedByType/> kind="recent"', () => { + it('should render', async () => { + const { getByText } = await renderInTestApp( + <Context.Provider value={{ ...defaultContextValue, kind: 'recent' }}> + <VisitedByType /> + </Context.Provider>, + ); + expect(getByText('Recently Visited')).toBeInTheDocument(); + }); + it('should display how long ago a visit happened', async () => { + const { getByText } = await renderInTestApp( + <Context.Provider + value={{ + ...defaultContextValue, + kind: 'recent', + loading: false, + visits: [ + { + id: 'tech-radar', + name: 'Tech Radar', + pathname: '/tech-radar', + hits: 40, + timestamp: Date.now() - 86400_000, + }, + ], + }} + > + <VisitedByType /> + </Context.Provider>, + ); + await waitFor(() => expect(getByText('1 day ago')).toBeInTheDocument()); + }); +}); diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx b/plugins/home/src/homePageComponents/VisitedByType/VisitedByType.tsx similarity index 85% rename from plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx rename to plugins/home/src/homePageComponents/VisitedByType/VisitedByType.tsx index 121d15b1d2..23d7f3fffd 100644 --- a/plugins/home/src/homePageComponents/RecentlyVisited/RecentlyVisited.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/VisitedByType.tsx @@ -17,19 +17,16 @@ import React from 'react'; import { VisitList } from '../../components/VisitList'; import { useContext } from './Context'; -/** - * Display recently visited pages for the homepage - * @public - */ -export const RecentlyVisited = () => { - const { collapsed, numVisitsOpen, numVisitsTotal, visits, loading } = + +export const VisitedByType = () => { + const { collapsed, numVisitsOpen, numVisitsTotal, visits, loading, kind } = useContext(); return ( <VisitList visits={visits} - title="Recently visited" - detailType="time-ago" + title={kind === 'top' ? 'Top Visited' : 'Recently Visited'} + detailType={kind === 'top' ? 'hits' : 'time-ago'} collapsed={collapsed} numVisitsOpen={numVisitsOpen} numVisitsTotal={numVisitsTotal} diff --git a/plugins/home/src/homePageComponents/RecentlyVisited/index.ts b/plugins/home/src/homePageComponents/VisitedByType/index.ts similarity index 90% rename from plugins/home/src/homePageComponents/RecentlyVisited/index.ts rename to plugins/home/src/homePageComponents/VisitedByType/index.ts index 8caf533ab1..f085007522 100644 --- a/plugins/home/src/homePageComponents/RecentlyVisited/index.ts +++ b/plugins/home/src/homePageComponents/VisitedByType/index.ts @@ -17,4 +17,4 @@ export { Content } from './Content'; export { Actions } from './Actions'; export { ContextProvider } from './Context'; -export type { RecentlyVisitedProps } from './Content'; +export type { VisitedByTypeProps, VisitedByTypeKind } from './Content'; diff --git a/plugins/home/src/homePageComponents/index.ts b/plugins/home/src/homePageComponents/index.ts index 026f068d3f..9149afa295 100644 --- a/plugins/home/src/homePageComponents/index.ts +++ b/plugins/home/src/homePageComponents/index.ts @@ -17,4 +17,4 @@ export type { ToolkitContentProps, Tool } from './Toolkit'; export type { ClockConfig } from './HeaderWorldClock'; export type { WelcomeTitleLanguageProps } from './WelcomeTitle'; -export type { RecentlyVisitedProps } from './RecentlyVisited'; +export type { VisitedByTypeProps, VisitedByTypeKind } from './VisitedByType'; diff --git a/plugins/home/src/index.ts b/plugins/home/src/index.ts index e133ad49b5..c60883d749 100644 --- a/plugins/home/src/index.ts +++ b/plugins/home/src/index.ts @@ -32,6 +32,7 @@ export { ComponentTab, WelcomeTitle, HeaderWorldClock, + HomePageVisitedByType, } from './plugin'; export * from './components'; export * from './assets'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index 90ac5c3519..c357562bec 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -20,10 +20,7 @@ import { createRoutableExtension, } from '@backstage/core-plugin-api'; import { createCardExtension } from '@backstage/plugin-home-react'; -import { - ToolkitContentProps, - RecentlyVisitedProps, -} from './homePageComponents'; +import { ToolkitContentProps, VisitedByTypeProps } from './homePageComponents'; import { rootRouteRef } from './routes'; /** @public */ @@ -177,12 +174,12 @@ export const HeaderWorldClock = homePlugin.provide( ); /** - * Display recently visited pages for the homepage + * Display recently/top visited pages for the homepage * @public */ -export const HomePageRecentlyVisited = homePlugin.provide( - createCardExtension<RecentlyVisitedProps>({ - name: 'HomePageRecentlyVisited', - components: () => import('./homePageComponents/RecentlyVisited'), +export const HomePageVisitedByType = homePlugin.provide( + createCardExtension<VisitedByTypeProps>({ + name: 'HomePageVisitedByType', + components: () => import('./homePageComponents/VisitedByType'), }), ); From 6d30b374a07fa910a315c85ad71daddcf1669025 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Fri, 8 Sep 2023 11:07:50 +0200 Subject: [PATCH 154/207] fix(home): Use luxon instead of date-fns Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/package.json | 2 +- .../src/components/VisitList/ItemDetail.tsx | 32 ++++++++++--------- yarn.lock | 4 +-- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/plugins/home/package.json b/plugins/home/package.json index 9a692557b1..f69db9d4ee 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -50,8 +50,8 @@ "@rjsf/utils": "5.13.0", "@rjsf/validator-ajv8": "5.13.0", "@types/react": "^16.13.1 || ^17.0.0", - "date-fns": "^2.30.0", "lodash": "^4.17.21", + "luxon": "^3.4.3", "react-grid-layout": "^1.3.4", "react-resizable": "^3.0.4", "react-use": "^17.2.4", diff --git a/plugins/home/src/components/VisitList/ItemDetail.tsx b/plugins/home/src/components/VisitList/ItemDetail.tsx index 5bdbdc0db4..3f55557f73 100644 --- a/plugins/home/src/components/VisitList/ItemDetail.tsx +++ b/plugins/home/src/components/VisitList/ItemDetail.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { Typography } from '@material-ui/core'; import { Visit } from '../../api/VisitsApi'; -import { format, formatDistance, formatISO, isToday } from 'date-fns'; +import { DateTime } from 'luxon'; const ItemDetailHits = ({ visit }: { visit: Visit }) => ( <Typography component="span" variant="caption" color="textSecondary"> @@ -25,20 +25,22 @@ const ItemDetailHits = ({ visit }: { visit: Visit }) => ( </Typography> ); -const ItemDetailTimeAgo = ({ visit }: { visit: Visit }) => ( - <Typography - component="time" - variant="caption" - color="textSecondary" - dateTime={formatISO(visit.timestamp)} - > - {isToday(visit.timestamp) - ? format(visit.timestamp, 'HH:mm') - : formatDistance(visit.timestamp, Date.now(), { - addSuffix: true, - })} - </Typography> -); +const ItemDetailTimeAgo = ({ visit }: { visit: Visit }) => { + const visitDate = DateTime.fromMillis(visit.timestamp); + + return ( + <Typography + component="time" + variant="caption" + color="textSecondary" + dateTime={visitDate.toISO() ?? undefined} + > + {visitDate >= DateTime.now().startOf('day') + ? visitDate.toFormat('HH:mm') + : visitDate.toRelative()} + </Typography> + ); +}; export type ItemDetailType = 'time-ago' | 'hits'; diff --git a/yarn.lock b/yarn.lock index 65ba1a0ec0..c9aa122ad9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7409,8 +7409,8 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/react-grid-layout": ^1.3.2 - date-fns: ^2.30.0 lodash: ^4.17.21 + luxon: ^3.4.3 msw: ^1.0.0 react-grid-layout: ^1.3.4 react-resizable: ^3.0.4 @@ -31784,7 +31784,7 @@ __metadata: languageName: node linkType: hard -"luxon@npm:^3.0.0, luxon@npm:^3.3.0": +"luxon@npm:^3.0.0, luxon@npm:^3.3.0, luxon@npm:^3.4.3": version: 3.4.3 resolution: "luxon@npm:3.4.3" checksum: 3eade81506224d038ed24035a0cd0dd4887848d7eba9361dce9ad8ef81380596a68153240be3988721f9690c624fb449fcf8fd8c3fc0681a6a8496faf48e92a3 From cac684376ed62dc2864a7a100837df862f7f2957 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Fri, 8 Sep 2023 11:19:47 +0200 Subject: [PATCH 155/207] refactor(home): Change parameters on saveVisit Result of a feedback on: https://github.com/backstage/backstage/pull/19645#discussion_r1313865318 Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 7 ++++++- plugins/home/src/api/VisitsApi.ts | 10 +++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 536032a8eb..8c0177e251 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -225,7 +225,7 @@ export type VisitFilter = { // @public export interface VisitsApi { listUserVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; - saveVisit(pageVisit: Omit<Visit, 'id' | 'hits' | 'timestamp'>): Promise<void>; + saveVisit(saveParams: VisitsApiSaveParams): Promise<void>; } // @public @@ -238,6 +238,11 @@ export type VisitsApiQueryParams = { // @public (undocumented) export const visitsApiRef: ApiRef<VisitsApi>; +// @public +export type VisitsApiSaveParams = { + visit: Omit<Visit, 'id' | 'hits' | 'timestamp'>; +}; + // @public export const WelcomeTitle: ({ language, diff --git a/plugins/home/src/api/VisitsApi.ts b/plugins/home/src/api/VisitsApi.ts index 8d5ae3f8cb..c461a5159b 100644 --- a/plugins/home/src/api/VisitsApi.ts +++ b/plugins/home/src/api/VisitsApi.ts @@ -85,6 +85,14 @@ export type VisitsApiQueryParams = { filterBy?: VisitFilter[]; }; +/** + * @public + * This data structure represents the parameters associated with saving visits. + */ +export type VisitsApiSaveParams = { + visit: Omit<Visit, 'id' | 'hits' | 'timestamp'>; +}; + /** * @public * Visits API public contract. @@ -94,7 +102,7 @@ export interface VisitsApi { * Persist a new visit. * @param pageVisit - a new visit data */ - saveVisit(pageVisit: Omit<Visit, 'id' | 'hits' | 'timestamp'>): Promise<void>; + saveVisit(saveParams: VisitsApiSaveParams): Promise<void>; /** * Get the logged user visits. * @param queryParams - optional search query params. From c0700220c97500b12ab1d65bde2f2abead4281ba Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Thu, 24 Aug 2023 17:56:59 +0200 Subject: [PATCH 156/207] feature(home-plugin): Creates the <VisitListener/> component This patch creates the <VisitListener/> component to be used on the app to register user visits enabling the homepage Recently Visited and Top Visited experience (<VisitedByType/>) to be functional. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 62 +++++- plugins/home/package.json | 1 + plugins/home/src/api/VisitsApi.ts | 36 ++-- .../src/components/VisitListener.test.tsx | 203 ++++++++++++++++++ plugins/home/src/components/VisitListener.tsx | 163 ++++++++++++++ plugins/home/src/components/index.ts | 1 + .../VisitedByType/Content.test.tsx | 2 +- .../VisitedByType/Content.tsx | 4 +- .../HomePageVisitedByType.stories.tsx | 2 +- yarn.lock | 1 + 10 files changed, 447 insertions(+), 28 deletions(-) create mode 100644 plugins/home/src/components/VisitListener.test.tsx create mode 100644 plugins/home/src/components/VisitListener.tsx diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 8c0177e251..acc073f685 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -14,13 +14,15 @@ import { CardSettings as CardSettings_2 } from '@backstage/plugin-home-react'; import { ComponentParts as ComponentParts_2 } from '@backstage/plugin-home-react'; import { ComponentRenderer as ComponentRenderer_2 } from '@backstage/plugin-home-react'; import { createCardExtension as createCardExtension_2 } from '@backstage/plugin-home-react'; -import { JsonValue } from '@backstage/types'; +import { Dispatch } from 'react'; import { JSX as JSX_2 } from 'react'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RendererProps as RendererProps_2 } from '@backstage/plugin-home-react'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SetStateAction } from 'react'; +import { stringifyEntityRef } from '@backstage/catalog-model'; // @public export type Breakpoint = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; @@ -99,6 +101,25 @@ export type CustomHomepageGridProps = { preventCollision?: boolean; }; +// @public +export const DoNotTrack: ({ + children, +}: { + children?: ReactNode; +}) => JSX.Element; + +// @public +export const getToEntityRef: ({ + rootPath, + stringifyEntityRefImpl, +}?: { + rootPath?: string | undefined; + stringifyEntityRefImpl?: typeof stringifyEntityRef | undefined; +}) => ({ pathname }: { pathname: string }) => string | undefined; + +// @public +export const getVisitName: (document: Document) => () => string; + // @public export const HeaderWorldClock: (props: { clockConfigs: ClockConfig[]; @@ -193,6 +214,9 @@ export type ToolkitContentProps = { tools: Tool[]; }; +// @public +export const useVisitListener: () => VisitListenerContextValue; + // @public export type Visit = { id: string; @@ -215,24 +239,46 @@ export type VisitedByTypeProps = { kind: VisitedByTypeKind; }; +// @public +export const VisitListener: ({ + children, + toEntityRef, + visitName, +}: { + children?: React_2.ReactNode; + toEntityRef?: + | (({ pathname }: { pathname: string }) => string | undefined) + | undefined; + visitName?: (({ pathname }: { pathname: string }) => string) | undefined; +}) => JSX.Element; + // @public (undocumented) -export type VisitFilter = { - field: string; - operator: '<' | '<=' | '==' | '>' | '>=' | 'contains'; - value: JsonValue; +export const VisitListenerContext: React_2.Context<VisitListenerContextValue>; + +// @public (undocumented) +export type VisitListenerContextValue = { + doNotTrack: boolean; + setDoNotTrack: Dispatch<SetStateAction<boolean>>; }; // @public export interface VisitsApi { listUserVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; - saveVisit(saveParams: VisitsApiSaveParams): Promise<void>; + saveVisit(saveParams: VisitsApiSaveParams): Promise<Visit>; } // @public export type VisitsApiQueryParams = { limit?: number; - orderBy?: Record<string, 'asc' | 'desc'>; - filterBy?: VisitFilter[]; + orderBy?: Array<{ + field: keyof Visit; + direction: 'asc' | 'desc'; + }>; + filterBy?: Array<{ + field: keyof Visit; + operator: '<' | '<=' | '==' | '>' | '>=' | 'contains'; + value: string | number; + }>; }; // @public (undocumented) diff --git a/plugins/home/package.json b/plugins/home/package.json index f69db9d4ee..6a9c5306c1 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -70,6 +70,7 @@ "@testing-library/dom": "^8.0.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", + "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.0.0", "@types/react-grid-layout": "^1.3.2", "msw": "^1.0.0" diff --git a/plugins/home/src/api/VisitsApi.ts b/plugins/home/src/api/VisitsApi.ts index c461a5159b..4ffb37e8b6 100644 --- a/plugins/home/src/api/VisitsApi.ts +++ b/plugins/home/src/api/VisitsApi.ts @@ -15,7 +15,6 @@ */ import { createApiRef } from '@backstage/core-plugin-api'; -import { JsonValue } from '@backstage/types'; /** * @public @@ -48,13 +47,6 @@ export type Visit = { entityRef?: string; }; -/** @public */ -export type VisitFilter = { - field: string; - operator: '<' | '<=' | '==' | '>' | '>=' | 'contains'; - value: JsonValue; -}; - /** * @public * This data structure represents the parameters associated with search queries for visits. @@ -65,24 +57,36 @@ export type VisitsApiQueryParams = { */ limit?: number; /** - * A record for which the key is a field name to sort on, and the value is the sort direction. - * For a multi-field sorting query, add multi entries to the record. + * Allows ordering visits on entity properties. * @example * Sort ascending by the timestamp field. * ``` - * { orderBy: { timestamp: 'asc' } } + * { orderBy: [{ field: 'timestamp', direction: 'asc' }] } * ``` */ - orderBy?: Record<string, 'asc' | 'desc'>; + orderBy?: Array<{ + field: keyof Visit; + direction: 'asc' | 'desc'; + }>; /** - * Allows filtering visits on number of hits, timestamp and/or entityRef attributes. + * Allows filtering visits on entity properties. * @example * Most popular docs on the past 7 days * ``` - * { orderBy: { hits: 'desc' }, filterBy: [{ field: 'timestamp', operator: '>=', value: <date> }, { field: 'entityRef', operator: 'contains', value: 'docs' }] } + * { + * orderBy: [{ field: 'hits', direction: 'desc' }], + * filterBy: [ + * { field: 'timestamp', operator: '>=', value: <date> }, + * { field: 'entityRef', operator: 'contains', value: 'docs' } + * ] + * } * ``` */ - filterBy?: VisitFilter[]; + filterBy?: Array<{ + field: keyof Visit; + operator: '<' | '<=' | '==' | '>' | '>=' | 'contains'; + value: string | number; + }>; }; /** @@ -102,7 +106,7 @@ export interface VisitsApi { * Persist a new visit. * @param pageVisit - a new visit data */ - saveVisit(saveParams: VisitsApiSaveParams): Promise<void>; + saveVisit(saveParams: VisitsApiSaveParams): Promise<Visit>; /** * Get the logged user visits. * @param queryParams - optional search query params. diff --git a/plugins/home/src/components/VisitListener.test.tsx b/plugins/home/src/components/VisitListener.test.tsx new file mode 100644 index 0000000000..81cff08a09 --- /dev/null +++ b/plugins/home/src/components/VisitListener.test.tsx @@ -0,0 +1,203 @@ +/* + * 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 { TestApiProvider, renderInTestApp } from '@backstage/test-utils'; +import { Visit, visitsApiRef } from '../api'; +import { DoNotTrack, VisitListener, useVisitListener } from './VisitListener'; +import { waitFor } from '@testing-library/react'; +import { act, renderHook } from '@testing-library/react-hooks'; +import { MemoryRouter } from 'react-router-dom'; + +const visits: Array<Visit> = [ + { + id: 'tech-radar', + name: 'Tech Radar', + pathname: '/tech-radar', + hits: 40, + timestamp: Date.now() - 360_000, + }, + { + id: 'explore', + name: 'Explore Backstage', + pathname: '/explore', + hits: 35, + timestamp: Date.now() - 86400_000 * 1, + }, + { + id: 'user-1', + name: 'Guest', + pathname: '/catalog/default/user/guest', + hits: 30, + timestamp: Date.now() - 86400_000 * 2, + entityRef: 'User:default/guest', + }, +]; + +const mockVisitsApi = { + saveVisit: jest.fn(async () => visits[0]), + listVisits: jest.fn(async () => visits), +}; + +describe('<VisitListener/>', () => { + afterEach(jest.resetAllMocks); + + it('registers a visit', async () => { + jest.spyOn(document, 'title', 'get').mockReturnValue('MockedTitle'); + const pathname = '/catalog/default/component/playback-order'; + + await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <VisitListener /> + </TestApiProvider>, + { routeEntries: [pathname] }, + ); + + await waitFor(() => + expect(mockVisitsApi.saveVisit).toHaveBeenCalledTimes(1), + ); + expect(mockVisitsApi.saveVisit).toHaveBeenCalledWith({ + visit: { + pathname, + entityRef: 'component:default/playback-order', + name: 'MockedTitle', + }, + }); + }); + + it('renders its children', async () => { + const { getByTestId } = await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <VisitListener> + <div data-testid="child">child</div> + </VisitListener> + </TestApiProvider>, + ); + + expect(getByTestId('child')).toBeTruthy(); + }); + + it('is able to override how visit names are defined', async () => { + jest.spyOn(document, 'title', 'get').mockReturnValue('MockedTitle'); + const pathname = '/catalog/default/component/playback-order'; + + const visitNameOverride = ({ pathname: path }: { pathname: string }) => + path; + + await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <VisitListener visitName={visitNameOverride} /> + </TestApiProvider>, + { routeEntries: [pathname] }, + ); + + await waitFor(() => + expect(mockVisitsApi.saveVisit).toHaveBeenCalledWith({ + visit: { + pathname, + entityRef: 'component:default/playback-order', + name: pathname, + }, + }), + ); + }); + + it('is able to override how entityRefs are defined', async () => { + jest.spyOn(document, 'title', 'get').mockReturnValue('MockedTitle'); + const pathname = '/catalog/default/component/playback-order'; + + const toEntityRefOverride = ({ pathname: path }: { pathname: string }) => + path; + + await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <VisitListener toEntityRef={toEntityRefOverride} /> + </TestApiProvider>, + { routeEntries: [pathname] }, + ); + + await waitFor(() => + expect(mockVisitsApi.saveVisit).toHaveBeenCalledWith({ + visit: { + pathname, + entityRef: pathname, + name: 'MockedTitle', + }, + }), + ); + }); +}); + +describe('<DoNotTrack/>', () => { + afterEach(jest.resetAllMocks); + + it("doesn't register a visit", async () => { + const requestAnimationFrameSpy = jest.spyOn( + window, + 'requestAnimationFrame', + ); + await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <VisitListener> + <DoNotTrack /> + </VisitListener> + </TestApiProvider>, + ); + await waitFor(() => expect(requestAnimationFrameSpy).toHaveBeenCalled()); + expect(mockVisitsApi.saveVisit).not.toHaveBeenCalled(); + }); + + it('renders its children', async () => { + const requestAnimationFrameSpy = jest.spyOn( + window, + 'requestAnimationFrame', + ); + const { getByTestId } = await renderInTestApp( + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <VisitListener> + <DoNotTrack> + <div data-testid="child">child</div> + </DoNotTrack> + </VisitListener> + </TestApiProvider>, + ); + await waitFor(() => expect(requestAnimationFrameSpy).toHaveBeenCalled()); + expect(getByTestId('child')).toBeTruthy(); + }); +}); + +describe('useVisitListener()', () => { + it('returns the default context', () => { + const { result } = renderHook(() => useVisitListener()); + expect(result.current.doNotTrack).toBeFalsy(); + expect(result.current.setDoNotTrack).toBeInstanceOf(Function); + }); + + it('changes the doNotTrack flag', () => { + const { result } = renderHook(() => useVisitListener(), { + wrapper: ({ children }) => ( + <MemoryRouter> + <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> + <VisitListener>{children}</VisitListener> + </TestApiProvider> + </MemoryRouter> + ), + }); + act(() => { + result.current.setDoNotTrack(true); + }); + expect(result.current.doNotTrack).toBeTruthy(); + }); +}); diff --git a/plugins/home/src/components/VisitListener.tsx b/plugins/home/src/components/VisitListener.tsx new file mode 100644 index 0000000000..cb92b47738 --- /dev/null +++ b/plugins/home/src/components/VisitListener.tsx @@ -0,0 +1,163 @@ +/* + * 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, { + createContext, + useState, + useEffect, + useContext, + Dispatch, + SetStateAction, + ReactNode, +} from 'react'; + +import { useLocation } from 'react-router-dom'; + +import { visitsApiRef } from '../api'; +import { useApi } from '@backstage/core-plugin-api'; +import { stringifyEntityRef } from '@backstage/catalog-model'; + +/** @public */ +export type VisitListenerContextValue = { + doNotTrack: boolean; + setDoNotTrack: Dispatch<SetStateAction<boolean>>; +}; + +const defaultVisitListenerContext: VisitListenerContextValue = { + doNotTrack: false, + setDoNotTrack: () => {}, +}; + +/** @public */ +export const VisitListenerContext = createContext<VisitListenerContextValue>( + defaultVisitListenerContext, +); + +/** + * @public + * This function returns an implementation of toEntityRef which is responsible + * for receiving a pathname and maybe returning an entityRef compatible with the + * catalog-model. + * By default this function uses the url root "/catalog" and the + * stringifyEntityRef implementation from catalog-model. + * Example: + * const toEntityRef = getToEntityRef(); + * toEntityRef(\{ pathname: "/catalog/default/component/playback-order" \}) + * // returns "component:default/playback-order" + */ +export const getToEntityRef = + ({ + rootPath = 'catalog', + stringifyEntityRefImpl = stringifyEntityRef, + } = {}) => + ({ pathname }: { pathname: string }): string | undefined => { + const regex = new RegExp( + `^\/${rootPath}\/(?<namespace>[^\/]+)\/(?<kind>[^\/]+)\/(?<name>[^\/]+)`, + ); + const result = regex.exec(pathname); + if (!result || !result?.groups) return undefined; + const entity = { + namespace: result.groups.namespace, + kind: result.groups.kind, + name: result.groups.name, + }; + return stringifyEntityRefImpl(entity); + }; + +/** + * @public + * This function returns an implementation of visitName which is responsible + * for receiving a pathname and returning a string (name). The default + * implementation ignores the pathname and uses the document.title . + */ +export const getVisitName = (document: Document) => () => document.title; + +/** + * @public + * Component responsible for listening to location changes and calling + * the visitsApi to save visits. + */ +export const VisitListener = ({ + children, + toEntityRef, + visitName, +}: { + children?: React.ReactNode; + toEntityRef?: ({ pathname }: { pathname: string }) => string | undefined; + visitName?: ({ pathname }: { pathname: string }) => string; +}): JSX.Element => { + const [doNotTrack, setDoNotTrack] = useState<boolean>( + defaultVisitListenerContext.doNotTrack, + ); + const visitsApi = useApi(visitsApiRef); + const { pathname } = useLocation(); + const toEntityRefImpl = toEntityRef ?? getToEntityRef(); + const visitNameImpl = visitName ?? getVisitName(document); + useEffect(() => { + // Wait for the browser to finish with paint with the assumption react + // has finished with dom reconciliation and the doNotTrack state update. + const requestId = requestAnimationFrame(() => { + if (!doNotTrack) + visitsApi.saveVisit({ + visit: { + name: visitNameImpl({ pathname }), + pathname, + entityRef: toEntityRefImpl({ pathname }), + }, + }); + }); + return () => cancelAnimationFrame(requestId); + }, [doNotTrack, visitsApi, pathname, toEntityRefImpl, visitNameImpl]); + + return ( + <VisitListenerContext.Provider value={{ doNotTrack, setDoNotTrack }}> + {children} + </VisitListenerContext.Provider> + ); +}; + +/** + * @public + * Hook used to access visit listener context. Is able to control if tracking + * should be disabled. + */ +export const useVisitListener = () => { + const value = useContext(VisitListenerContext); + + if (value === undefined) + throw new Error( + 'useVisitListener found an undefined context, <VisitListener/> could be missing', + ); + + return value; +}; + +/** + * @public + * Use this component to warn VisitListener to disable tracking. + */ +export const DoNotTrack = ({ + children, +}: { + children?: ReactNode; +}): JSX.Element => { + const { setDoNotTrack } = useVisitListener(); + useEffect(() => { + setDoNotTrack(true); + return () => setDoNotTrack(false); + }, [setDoNotTrack]); + + return <>{children}</>; +}; diff --git a/plugins/home/src/components/index.ts b/plugins/home/src/components/index.ts index e528e0795d..a6a4148e36 100644 --- a/plugins/home/src/components/index.ts +++ b/plugins/home/src/components/index.ts @@ -16,3 +16,4 @@ export { HomepageCompositionRoot } from './HomepageCompositionRoot'; export * from './CustomHomepage'; +export * from './VisitListener'; diff --git a/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx b/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx index 329bf4e845..d73a9d1a75 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx @@ -32,7 +32,7 @@ const visits = [ ]; const mockVisitsApi = { - saveVisit: async () => {}, + saveVisit: async () => visits[0], listUserVisits: async () => visits, }; diff --git a/plugins/home/src/homePageComponents/VisitedByType/Content.tsx b/plugins/home/src/homePageComponents/VisitedByType/Content.tsx index 62b0de0d7d..4eef2a87ad 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/Content.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/Content.tsx @@ -67,7 +67,7 @@ export const Content = ({ return await visitsApi .listUserVisits({ limit: numVisitsTotal ?? 8, - orderBy: { timestamp: 'desc' }, + orderBy: [{ field: 'timestamp', direction: 'desc' }], }) .then(setVisits); } @@ -75,7 +75,7 @@ export const Content = ({ return await visitsApi .listUserVisits({ limit: numVisitsTotal ?? 8, - orderBy: { hits: 'desc' }, + orderBy: [{ field: 'hits', direction: 'desc' }], }) .then(setVisits); } diff --git a/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx b/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx index 64698da921..0dd9c9e873 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx @@ -87,7 +87,7 @@ const visits: Array<Visit> = [ ]; const mockVisitsApi = { - saveVisit: async () => {}, + saveVisit: async () => visits[0], listUserVisits: async () => visits, }; diff --git a/yarn.lock b/yarn.lock index c9aa122ad9..2fdd9e041f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7406,6 +7406,7 @@ __metadata: "@testing-library/dom": ^8.0.0 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 + "@testing-library/react-hooks": ^8.0.1 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/react-grid-layout": ^1.3.2 From 09a7f8f285e45bedbac4af2064c3d631882e21b3 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Tue, 19 Sep 2023 11:19:46 +0200 Subject: [PATCH 157/207] refactoring(plugins/home): Don't export getToEntityRef Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> Co-authored-by: Camila Belo <camilaibs@gmail.com> --- plugins/home/api-report.md | 10 ---------- plugins/home/src/components/VisitListener.tsx | 3 +-- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index acc073f685..7f96f24240 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -22,7 +22,6 @@ import { ReactNode } from 'react'; import { RendererProps as RendererProps_2 } from '@backstage/plugin-home-react'; import { RouteRef } from '@backstage/core-plugin-api'; import { SetStateAction } from 'react'; -import { stringifyEntityRef } from '@backstage/catalog-model'; // @public export type Breakpoint = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; @@ -108,15 +107,6 @@ export const DoNotTrack: ({ children?: ReactNode; }) => JSX.Element; -// @public -export const getToEntityRef: ({ - rootPath, - stringifyEntityRefImpl, -}?: { - rootPath?: string | undefined; - stringifyEntityRefImpl?: typeof stringifyEntityRef | undefined; -}) => ({ pathname }: { pathname: string }) => string | undefined; - // @public export const getVisitName: (document: Document) => () => string; diff --git a/plugins/home/src/components/VisitListener.tsx b/plugins/home/src/components/VisitListener.tsx index cb92b47738..c564301525 100644 --- a/plugins/home/src/components/VisitListener.tsx +++ b/plugins/home/src/components/VisitListener.tsx @@ -46,7 +46,6 @@ export const VisitListenerContext = createContext<VisitListenerContextValue>( ); /** - * @public * This function returns an implementation of toEntityRef which is responsible * for receiving a pathname and maybe returning an entityRef compatible with the * catalog-model. @@ -57,7 +56,7 @@ export const VisitListenerContext = createContext<VisitListenerContextValue>( * toEntityRef(\{ pathname: "/catalog/default/component/playback-order" \}) * // returns "component:default/playback-order" */ -export const getToEntityRef = +const getToEntityRef = ({ rootPath = 'catalog', stringifyEntityRefImpl = stringifyEntityRef, From a84cac67caf447244c1645fea6a67c08f92d41f9 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Tue, 19 Sep 2023 11:30:22 +0200 Subject: [PATCH 158/207] feature(plugins/home): Remove DoNotTrack functionality Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> --- plugins/home/api-report.md | 21 ----- .../src/components/VisitListener.test.tsx | 66 +------------- plugins/home/src/components/VisitListener.tsx | 86 +++---------------- 3 files changed, 11 insertions(+), 162 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 7f96f24240..a3c56dd7dd 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -14,14 +14,12 @@ import { CardSettings as CardSettings_2 } from '@backstage/plugin-home-react'; import { ComponentParts as ComponentParts_2 } from '@backstage/plugin-home-react'; import { ComponentRenderer as ComponentRenderer_2 } from '@backstage/plugin-home-react'; import { createCardExtension as createCardExtension_2 } from '@backstage/plugin-home-react'; -import { Dispatch } from 'react'; import { JSX as JSX_2 } from 'react'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RendererProps as RendererProps_2 } from '@backstage/plugin-home-react'; import { RouteRef } from '@backstage/core-plugin-api'; -import { SetStateAction } from 'react'; // @public export type Breakpoint = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; @@ -100,13 +98,6 @@ export type CustomHomepageGridProps = { preventCollision?: boolean; }; -// @public -export const DoNotTrack: ({ - children, -}: { - children?: ReactNode; -}) => JSX.Element; - // @public export const getVisitName: (document: Document) => () => string; @@ -204,9 +195,6 @@ export type ToolkitContentProps = { tools: Tool[]; }; -// @public -export const useVisitListener: () => VisitListenerContextValue; - // @public export type Visit = { id: string; @@ -242,15 +230,6 @@ export const VisitListener: ({ visitName?: (({ pathname }: { pathname: string }) => string) | undefined; }) => JSX.Element; -// @public (undocumented) -export const VisitListenerContext: React_2.Context<VisitListenerContextValue>; - -// @public (undocumented) -export type VisitListenerContextValue = { - doNotTrack: boolean; - setDoNotTrack: Dispatch<SetStateAction<boolean>>; -}; - // @public export interface VisitsApi { listUserVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; diff --git a/plugins/home/src/components/VisitListener.test.tsx b/plugins/home/src/components/VisitListener.test.tsx index 81cff08a09..81587b4067 100644 --- a/plugins/home/src/components/VisitListener.test.tsx +++ b/plugins/home/src/components/VisitListener.test.tsx @@ -16,10 +16,8 @@ import React from 'react'; import { TestApiProvider, renderInTestApp } from '@backstage/test-utils'; import { Visit, visitsApiRef } from '../api'; -import { DoNotTrack, VisitListener, useVisitListener } from './VisitListener'; +import { VisitListener } from './VisitListener'; import { waitFor } from '@testing-library/react'; -import { act, renderHook } from '@testing-library/react-hooks'; -import { MemoryRouter } from 'react-router-dom'; const visits: Array<Visit> = [ { @@ -139,65 +137,3 @@ describe('<VisitListener/>', () => { ); }); }); - -describe('<DoNotTrack/>', () => { - afterEach(jest.resetAllMocks); - - it("doesn't register a visit", async () => { - const requestAnimationFrameSpy = jest.spyOn( - window, - 'requestAnimationFrame', - ); - await renderInTestApp( - <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> - <VisitListener> - <DoNotTrack /> - </VisitListener> - </TestApiProvider>, - ); - await waitFor(() => expect(requestAnimationFrameSpy).toHaveBeenCalled()); - expect(mockVisitsApi.saveVisit).not.toHaveBeenCalled(); - }); - - it('renders its children', async () => { - const requestAnimationFrameSpy = jest.spyOn( - window, - 'requestAnimationFrame', - ); - const { getByTestId } = await renderInTestApp( - <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> - <VisitListener> - <DoNotTrack> - <div data-testid="child">child</div> - </DoNotTrack> - </VisitListener> - </TestApiProvider>, - ); - await waitFor(() => expect(requestAnimationFrameSpy).toHaveBeenCalled()); - expect(getByTestId('child')).toBeTruthy(); - }); -}); - -describe('useVisitListener()', () => { - it('returns the default context', () => { - const { result } = renderHook(() => useVisitListener()); - expect(result.current.doNotTrack).toBeFalsy(); - expect(result.current.setDoNotTrack).toBeInstanceOf(Function); - }); - - it('changes the doNotTrack flag', () => { - const { result } = renderHook(() => useVisitListener(), { - wrapper: ({ children }) => ( - <MemoryRouter> - <TestApiProvider apis={[[visitsApiRef, mockVisitsApi]]}> - <VisitListener>{children}</VisitListener> - </TestApiProvider> - </MemoryRouter> - ), - }); - act(() => { - result.current.setDoNotTrack(true); - }); - expect(result.current.doNotTrack).toBeTruthy(); - }); -}); diff --git a/plugins/home/src/components/VisitListener.tsx b/plugins/home/src/components/VisitListener.tsx index c564301525..c0cf34bdc9 100644 --- a/plugins/home/src/components/VisitListener.tsx +++ b/plugins/home/src/components/VisitListener.tsx @@ -13,15 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { - createContext, - useState, - useEffect, - useContext, - Dispatch, - SetStateAction, - ReactNode, -} from 'react'; +import React, { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; @@ -29,22 +21,6 @@ import { visitsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import { stringifyEntityRef } from '@backstage/catalog-model'; -/** @public */ -export type VisitListenerContextValue = { - doNotTrack: boolean; - setDoNotTrack: Dispatch<SetStateAction<boolean>>; -}; - -const defaultVisitListenerContext: VisitListenerContextValue = { - doNotTrack: false, - setDoNotTrack: () => {}, -}; - -/** @public */ -export const VisitListenerContext = createContext<VisitListenerContextValue>( - defaultVisitListenerContext, -); - /** * This function returns an implementation of toEntityRef which is responsible * for receiving a pathname and maybe returning an entityRef compatible with the @@ -97,66 +73,24 @@ export const VisitListener = ({ toEntityRef?: ({ pathname }: { pathname: string }) => string | undefined; visitName?: ({ pathname }: { pathname: string }) => string; }): JSX.Element => { - const [doNotTrack, setDoNotTrack] = useState<boolean>( - defaultVisitListenerContext.doNotTrack, - ); const visitsApi = useApi(visitsApiRef); const { pathname } = useLocation(); const toEntityRefImpl = toEntityRef ?? getToEntityRef(); const visitNameImpl = visitName ?? getVisitName(document); useEffect(() => { // Wait for the browser to finish with paint with the assumption react - // has finished with dom reconciliation and the doNotTrack state update. + // has finished with dom reconciliation. const requestId = requestAnimationFrame(() => { - if (!doNotTrack) - visitsApi.saveVisit({ - visit: { - name: visitNameImpl({ pathname }), - pathname, - entityRef: toEntityRefImpl({ pathname }), - }, - }); + visitsApi.saveVisit({ + visit: { + name: visitNameImpl({ pathname }), + pathname, + entityRef: toEntityRefImpl({ pathname }), + }, + }); }); return () => cancelAnimationFrame(requestId); - }, [doNotTrack, visitsApi, pathname, toEntityRefImpl, visitNameImpl]); - - return ( - <VisitListenerContext.Provider value={{ doNotTrack, setDoNotTrack }}> - {children} - </VisitListenerContext.Provider> - ); -}; - -/** - * @public - * Hook used to access visit listener context. Is able to control if tracking - * should be disabled. - */ -export const useVisitListener = () => { - const value = useContext(VisitListenerContext); - - if (value === undefined) - throw new Error( - 'useVisitListener found an undefined context, <VisitListener/> could be missing', - ); - - return value; -}; - -/** - * @public - * Use this component to warn VisitListener to disable tracking. - */ -export const DoNotTrack = ({ - children, -}: { - children?: ReactNode; -}): JSX.Element => { - const { setDoNotTrack } = useVisitListener(); - useEffect(() => { - setDoNotTrack(true); - return () => setDoNotTrack(false); - }, [setDoNotTrack]); + }, [visitsApi, pathname, toEntityRefImpl, visitNameImpl]); return <>{children}</>; }; From 5d671e622021a2484d93e6bd6754dc7088dce0ab Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Tue, 29 Aug 2023 13:45:54 +0200 Subject: [PATCH 159/207] feature(home-plugin): Create reference implementation (localStorage) This is a reference implementation using local storage. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 42 ++- .../src/api/LocalStorageVisitsApi.test.ts | 66 ++++ plugins/home/src/api/LocalStorageVisitsApi.ts | 54 +++ plugins/home/src/api/VisitsApi.ts | 4 +- plugins/home/src/api/VisitsApiFactory.test.ts | 325 ++++++++++++++++++ plugins/home/src/api/VisitsApiFactory.ts | 119 +++++++ plugins/home/src/api/index.ts | 2 + .../VisitedByType/Content.tsx | 4 +- 8 files changed, 611 insertions(+), 5 deletions(-) create mode 100644 plugins/home/src/api/LocalStorageVisitsApi.test.ts create mode 100644 plugins/home/src/api/LocalStorageVisitsApi.ts create mode 100644 plugins/home/src/api/VisitsApiFactory.test.ts create mode 100644 plugins/home/src/api/VisitsApiFactory.ts diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index a3c56dd7dd..56fa3ef281 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -161,6 +161,19 @@ export type LayoutConfiguration = { resizable?: boolean; }; +// @public +export class LocalStorageVisitsApi extends VisitsApiFactory { + constructor({ + localStorage, + randomUUID, + limit, + }?: { + localStorage?: Window['localStorage']; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + }); +} + // @public @deprecated (undocumented) export type RendererProps = RendererProps_2; @@ -232,7 +245,34 @@ export const VisitListener: ({ // @public export interface VisitsApi { - listUserVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; + listVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; + saveVisit(saveParams: VisitsApiSaveParams): Promise<Visit>; +} + +// @public +export class VisitsApiFactory implements VisitsApi { + constructor({ + randomUUID, + limit, + retrieveAll, + persistAll, + }: { + randomUUID: Window['crypto']['randomUUID']; + limit: number; + retrieveAll?: () => Promise<Array<Visit>>; + persistAll?: (visits: Array<Visit>) => Promise<void>; + }); + // (undocumented) + protected readonly limit: number; + // (undocumented) + listVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; + // (undocumented) + protected persistAll: (visits: Array<Visit>) => Promise<void>; + // (undocumented) + protected readonly randomUUID: Window['crypto']['randomUUID']; + // (undocumented) + protected retrieveAll: () => Promise<Array<Visit>>; + // (undocumented) saveVisit(saveParams: VisitsApiSaveParams): Promise<Visit>; } diff --git a/plugins/home/src/api/LocalStorageVisitsApi.test.ts b/plugins/home/src/api/LocalStorageVisitsApi.test.ts new file mode 100644 index 0000000000..8cf94e6c25 --- /dev/null +++ b/plugins/home/src/api/LocalStorageVisitsApi.test.ts @@ -0,0 +1,66 @@ +/* + * 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 { LocalStorageVisitsApi } from './LocalStorageVisitsApi'; + +describe('new LocalStorageVisitsApi()', () => { + const mockRandomUUID = () => + '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( + /x/g, + () => Math.floor(Math.random() * 16).toString(16), // 0x0 to 0xf + ) as `${string}-${string}-${string}-${string}-${string}`; + + beforeEach(() => { + window.crypto.randomUUID = mockRandomUUID; + }); + + afterEach(() => { + window.localStorage.clear(); + }); + + it('instantiates with no configuration', () => { + const api = new LocalStorageVisitsApi(); + expect(api).toBeTruthy(); + }); + + it('saves a visit', async () => { + const api = new LocalStorageVisitsApi(); + const visit = { + pathname: '/catalog/default/component/playback-order', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + const returnedVisit = await api.saveVisit({ visit }); + expect(returnedVisit).toEqual(expect.objectContaining(visit)); + expect(returnedVisit.id).toBeTruthy(); + expect(returnedVisit.timestamp).toBeTruthy(); + expect(returnedVisit.hits).toBeTruthy(); + }); + + it('retrieves visits', async () => { + const api = new LocalStorageVisitsApi(); + const visit = { + pathname: '/catalog/default/component/playback-order', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + const returnedVisit = await api.saveVisit({ visit }); + const visits = await api.listVisits(); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visit)]); + expect(visits).toEqual([returnedVisit]); + }); +}); diff --git a/plugins/home/src/api/LocalStorageVisitsApi.ts b/plugins/home/src/api/LocalStorageVisitsApi.ts new file mode 100644 index 0000000000..5999930e3a --- /dev/null +++ b/plugins/home/src/api/LocalStorageVisitsApi.ts @@ -0,0 +1,54 @@ +/* + * 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 { Visit } from './VisitsApi'; +import { VisitsApiFactory } from './VisitsApiFactory'; + +/** + * @public + * This is a reference implementation of VisitsApi using window.localStorage. + */ +export class LocalStorageVisitsApi extends VisitsApiFactory { + private readonly localStorage: Window['localStorage']; + private readonly storageKey = '@backstage/plugin-home:visits'; + + constructor({ + localStorage = window?.localStorage, + randomUUID = window?.crypto?.randomUUID, + limit = 100, + }: { + localStorage?: Window['localStorage']; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + } = {}) { + super({ randomUUID, limit }); + this.localStorage = localStorage; + this.retrieveAll = async (): Promise<Array<Visit>> => { + let visits: Array<Visit>; + try { + visits = JSON.parse(this.localStorage.getItem(this.storageKey) ?? '[]'); + } catch { + visits = []; + } + return visits; + }; + this.persistAll = async (visits: Array<Visit>) => { + this.localStorage.setItem( + this.storageKey, + JSON.stringify(visits.splice(0, this.limit)), + ); + }; + } +} diff --git a/plugins/home/src/api/VisitsApi.ts b/plugins/home/src/api/VisitsApi.ts index 4ffb37e8b6..ab53ea7f10 100644 --- a/plugins/home/src/api/VisitsApi.ts +++ b/plugins/home/src/api/VisitsApi.ts @@ -108,10 +108,10 @@ export interface VisitsApi { */ saveVisit(saveParams: VisitsApiSaveParams): Promise<Visit>; /** - * Get the logged user visits. + * Get user visits. * @param queryParams - optional search query params. */ - listUserVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; + listVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; } /** @public */ diff --git a/plugins/home/src/api/VisitsApiFactory.test.ts b/plugins/home/src/api/VisitsApiFactory.test.ts new file mode 100644 index 0000000000..3281c320b7 --- /dev/null +++ b/plugins/home/src/api/VisitsApiFactory.test.ts @@ -0,0 +1,325 @@ +/* + * 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 { Visit } from './VisitsApi'; +import { VisitsApiFactory } from './VisitsApiFactory'; + +class MemoryVisitsApi extends VisitsApiFactory { + private visits: Array<Visit> = []; + + constructor({ + randomUUID = window?.crypto?.randomUUID, + limit = 100, + }: { + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + } = {}) { + super({ randomUUID, limit }); + this.retrieveAll = async (): Promise<Array<Visit>> => { + let visits: Array<Visit>; + try { + visits = this.visits; + } catch { + visits = []; + } + return visits; + }; + this.persistAll = async (visits: Array<Visit>) => { + this.visits = visits; + }; + } +} + +describe('new MemoryVisitsApi()', () => { + const mockRandomUUID = () => + '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( + /x/g, + () => Math.floor(Math.random() * 16).toString(16), // 0x0 to 0xf + ) as `${string}-${string}-${string}-${string}-${string}`; + + beforeEach(() => { + jest.useFakeTimers(); + window.crypto.randomUUID = mockRandomUUID; + }); + + afterEach(() => { + jest.resetAllMocks(); + jest.useRealTimers(); + window.localStorage.clear(); + }); + + it('instantiates with no configuration', () => { + const api = new MemoryVisitsApi(); + expect(api).toBeTruthy(); + }); + + describe('.saveVisit()', () => { + it('saves a visit', async () => { + const api = new MemoryVisitsApi(); + const visit = { + pathname: '/catalog/default/component/playback-order', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + const returnedVisit = await api.saveVisit({ visit }); + expect(returnedVisit).toEqual(expect.objectContaining(visit)); + expect(returnedVisit.id).toBeTruthy(); + expect(returnedVisit.timestamp).toBeTruthy(); + expect(returnedVisit.hits).toBeTruthy(); + }); + + it('can control the number of stored entities', async () => { + const api = new MemoryVisitsApi({ limit: 2 }); + const baseDate = Date.now(); + const visit1 = { + pathname: '/catalog/default/component/playback-order-1', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + jest.setSystemTime(baseDate); + await api.saveVisit({ visit: visit1 }); + const visit2 = { + pathname: '/catalog/default/component/playback-order-2', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + jest.setSystemTime(baseDate + 360_000); + await api.saveVisit({ visit: visit2 }); + const visit3 = { + pathname: '/catalog/default/component/playback-order-3', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + jest.setSystemTime(baseDate + 360_000 * 2); + await api.saveVisit({ visit: visit3 }); + const visits = await api.listVisits(); + expect(visits).toHaveLength(2); + expect(visits).toContainEqual(expect.objectContaining(visit2)); + expect(visits).toContainEqual(expect.objectContaining(visit3)); + }); + + it('correctly bumps the hits from a previous visit', async () => { + const api = new MemoryVisitsApi(); + const visit = { + pathname: '/catalog/default/component/playback-order', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + const visit1 = await api.saveVisit({ visit }); + const visit2 = await api.saveVisit({ visit }); + const visits = await api.listVisits(); + expect(visits).toHaveLength(1); + expect(visits).toContainEqual(expect.objectContaining(visit)); + // keeps the original id created on the first visit + expect(visits).toContainEqual(expect.objectContaining({ id: visit1.id })); + // updates timestamp and hits + expect(visits).toContainEqual( + expect.objectContaining({ timestamp: visit2.timestamp, hits: 2 }), + ); + }); + }); + + describe('.listVisits()', () => { + let api: MemoryVisitsApi; + let visitsToSave: Array<Omit<Visit, 'id' | 'hits' | 'timestamp'>>; + let baseDate: number; + beforeEach(() => { + api = new MemoryVisitsApi(); + visitsToSave = [ + { + pathname: '/catalog/default/component/playback-order-1', + entityRef: 'component:default/playback-order-1', + name: 'Playback Order Odd', + }, + { + pathname: '/catalog/default/component/playback-order-2', + entityRef: 'component:default/playback-order-2', + name: 'Playback Order Even', + }, + { + pathname: '/catalog/default/component/playback-order-3', + entityRef: 'component:default/playback-order-3', + name: 'Playback Order Odd', + }, + ]; + baseDate = Date.now(); + // Chaining items to ensure the right setSystemTime + return visitsToSave.reduce( + (acc, visit, index) => + acc.then(() => { + jest.setSystemTime(baseDate + 360_000 * index); + return api.saveVisit({ visit }); + }), + Promise.resolve({}), + ); + }); + + it('retrieves visits', async () => { + const visits = await api.listVisits(); + expect(visits).toHaveLength(3); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + + it('orders by timestamp asc', async () => { + const visits = await api.listVisits({ + orderBy: [{ field: 'timestamp', direction: 'asc' }], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[0]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[2]), + ]); + }); + + it('orders by timestamp desc', async () => { + const visits = await api.listVisits({ + orderBy: [{ field: 'timestamp', direction: 'desc' }], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + + it('orders by entityRef asc', async () => { + const visits = await api.listVisits({ + orderBy: [{ field: 'entityRef', direction: 'asc' }], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[0]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[2]), + ]); + }); + + it('orders by entityRef desc', async () => { + const visits = await api.listVisits({ + orderBy: [{ field: 'entityRef', direction: 'desc' }], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + + it('orders by name asc then by entityRef asc', async () => { + const visits = await api.listVisits({ + orderBy: [ + { field: 'name', direction: 'asc' }, + { field: 'entityRef', direction: 'asc' }, + ], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[1]), // Playback Order Even, playback-order-2 + expect.objectContaining(visitsToSave[0]), // Playback Order Odd, playback-order-1 + expect.objectContaining(visitsToSave[2]), // Playback Order Odd, playback-order-3 + ]); + }); + + it('orders by name desc then by entityRef asc', async () => { + const visits = await api.listVisits({ + orderBy: [ + { field: 'name', direction: 'desc' }, + { field: 'entityRef', direction: 'asc' }, + ], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[0]), // Playback Order Odd, playback-order-1 + expect.objectContaining(visitsToSave[2]), // Playback Order Odd, playback-order-3 + expect.objectContaining(visitsToSave[1]), // Playback Order Even, playback-order-2 + ]); + }); + + it('filters by timestamp with >', async () => { + const visits = await api.listVisits({ + filterBy: [{ field: 'timestamp', operator: '>', value: baseDate }], + }); + expect(visits).toHaveLength(2); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[1]), + ]); + }); + + it('filters by timestamp with >=', async () => { + const visits = await api.listVisits({ + filterBy: [ + { field: 'timestamp', operator: '>=', value: baseDate + 360_000 * 2 }, + ], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[2])]); + }); + + it('filters by timestamp with <', async () => { + const visits = await api.listVisits({ + filterBy: [{ field: 'timestamp', operator: '<', value: baseDate + 1 }], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[0])]); + }); + + it('filters by timestamp with <=', async () => { + const visits = await api.listVisits({ + filterBy: [ + { field: 'timestamp', operator: '<=', value: baseDate + 360_000 }, + ], + }); + expect(visits).toHaveLength(2); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + + it('filters by timestamp with ==', async () => { + const visits = await api.listVisits({ + filterBy: [ + { field: 'timestamp', operator: '==', value: baseDate + 360_000 }, + ], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[1])]); + }); + + it('filters by entityRef with contains', async () => { + const visits = await api.listVisits({ + filterBy: [ + { field: 'entityRef', operator: 'contains', value: 'order-2' }, + ], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[1])]); + }); + + it('filters by timestamp with <= then by name with contains', async () => { + const visits = await api.listVisits({ + filterBy: [ + { field: 'timestamp', operator: '<=', value: baseDate + 360_000 }, + { field: 'name', operator: 'contains', value: 'Odd' }, + ], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[0])]); + }); + }); +}); diff --git a/plugins/home/src/api/VisitsApiFactory.ts b/plugins/home/src/api/VisitsApiFactory.ts new file mode 100644 index 0000000000..ba3fe1fe3e --- /dev/null +++ b/plugins/home/src/api/VisitsApiFactory.ts @@ -0,0 +1,119 @@ +/* + * 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 { Visit, VisitsApi, VisitsApiQueryParams, VisitsApiSaveParams } from './VisitsApi'; + +type ArrayElement<A> = A extends readonly (infer T)[] ? T : never; + +/** + * @public + * This helps the creation of VisitApi implementations. Important to note + * that it implements features like orderBy and filterBy on memory, therefore + * is intended to handle few visits. The default is 100. + * See LocalStorageVisitsApi for an usage example. + */ +export class VisitsApiFactory implements VisitsApi { + protected readonly randomUUID: Window['crypto']['randomUUID']; + protected readonly limit: number; + protected retrieveAll: () => Promise<Array<Visit>>; + protected persistAll: (visits: Array<Visit>) => Promise<void>; + + constructor({ + randomUUID = window?.crypto?.randomUUID, + limit = 100, + retrieveAll, + persistAll, + }: { + randomUUID: Window['crypto']['randomUUID']; + limit: number; + retrieveAll?: () => Promise<Array<Visit>>; + persistAll?: (visits: Array<Visit>) => Promise<void>; + }) { + this.randomUUID = randomUUID; + this.limit = Math.abs(limit); + this.retrieveAll = retrieveAll ?? (async () => []); + this.persistAll = persistAll ?? (async () => {}); + } + + async listVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]> { + let visits = await this.retrieveAll(); + + // reversing order to guarantee orderBy priority + (queryParams?.orderBy ?? []).reverse().forEach(order => { + if (order.direction === 'asc') { + visits.sort((a, b) => this.compare(order, a, b)); + } else { + visits.sort((a, b) => this.compare(order, b, a)); + } + }); + + (queryParams?.filterBy ?? []).reverse().forEach(filter => { + visits = visits.filter(visit => { + const field = visit[filter.field] as number | string; + if (filter.operator === '>') return field > filter.value; + if (filter.operator === '>=') return field >= filter.value; + if (filter.operator === '<') return field < filter.value; + if (filter.operator === '<=') return field <= filter.value; + if (filter.operator === '==') return field === filter.value; + if (filter.operator === 'contains') + return `${field}`.includes(`${filter.value}`); + return false; + }); + }); + + return visits; + } + + async saveVisit( + saveParams: VisitsApiSaveParams, + ): Promise<Visit> { + const visits = await this.retrieveAll(); + + const visit: Visit = { + ...saveParams.visit, + id: this.randomUUID(), + hits: 1, + timestamp: Date.now(), + }; + + // Updates entry if pathname is already registered + const visitIndex = visits.findIndex(e => e.pathname === visit.pathname); + if (visitIndex >= 0) { + visit.id = visits[visitIndex].id; + visit.hits = visits[visitIndex].hits + 1; + visits[visitIndex] = visit; + } else { + visits.push(visit); + } + + // Sort by time, most recent first + visits.sort((a, b) => b.timestamp - a.timestamp); + // Keep the most recent items up to limit + await this.persistAll(visits.splice(0, this.limit)); + return visit; + } + + // This assumes Visit fields are either numbers or strings + private compare( + order: ArrayElement<VisitsApiQueryParams['orderBy']>, + a: Visit, + b: Visit, + ): number { + const isNumber = typeof a[order.field] === 'number'; + return isNumber + ? (a[order.field] as number) - (b[order.field] as number) + : `${a[order.field]}`.localeCompare(`${b[order.field]}`); + } +} diff --git a/plugins/home/src/api/index.ts b/plugins/home/src/api/index.ts index 29a8fb5468..b90a14299c 100644 --- a/plugins/home/src/api/index.ts +++ b/plugins/home/src/api/index.ts @@ -15,3 +15,5 @@ */ export * from './VisitsApi'; +export * from './LocalStorageVisitsApi'; +export * from './VisitsApiFactory'; diff --git a/plugins/home/src/homePageComponents/VisitedByType/Content.tsx b/plugins/home/src/homePageComponents/VisitedByType/Content.tsx index 4eef2a87ad..8f492a2099 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/Content.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/Content.tsx @@ -65,7 +65,7 @@ export const Content = ({ const { loading: reqLoading } = useAsync(async () => { if (!visits && !loading && kind === 'recent') { return await visitsApi - .listUserVisits({ + .listVisits({ limit: numVisitsTotal ?? 8, orderBy: [{ field: 'timestamp', direction: 'desc' }], }) @@ -73,7 +73,7 @@ export const Content = ({ } if (!visits && !loading && kind === 'top') { return await visitsApi - .listUserVisits({ + .listVisits({ limit: numVisitsTotal ?? 8, orderBy: [{ field: 'hits', direction: 'desc' }], }) From c4854690988f1e23d7deabd44570f8db28bf936e Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Tue, 29 Aug 2023 17:34:52 +0200 Subject: [PATCH 160/207] feature(home-plugin): VisitApi implementation backed by StorageApi Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 14 ++++ .../home/src/api/CoreStorageVisitsApi.test.ts | 73 +++++++++++++++++++ plugins/home/src/api/CoreStorageVisitsApi.ts | 52 +++++++++++++ plugins/home/src/api/index.ts | 3 +- .../VisitedByType/Content.test.tsx | 2 +- 5 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 plugins/home/src/api/CoreStorageVisitsApi.test.ts create mode 100644 plugins/home/src/api/CoreStorageVisitsApi.ts diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 56fa3ef281..3352a291bc 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -20,6 +20,7 @@ import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RendererProps as RendererProps_2 } from '@backstage/plugin-home-react'; import { RouteRef } from '@backstage/core-plugin-api'; +import { StorageApi } from '@backstage/core-plugin-api'; // @public export type Breakpoint = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; @@ -74,6 +75,19 @@ export const ComponentTabs: (props: { }[]; }) => JSX_2.Element; +// @public +export class CoreStorageVisitsApi extends VisitsApiFactory { + constructor({ + storageApi, + randomUUID, + limit, + }: { + storageApi: StorageApi; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + }); +} + // @public @deprecated (undocumented) export const createCardExtension: typeof createCardExtension_2; diff --git a/plugins/home/src/api/CoreStorageVisitsApi.test.ts b/plugins/home/src/api/CoreStorageVisitsApi.test.ts new file mode 100644 index 0000000000..9185ece2c6 --- /dev/null +++ b/plugins/home/src/api/CoreStorageVisitsApi.test.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 { CoreStorageVisitsApi } from './CoreStorageVisitsApi'; +import { MockStorageApi } from '@backstage/test-utils'; + +describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () => { + const mockRandomUUID = () => + '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( + /x/g, + () => Math.floor(Math.random() * 16).toString(16), // 0x0 to 0xf + ) as `${string}-${string}-${string}-${string}-${string}`; + + beforeEach(() => { + window.crypto.randomUUID = mockRandomUUID; + }); + + afterEach(() => { + window.localStorage.clear(); + }); + + it('instantiates with no configuration', () => { + const api = new CoreStorageVisitsApi({ + storageApi: MockStorageApi.create(), + }); + expect(api).toBeTruthy(); + }); + + it('saves a visit', async () => { + const api = new CoreStorageVisitsApi({ + storageApi: MockStorageApi.create(), + }); + const visit = { + pathname: '/catalog/default/component/playback-order', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + const returnedVisit = await api.saveVisit({ visit }); + expect(returnedVisit).toEqual(expect.objectContaining(visit)); + expect(returnedVisit.id).toBeTruthy(); + expect(returnedVisit.timestamp).toBeTruthy(); + expect(returnedVisit.hits).toBeTruthy(); + }); + + it('retrieves visits', async () => { + const api = new CoreStorageVisitsApi({ + storageApi: MockStorageApi.create(), + }); + const visit = { + pathname: '/catalog/default/component/playback-order', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + const returnedVisit = await api.saveVisit({ visit }); + const visits = await api.listVisits(); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visit)]); + expect(visits).toEqual([returnedVisit]); + }); +}); diff --git a/plugins/home/src/api/CoreStorageVisitsApi.ts b/plugins/home/src/api/CoreStorageVisitsApi.ts new file mode 100644 index 0000000000..8b54fcc416 --- /dev/null +++ b/plugins/home/src/api/CoreStorageVisitsApi.ts @@ -0,0 +1,52 @@ +/* + * 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 { StorageApi } from '@backstage/core-plugin-api'; +import { Visit } from './VisitsApi'; +import { VisitsApiFactory } from './VisitsApiFactory'; + +/** + * @public + * This is an implementation of VisitsApi that relies on a StorageApi + */ +export class CoreStorageVisitsApi extends VisitsApiFactory { + private readonly storageApi: StorageApi; + private readonly storageKey = '@backstage/plugin-home:visits'; + + constructor({ + storageApi, + randomUUID = window?.crypto?.randomUUID, + limit = 100, + }: { + storageApi: StorageApi; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + }) { + super({ randomUUID, limit }); + this.storageApi = storageApi; + this.retrieveAll = async (): Promise<Array<Visit>> => { + let visits: Array<Visit>; + try { + visits = + this.storageApi.snapshot<Array<Visit>>(this.storageKey).value ?? []; + } catch { + visits = []; + } + return visits; + }; + this.persistAll = async (visits: Array<Visit>) => + this.storageApi.set<Array<Visit>>(this.storageKey, visits); + } +} diff --git a/plugins/home/src/api/index.ts b/plugins/home/src/api/index.ts index b90a14299c..cb283aa2cf 100644 --- a/plugins/home/src/api/index.ts +++ b/plugins/home/src/api/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ -export * from './VisitsApi'; +export * from './CoreStorageVisitsApi'; export * from './LocalStorageVisitsApi'; +export * from './VisitsApi'; export * from './VisitsApiFactory'; diff --git a/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx b/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx index d73a9d1a75..a9ff2cdd7c 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx @@ -33,7 +33,7 @@ const visits = [ const mockVisitsApi = { saveVisit: async () => visits[0], - listUserVisits: async () => visits, + listVisits: async () => visits, }; describe('<Content kind="recent"/>', () => { From 6cfcf8a4a759fad3b1775f8002eeadc65c675f47 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Wed, 30 Aug 2023 10:26:16 +0200 Subject: [PATCH 161/207] feature(home-plugin): Adds user scope to storage calls This patch adds the userEntityRef to the storage key ensuring they are scoped per user. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 7 +++++- .../home/src/api/CoreStorageVisitsApi.test.ts | 14 +++++++++++- plugins/home/src/api/CoreStorageVisitsApi.ts | 22 ++++++++++++++----- .../src/api/LocalStorageVisitsApi.test.ts | 18 +++++++++++---- plugins/home/src/api/LocalStorageVisitsApi.ts | 21 +++++++++++++----- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 3352a291bc..9eddb81da5 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -14,6 +14,7 @@ import { CardSettings as CardSettings_2 } from '@backstage/plugin-home-react'; import { ComponentParts as ComponentParts_2 } from '@backstage/plugin-home-react'; import { ComponentRenderer as ComponentRenderer_2 } from '@backstage/plugin-home-react'; import { createCardExtension as createCardExtension_2 } from '@backstage/plugin-home-react'; +import { IdentityApi } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; @@ -79,12 +80,14 @@ export const ComponentTabs: (props: { export class CoreStorageVisitsApi extends VisitsApiFactory { constructor({ storageApi, + identityApi, randomUUID, limit, }: { storageApi: StorageApi; randomUUID?: Window['crypto']['randomUUID']; limit?: number; + identityApi: IdentityApi; }); } @@ -181,10 +184,12 @@ export class LocalStorageVisitsApi extends VisitsApiFactory { localStorage, randomUUID, limit, - }?: { + identityApi, + }: { localStorage?: Window['localStorage']; randomUUID?: Window['crypto']['randomUUID']; limit?: number; + identityApi: IdentityApi; }); } diff --git a/plugins/home/src/api/CoreStorageVisitsApi.test.ts b/plugins/home/src/api/CoreStorageVisitsApi.test.ts index 9185ece2c6..e14f71ad60 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.test.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { BackstageUserIdentity, IdentityApi } from '@backstage/core-plugin-api'; import { CoreStorageVisitsApi } from './CoreStorageVisitsApi'; import { MockStorageApi } from '@backstage/test-utils'; @@ -24,6 +25,14 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () () => Math.floor(Math.random() * 16).toString(16), // 0x0 to 0xf ) as `${string}-${string}-${string}-${string}-${string}`; + const mockIdentityApi: IdentityApi = { + signOut: jest.fn(), + getProfileInfo: jest.fn(), + getBackstageIdentity: async () => + ({ userEntityRef: 'user:default/guest' } as BackstageUserIdentity), + getCredentials: jest.fn(), + }; + beforeEach(() => { window.crypto.randomUUID = mockRandomUUID; }); @@ -32,9 +41,10 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () window.localStorage.clear(); }); - it('instantiates with no configuration', () => { + it('instantiates', () => { const api = new CoreStorageVisitsApi({ storageApi: MockStorageApi.create(), + identityApi: mockIdentityApi, }); expect(api).toBeTruthy(); }); @@ -42,6 +52,7 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () it('saves a visit', async () => { const api = new CoreStorageVisitsApi({ storageApi: MockStorageApi.create(), + identityApi: mockIdentityApi, }); const visit = { pathname: '/catalog/default/component/playback-order', @@ -58,6 +69,7 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () it('retrieves visits', async () => { const api = new CoreStorageVisitsApi({ storageApi: MockStorageApi.create(), + identityApi: mockIdentityApi, }); const visit = { pathname: '/catalog/default/component/playback-order', diff --git a/plugins/home/src/api/CoreStorageVisitsApi.ts b/plugins/home/src/api/CoreStorageVisitsApi.ts index 8b54fcc416..ae7fac14e1 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { StorageApi } from '@backstage/core-plugin-api'; +import { IdentityApi, StorageApi } from '@backstage/core-plugin-api'; import { Visit } from './VisitsApi'; import { VisitsApiFactory } from './VisitsApiFactory'; @@ -23,30 +23,40 @@ import { VisitsApiFactory } from './VisitsApiFactory'; */ export class CoreStorageVisitsApi extends VisitsApiFactory { private readonly storageApi: StorageApi; - private readonly storageKey = '@backstage/plugin-home:visits'; + private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; + private readonly identityApi: IdentityApi; constructor({ storageApi, + identityApi, randomUUID = window?.crypto?.randomUUID, limit = 100, }: { storageApi: StorageApi; randomUUID?: Window['crypto']['randomUUID']; limit?: number; + identityApi: IdentityApi; }) { super({ randomUUID, limit }); this.storageApi = storageApi; + this.identityApi = identityApi; this.retrieveAll = async (): Promise<Array<Visit>> => { let visits: Array<Visit>; + const { userEntityRef } = await this.identityApi.getBackstageIdentity(); + const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; + try { - visits = - this.storageApi.snapshot<Array<Visit>>(this.storageKey).value ?? []; + visits = this.storageApi.snapshot<Array<Visit>>(storageKey).value ?? []; } catch { visits = []; } return visits; }; - this.persistAll = async (visits: Array<Visit>) => - this.storageApi.set<Array<Visit>>(this.storageKey, visits); + this.persistAll = async (visits: Array<Visit>) => { + const { userEntityRef } = await this.identityApi.getBackstageIdentity(); + const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; + + return this.storageApi.set<Array<Visit>>(storageKey, visits); + }; } } diff --git a/plugins/home/src/api/LocalStorageVisitsApi.test.ts b/plugins/home/src/api/LocalStorageVisitsApi.test.ts index 8cf94e6c25..4e2e3f9c7a 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.test.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { BackstageUserIdentity, IdentityApi } from '@backstage/core-plugin-api'; import { LocalStorageVisitsApi } from './LocalStorageVisitsApi'; describe('new LocalStorageVisitsApi()', () => { @@ -23,21 +24,30 @@ describe('new LocalStorageVisitsApi()', () => { () => Math.floor(Math.random() * 16).toString(16), // 0x0 to 0xf ) as `${string}-${string}-${string}-${string}-${string}`; + const mockIdentityApi: IdentityApi = { + signOut: jest.fn(), + getProfileInfo: jest.fn(), + getBackstageIdentity: async () => + ({ userEntityRef: 'user:default/guest' } as BackstageUserIdentity), + getCredentials: jest.fn(), + }; + beforeEach(() => { window.crypto.randomUUID = mockRandomUUID; }); afterEach(() => { window.localStorage.clear(); + jest.resetAllMocks(); }); - it('instantiates with no configuration', () => { - const api = new LocalStorageVisitsApi(); + it('instantiates with only identitiyApi', () => { + const api = new LocalStorageVisitsApi({ identityApi: mockIdentityApi }); expect(api).toBeTruthy(); }); it('saves a visit', async () => { - const api = new LocalStorageVisitsApi(); + const api = new LocalStorageVisitsApi({ identityApi: mockIdentityApi }); const visit = { pathname: '/catalog/default/component/playback-order', entityRef: 'component:default/playback-order', @@ -51,7 +61,7 @@ describe('new LocalStorageVisitsApi()', () => { }); it('retrieves visits', async () => { - const api = new LocalStorageVisitsApi(); + const api = new LocalStorageVisitsApi({ identityApi: mockIdentityApi }); const visit = { pathname: '/catalog/default/component/playback-order', entityRef: 'component:default/playback-order', diff --git a/plugins/home/src/api/LocalStorageVisitsApi.ts b/plugins/home/src/api/LocalStorageVisitsApi.ts index 5999930e3a..21a8e5cb6f 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { IdentityApi } from '@backstage/core-plugin-api'; import { Visit } from './VisitsApi'; import { VisitsApiFactory } from './VisitsApiFactory'; @@ -22,31 +23,41 @@ import { VisitsApiFactory } from './VisitsApiFactory'; */ export class LocalStorageVisitsApi extends VisitsApiFactory { private readonly localStorage: Window['localStorage']; - private readonly storageKey = '@backstage/plugin-home:visits'; + private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; + private readonly identityApi: IdentityApi; constructor({ localStorage = window?.localStorage, randomUUID = window?.crypto?.randomUUID, limit = 100, + identityApi, }: { localStorage?: Window['localStorage']; randomUUID?: Window['crypto']['randomUUID']; limit?: number; - } = {}) { + identityApi: IdentityApi; + }) { super({ randomUUID, limit }); this.localStorage = localStorage; + this.identityApi = identityApi; this.retrieveAll = async (): Promise<Array<Visit>> => { let visits: Array<Visit>; + const { userEntityRef } = await this.identityApi.getBackstageIdentity(); + const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; + try { - visits = JSON.parse(this.localStorage.getItem(this.storageKey) ?? '[]'); + visits = JSON.parse(this.localStorage.getItem(storageKey) ?? '[]'); } catch { visits = []; } return visits; }; this.persistAll = async (visits: Array<Visit>) => { - this.localStorage.setItem( - this.storageKey, + const { userEntityRef } = await this.identityApi.getBackstageIdentity(); + const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; + + return this.localStorage.setItem( + storageKey, JSON.stringify(visits.splice(0, this.limit)), ); }; From b53d3537ddd30362ec9dc8ff298eedbb9aea14b0 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Wed, 30 Aug 2023 17:23:31 +0200 Subject: [PATCH 162/207] feature(home-plugin): Use static methods on Api classes Confirming with the style guide: 7.Keep constructors private, prefer static factory methods for creating instances. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 59 ++++++++++--------- .../home/src/api/CoreStorageVisitsApi.test.ts | 8 +-- plugins/home/src/api/CoreStorageVisitsApi.ts | 21 ++++--- .../src/api/LocalStorageVisitsApi.test.ts | 8 +-- plugins/home/src/api/LocalStorageVisitsApi.ts | 21 ++++--- plugins/home/src/api/VisitsApiFactory.ts | 18 +++--- 6 files changed, 77 insertions(+), 58 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 9eddb81da5..2dc1aca8e2 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -78,19 +78,18 @@ export const ComponentTabs: (props: { // @public export class CoreStorageVisitsApi extends VisitsApiFactory { - constructor({ - storageApi, - identityApi, - randomUUID, - limit, - }: { - storageApi: StorageApi; - randomUUID?: Window['crypto']['randomUUID']; - limit?: number; - identityApi: IdentityApi; - }); + // (undocumented) + static create(options: CoreStorageVisitsApiOptions): CoreStorageVisitsApi; } +// @public (undocumented) +export type CoreStorageVisitsApiOptions = { + storageApi: StorageApi; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + identityApi: IdentityApi; +}; + // @public @deprecated (undocumented) export const createCardExtension: typeof createCardExtension_2; @@ -180,19 +179,18 @@ export type LayoutConfiguration = { // @public export class LocalStorageVisitsApi extends VisitsApiFactory { - constructor({ - localStorage, - randomUUID, - limit, - identityApi, - }: { - localStorage?: Window['localStorage']; - randomUUID?: Window['crypto']['randomUUID']; - limit?: number; - identityApi: IdentityApi; - }); + // (undocumented) + static create(options: LocalStorageVisitsApiOptions): LocalStorageVisitsApi; } +// @public (undocumented) +export type LocalStorageVisitsApiOptions = { + localStorage?: Window['localStorage']; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + identityApi: IdentityApi; +}; + // @public @deprecated (undocumented) export type RendererProps = RendererProps_2; @@ -270,17 +268,12 @@ export interface VisitsApi { // @public export class VisitsApiFactory implements VisitsApi { - constructor({ + protected constructor({ randomUUID, limit, retrieveAll, persistAll, - }: { - randomUUID: Window['crypto']['randomUUID']; - limit: number; - retrieveAll?: () => Promise<Array<Visit>>; - persistAll?: (visits: Array<Visit>) => Promise<void>; - }); + }: VisitsApiFactoryOptions); // (undocumented) protected readonly limit: number; // (undocumented) @@ -295,6 +288,14 @@ export class VisitsApiFactory implements VisitsApi { saveVisit(saveParams: VisitsApiSaveParams): Promise<Visit>; } +// @public (undocumented) +export type VisitsApiFactoryOptions = { + randomUUID: Window['crypto']['randomUUID']; + limit: number; + retrieveAll?: () => Promise<Array<Visit>>; + persistAll?: (visits: Array<Visit>) => Promise<void>; +}; + // @public export type VisitsApiQueryParams = { limit?: number; diff --git a/plugins/home/src/api/CoreStorageVisitsApi.test.ts b/plugins/home/src/api/CoreStorageVisitsApi.test.ts index e14f71ad60..ab5d66c495 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.test.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.test.ts @@ -18,7 +18,7 @@ import { BackstageUserIdentity, IdentityApi } from '@backstage/core-plugin-api'; import { CoreStorageVisitsApi } from './CoreStorageVisitsApi'; import { MockStorageApi } from '@backstage/test-utils'; -describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () => { +describe('CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create() })', () => { const mockRandomUUID = () => '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( /x/g, @@ -42,7 +42,7 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () }); it('instantiates', () => { - const api = new CoreStorageVisitsApi({ + const api = CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); @@ -50,7 +50,7 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () }); it('saves a visit', async () => { - const api = new CoreStorageVisitsApi({ + const api = CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); @@ -67,7 +67,7 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () }); it('retrieves visits', async () => { - const api = new CoreStorageVisitsApi({ + const api = CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); diff --git a/plugins/home/src/api/CoreStorageVisitsApi.ts b/plugins/home/src/api/CoreStorageVisitsApi.ts index ae7fac14e1..c4b70eff88 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.ts @@ -17,6 +17,14 @@ import { IdentityApi, StorageApi } from '@backstage/core-plugin-api'; import { Visit } from './VisitsApi'; import { VisitsApiFactory } from './VisitsApiFactory'; +/** @public */ +export type CoreStorageVisitsApiOptions = { + storageApi: StorageApi; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + identityApi: IdentityApi; +}; + /** * @public * This is an implementation of VisitsApi that relies on a StorageApi @@ -26,17 +34,16 @@ export class CoreStorageVisitsApi extends VisitsApiFactory { private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; private readonly identityApi: IdentityApi; - constructor({ + static create(options: CoreStorageVisitsApiOptions) { + return new CoreStorageVisitsApi(options); + } + + private constructor({ storageApi, identityApi, randomUUID = window?.crypto?.randomUUID, limit = 100, - }: { - storageApi: StorageApi; - randomUUID?: Window['crypto']['randomUUID']; - limit?: number; - identityApi: IdentityApi; - }) { + }: CoreStorageVisitsApiOptions) { super({ randomUUID, limit }); this.storageApi = storageApi; this.identityApi = identityApi; diff --git a/plugins/home/src/api/LocalStorageVisitsApi.test.ts b/plugins/home/src/api/LocalStorageVisitsApi.test.ts index 4e2e3f9c7a..c17fa3cfb8 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.test.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.test.ts @@ -17,7 +17,7 @@ import { BackstageUserIdentity, IdentityApi } from '@backstage/core-plugin-api'; import { LocalStorageVisitsApi } from './LocalStorageVisitsApi'; -describe('new LocalStorageVisitsApi()', () => { +describe('LocalStorageVisitsApi.create()', () => { const mockRandomUUID = () => '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( /x/g, @@ -42,12 +42,12 @@ describe('new LocalStorageVisitsApi()', () => { }); it('instantiates with only identitiyApi', () => { - const api = new LocalStorageVisitsApi({ identityApi: mockIdentityApi }); + const api = LocalStorageVisitsApi.create({ identityApi: mockIdentityApi }); expect(api).toBeTruthy(); }); it('saves a visit', async () => { - const api = new LocalStorageVisitsApi({ identityApi: mockIdentityApi }); + const api = LocalStorageVisitsApi.create({ identityApi: mockIdentityApi }); const visit = { pathname: '/catalog/default/component/playback-order', entityRef: 'component:default/playback-order', @@ -61,7 +61,7 @@ describe('new LocalStorageVisitsApi()', () => { }); it('retrieves visits', async () => { - const api = new LocalStorageVisitsApi({ identityApi: mockIdentityApi }); + const api = LocalStorageVisitsApi.create({ identityApi: mockIdentityApi }); const visit = { pathname: '/catalog/default/component/playback-order', entityRef: 'component:default/playback-order', diff --git a/plugins/home/src/api/LocalStorageVisitsApi.ts b/plugins/home/src/api/LocalStorageVisitsApi.ts index 21a8e5cb6f..31cd30dc21 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.ts @@ -17,6 +17,14 @@ import { IdentityApi } from '@backstage/core-plugin-api'; import { Visit } from './VisitsApi'; import { VisitsApiFactory } from './VisitsApiFactory'; +/** @public */ +export type LocalStorageVisitsApiOptions = { + localStorage?: Window['localStorage']; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + identityApi: IdentityApi; +}; + /** * @public * This is a reference implementation of VisitsApi using window.localStorage. @@ -26,17 +34,16 @@ export class LocalStorageVisitsApi extends VisitsApiFactory { private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; private readonly identityApi: IdentityApi; - constructor({ + static create(options: LocalStorageVisitsApiOptions) { + return new LocalStorageVisitsApi(options); + } + + private constructor({ localStorage = window?.localStorage, randomUUID = window?.crypto?.randomUUID, limit = 100, identityApi, - }: { - localStorage?: Window['localStorage']; - randomUUID?: Window['crypto']['randomUUID']; - limit?: number; - identityApi: IdentityApi; - }) { + }: LocalStorageVisitsApiOptions) { super({ randomUUID, limit }); this.localStorage = localStorage; this.identityApi = identityApi; diff --git a/plugins/home/src/api/VisitsApiFactory.ts b/plugins/home/src/api/VisitsApiFactory.ts index ba3fe1fe3e..1b04c775a0 100644 --- a/plugins/home/src/api/VisitsApiFactory.ts +++ b/plugins/home/src/api/VisitsApiFactory.ts @@ -17,6 +17,14 @@ import { Visit, VisitsApi, VisitsApiQueryParams, VisitsApiSaveParams } from './V type ArrayElement<A> = A extends readonly (infer T)[] ? T : never; +/** @public */ +export type VisitsApiFactoryOptions = { + randomUUID: Window['crypto']['randomUUID']; + limit: number; + retrieveAll?: () => Promise<Array<Visit>>; + persistAll?: (visits: Array<Visit>) => Promise<void>; +}; + /** * @public * This helps the creation of VisitApi implementations. Important to note @@ -30,17 +38,12 @@ export class VisitsApiFactory implements VisitsApi { protected retrieveAll: () => Promise<Array<Visit>>; protected persistAll: (visits: Array<Visit>) => Promise<void>; - constructor({ + protected constructor({ randomUUID = window?.crypto?.randomUUID, limit = 100, retrieveAll, persistAll, - }: { - randomUUID: Window['crypto']['randomUUID']; - limit: number; - retrieveAll?: () => Promise<Array<Visit>>; - persistAll?: (visits: Array<Visit>) => Promise<void>; - }) { + }: VisitsApiFactoryOptions) { this.randomUUID = randomUUID; this.limit = Math.abs(limit); this.retrieveAll = retrieveAll ?? (async () => []); @@ -59,6 +62,7 @@ export class VisitsApiFactory implements VisitsApi { } }); + // reversing order to guarantee filterBy priority (queryParams?.filterBy ?? []).reverse().forEach(filter => { visits = visits.filter(visit => { const field = visit[filter.field] as number | string; From c30e715a2bfe3326c6be72577963271d56848f04 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Thu, 31 Aug 2023 10:17:35 +0200 Subject: [PATCH 163/207] feature(home-plugin): Add default implementation to plugin.ts Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/src/plugin.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index c357562bec..3bbfd9d544 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -15,17 +15,32 @@ */ import { + createApiFactory, createComponentExtension, createPlugin, createRoutableExtension, + identityApiRef, + storageApiRef, } from '@backstage/core-plugin-api'; import { createCardExtension } from '@backstage/plugin-home-react'; import { ToolkitContentProps, VisitedByTypeProps } from './homePageComponents'; import { rootRouteRef } from './routes'; +import { CoreStorageVisitsApi, visitsApiRef } from './api'; /** @public */ export const homePlugin = createPlugin({ id: 'home', + apis: [ + createApiFactory({ + api: visitsApiRef, + deps: { + storageApi: storageApiRef, + identityApi: identityApiRef, + }, + factory: ({ storageApi, identityApi }) => + CoreStorageVisitsApi.create({ storageApi, identityApi }), + }), + ], routes: { root: rootRouteRef, }, From 6c93a6799e1befc7221b54a2dff1a0dc58d6c903 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Fri, 8 Sep 2023 13:31:12 +0200 Subject: [PATCH 164/207] refactor(plugins/home): Simplify VisitsApi method names Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 8 +-- .../home/src/api/CoreStorageVisitsApi.test.ts | 6 +-- .../src/api/LocalStorageVisitsApi.test.ts | 6 +-- plugins/home/src/api/VisitsApi.ts | 4 +- plugins/home/src/api/VisitsApiFactory.test.ts | 50 +++++++++---------- plugins/home/src/api/VisitsApiFactory.ts | 13 +++-- .../src/components/VisitListener.test.tsx | 14 +++--- plugins/home/src/components/VisitListener.tsx | 2 +- .../VisitedByType/Content.test.tsx | 4 +- .../VisitedByType/Content.tsx | 4 +- .../HomePageVisitedByType.stories.tsx | 4 +- 11 files changed, 58 insertions(+), 57 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 2dc1aca8e2..a71916d8b3 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -262,8 +262,8 @@ export const VisitListener: ({ // @public export interface VisitsApi { - listVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; - saveVisit(saveParams: VisitsApiSaveParams): Promise<Visit>; + list(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; + save(saveParams: VisitsApiSaveParams): Promise<Visit>; } // @public @@ -277,7 +277,7 @@ export class VisitsApiFactory implements VisitsApi { // (undocumented) protected readonly limit: number; // (undocumented) - listVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; + list(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; // (undocumented) protected persistAll: (visits: Array<Visit>) => Promise<void>; // (undocumented) @@ -285,7 +285,7 @@ export class VisitsApiFactory implements VisitsApi { // (undocumented) protected retrieveAll: () => Promise<Array<Visit>>; // (undocumented) - saveVisit(saveParams: VisitsApiSaveParams): Promise<Visit>; + save(saveParams: VisitsApiSaveParams): Promise<Visit>; } // @public (undocumented) diff --git a/plugins/home/src/api/CoreStorageVisitsApi.test.ts b/plugins/home/src/api/CoreStorageVisitsApi.test.ts index ab5d66c495..e1f39d8464 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.test.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.test.ts @@ -59,7 +59,7 @@ describe('CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create() })', entityRef: 'component:default/playback-order', name: 'Playback Order', }; - const returnedVisit = await api.saveVisit({ visit }); + const returnedVisit = await api.save({ visit }); expect(returnedVisit).toEqual(expect.objectContaining(visit)); expect(returnedVisit.id).toBeTruthy(); expect(returnedVisit.timestamp).toBeTruthy(); @@ -76,8 +76,8 @@ describe('CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create() })', entityRef: 'component:default/playback-order', name: 'Playback Order', }; - const returnedVisit = await api.saveVisit({ visit }); - const visits = await api.listVisits(); + const returnedVisit = await api.save({ visit }); + const visits = await api.list(); expect(visits).toHaveLength(1); expect(visits).toEqual([expect.objectContaining(visit)]); expect(visits).toEqual([returnedVisit]); diff --git a/plugins/home/src/api/LocalStorageVisitsApi.test.ts b/plugins/home/src/api/LocalStorageVisitsApi.test.ts index c17fa3cfb8..eb19859055 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.test.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.test.ts @@ -53,7 +53,7 @@ describe('LocalStorageVisitsApi.create()', () => { entityRef: 'component:default/playback-order', name: 'Playback Order', }; - const returnedVisit = await api.saveVisit({ visit }); + const returnedVisit = await api.save({ visit }); expect(returnedVisit).toEqual(expect.objectContaining(visit)); expect(returnedVisit.id).toBeTruthy(); expect(returnedVisit.timestamp).toBeTruthy(); @@ -67,8 +67,8 @@ describe('LocalStorageVisitsApi.create()', () => { entityRef: 'component:default/playback-order', name: 'Playback Order', }; - const returnedVisit = await api.saveVisit({ visit }); - const visits = await api.listVisits(); + const returnedVisit = await api.save({ visit }); + const visits = await api.list(); expect(visits).toHaveLength(1); expect(visits).toEqual([expect.objectContaining(visit)]); expect(visits).toEqual([returnedVisit]); diff --git a/plugins/home/src/api/VisitsApi.ts b/plugins/home/src/api/VisitsApi.ts index ab53ea7f10..ab43d1c7a7 100644 --- a/plugins/home/src/api/VisitsApi.ts +++ b/plugins/home/src/api/VisitsApi.ts @@ -106,12 +106,12 @@ export interface VisitsApi { * Persist a new visit. * @param pageVisit - a new visit data */ - saveVisit(saveParams: VisitsApiSaveParams): Promise<Visit>; + save(saveParams: VisitsApiSaveParams): Promise<Visit>; /** * Get user visits. * @param queryParams - optional search query params. */ - listVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; + list(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; } /** @public */ diff --git a/plugins/home/src/api/VisitsApiFactory.test.ts b/plugins/home/src/api/VisitsApiFactory.test.ts index 3281c320b7..8c19a8e6a5 100644 --- a/plugins/home/src/api/VisitsApiFactory.test.ts +++ b/plugins/home/src/api/VisitsApiFactory.test.ts @@ -66,7 +66,7 @@ describe('new MemoryVisitsApi()', () => { expect(api).toBeTruthy(); }); - describe('.saveVisit()', () => { + describe('.save()', () => { it('saves a visit', async () => { const api = new MemoryVisitsApi(); const visit = { @@ -74,7 +74,7 @@ describe('new MemoryVisitsApi()', () => { entityRef: 'component:default/playback-order', name: 'Playback Order', }; - const returnedVisit = await api.saveVisit({ visit }); + const returnedVisit = await api.save({ visit }); expect(returnedVisit).toEqual(expect.objectContaining(visit)); expect(returnedVisit.id).toBeTruthy(); expect(returnedVisit.timestamp).toBeTruthy(); @@ -90,22 +90,22 @@ describe('new MemoryVisitsApi()', () => { name: 'Playback Order', }; jest.setSystemTime(baseDate); - await api.saveVisit({ visit: visit1 }); + await api.save({ visit: visit1 }); const visit2 = { pathname: '/catalog/default/component/playback-order-2', entityRef: 'component:default/playback-order', name: 'Playback Order', }; jest.setSystemTime(baseDate + 360_000); - await api.saveVisit({ visit: visit2 }); + await api.save({ visit: visit2 }); const visit3 = { pathname: '/catalog/default/component/playback-order-3', entityRef: 'component:default/playback-order', name: 'Playback Order', }; jest.setSystemTime(baseDate + 360_000 * 2); - await api.saveVisit({ visit: visit3 }); - const visits = await api.listVisits(); + await api.save({ visit: visit3 }); + const visits = await api.list(); expect(visits).toHaveLength(2); expect(visits).toContainEqual(expect.objectContaining(visit2)); expect(visits).toContainEqual(expect.objectContaining(visit3)); @@ -118,9 +118,9 @@ describe('new MemoryVisitsApi()', () => { entityRef: 'component:default/playback-order', name: 'Playback Order', }; - const visit1 = await api.saveVisit({ visit }); - const visit2 = await api.saveVisit({ visit }); - const visits = await api.listVisits(); + const visit1 = await api.save({ visit }); + const visit2 = await api.save({ visit }); + const visits = await api.list(); expect(visits).toHaveLength(1); expect(visits).toContainEqual(expect.objectContaining(visit)); // keeps the original id created on the first visit @@ -132,7 +132,7 @@ describe('new MemoryVisitsApi()', () => { }); }); - describe('.listVisits()', () => { + describe('.list()', () => { let api: MemoryVisitsApi; let visitsToSave: Array<Omit<Visit, 'id' | 'hits' | 'timestamp'>>; let baseDate: number; @@ -161,14 +161,14 @@ describe('new MemoryVisitsApi()', () => { (acc, visit, index) => acc.then(() => { jest.setSystemTime(baseDate + 360_000 * index); - return api.saveVisit({ visit }); + return api.save({ visit }); }), Promise.resolve({}), ); }); it('retrieves visits', async () => { - const visits = await api.listVisits(); + const visits = await api.list(); expect(visits).toHaveLength(3); expect(visits).toEqual([ expect.objectContaining(visitsToSave[2]), @@ -178,7 +178,7 @@ describe('new MemoryVisitsApi()', () => { }); it('orders by timestamp asc', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ orderBy: [{ field: 'timestamp', direction: 'asc' }], }); expect(visits).toEqual([ @@ -189,7 +189,7 @@ describe('new MemoryVisitsApi()', () => { }); it('orders by timestamp desc', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ orderBy: [{ field: 'timestamp', direction: 'desc' }], }); expect(visits).toEqual([ @@ -200,7 +200,7 @@ describe('new MemoryVisitsApi()', () => { }); it('orders by entityRef asc', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ orderBy: [{ field: 'entityRef', direction: 'asc' }], }); expect(visits).toEqual([ @@ -211,7 +211,7 @@ describe('new MemoryVisitsApi()', () => { }); it('orders by entityRef desc', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ orderBy: [{ field: 'entityRef', direction: 'desc' }], }); expect(visits).toEqual([ @@ -222,7 +222,7 @@ describe('new MemoryVisitsApi()', () => { }); it('orders by name asc then by entityRef asc', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ orderBy: [ { field: 'name', direction: 'asc' }, { field: 'entityRef', direction: 'asc' }, @@ -236,7 +236,7 @@ describe('new MemoryVisitsApi()', () => { }); it('orders by name desc then by entityRef asc', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ orderBy: [ { field: 'name', direction: 'desc' }, { field: 'entityRef', direction: 'asc' }, @@ -250,7 +250,7 @@ describe('new MemoryVisitsApi()', () => { }); it('filters by timestamp with >', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ filterBy: [{ field: 'timestamp', operator: '>', value: baseDate }], }); expect(visits).toHaveLength(2); @@ -261,7 +261,7 @@ describe('new MemoryVisitsApi()', () => { }); it('filters by timestamp with >=', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ filterBy: [ { field: 'timestamp', operator: '>=', value: baseDate + 360_000 * 2 }, ], @@ -271,7 +271,7 @@ describe('new MemoryVisitsApi()', () => { }); it('filters by timestamp with <', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ filterBy: [{ field: 'timestamp', operator: '<', value: baseDate + 1 }], }); expect(visits).toHaveLength(1); @@ -279,7 +279,7 @@ describe('new MemoryVisitsApi()', () => { }); it('filters by timestamp with <=', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ filterBy: [ { field: 'timestamp', operator: '<=', value: baseDate + 360_000 }, ], @@ -292,7 +292,7 @@ describe('new MemoryVisitsApi()', () => { }); it('filters by timestamp with ==', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ filterBy: [ { field: 'timestamp', operator: '==', value: baseDate + 360_000 }, ], @@ -302,7 +302,7 @@ describe('new MemoryVisitsApi()', () => { }); it('filters by entityRef with contains', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ filterBy: [ { field: 'entityRef', operator: 'contains', value: 'order-2' }, ], @@ -312,7 +312,7 @@ describe('new MemoryVisitsApi()', () => { }); it('filters by timestamp with <= then by name with contains', async () => { - const visits = await api.listVisits({ + const visits = await api.list({ filterBy: [ { field: 'timestamp', operator: '<=', value: baseDate + 360_000 }, { field: 'name', operator: 'contains', value: 'Odd' }, diff --git a/plugins/home/src/api/VisitsApiFactory.ts b/plugins/home/src/api/VisitsApiFactory.ts index 1b04c775a0..d54ed0c984 100644 --- a/plugins/home/src/api/VisitsApiFactory.ts +++ b/plugins/home/src/api/VisitsApiFactory.ts @@ -13,7 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Visit, VisitsApi, VisitsApiQueryParams, VisitsApiSaveParams } from './VisitsApi'; +import { + Visit, + VisitsApi, + VisitsApiQueryParams, + VisitsApiSaveParams, +} from './VisitsApi'; type ArrayElement<A> = A extends readonly (infer T)[] ? T : never; @@ -50,7 +55,7 @@ export class VisitsApiFactory implements VisitsApi { this.persistAll = persistAll ?? (async () => {}); } - async listVisits(queryParams?: VisitsApiQueryParams): Promise<Visit[]> { + async list(queryParams?: VisitsApiQueryParams): Promise<Visit[]> { let visits = await this.retrieveAll(); // reversing order to guarantee orderBy priority @@ -80,9 +85,7 @@ export class VisitsApiFactory implements VisitsApi { return visits; } - async saveVisit( - saveParams: VisitsApiSaveParams, - ): Promise<Visit> { + async save(saveParams: VisitsApiSaveParams): Promise<Visit> { const visits = await this.retrieveAll(); const visit: Visit = { diff --git a/plugins/home/src/components/VisitListener.test.tsx b/plugins/home/src/components/VisitListener.test.tsx index 81587b4067..7a0ce57de5 100644 --- a/plugins/home/src/components/VisitListener.test.tsx +++ b/plugins/home/src/components/VisitListener.test.tsx @@ -45,8 +45,8 @@ const visits: Array<Visit> = [ ]; const mockVisitsApi = { - saveVisit: jest.fn(async () => visits[0]), - listVisits: jest.fn(async () => visits), + save: jest.fn(async () => visits[0]), + list: jest.fn(async () => visits), }; describe('<VisitListener/>', () => { @@ -63,10 +63,8 @@ describe('<VisitListener/>', () => { { routeEntries: [pathname] }, ); - await waitFor(() => - expect(mockVisitsApi.saveVisit).toHaveBeenCalledTimes(1), - ); - expect(mockVisitsApi.saveVisit).toHaveBeenCalledWith({ + await waitFor(() => expect(mockVisitsApi.save).toHaveBeenCalledTimes(1)); + expect(mockVisitsApi.save).toHaveBeenCalledWith({ visit: { pathname, entityRef: 'component:default/playback-order', @@ -102,7 +100,7 @@ describe('<VisitListener/>', () => { ); await waitFor(() => - expect(mockVisitsApi.saveVisit).toHaveBeenCalledWith({ + expect(mockVisitsApi.save).toHaveBeenCalledWith({ visit: { pathname, entityRef: 'component:default/playback-order', @@ -127,7 +125,7 @@ describe('<VisitListener/>', () => { ); await waitFor(() => - expect(mockVisitsApi.saveVisit).toHaveBeenCalledWith({ + expect(mockVisitsApi.save).toHaveBeenCalledWith({ visit: { pathname, entityRef: pathname, diff --git a/plugins/home/src/components/VisitListener.tsx b/plugins/home/src/components/VisitListener.tsx index c0cf34bdc9..4a7900a63a 100644 --- a/plugins/home/src/components/VisitListener.tsx +++ b/plugins/home/src/components/VisitListener.tsx @@ -81,7 +81,7 @@ export const VisitListener = ({ // Wait for the browser to finish with paint with the assumption react // has finished with dom reconciliation. const requestId = requestAnimationFrame(() => { - visitsApi.saveVisit({ + visitsApi.save({ visit: { name: visitNameImpl({ pathname }), pathname, diff --git a/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx b/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx index a9ff2cdd7c..4442c319e6 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/Content.test.tsx @@ -32,8 +32,8 @@ const visits = [ ]; const mockVisitsApi = { - saveVisit: async () => visits[0], - listVisits: async () => visits, + save: async () => visits[0], + list: async () => visits, }; describe('<Content kind="recent"/>', () => { diff --git a/plugins/home/src/homePageComponents/VisitedByType/Content.tsx b/plugins/home/src/homePageComponents/VisitedByType/Content.tsx index 8f492a2099..4e847b717f 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/Content.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/Content.tsx @@ -65,7 +65,7 @@ export const Content = ({ const { loading: reqLoading } = useAsync(async () => { if (!visits && !loading && kind === 'recent') { return await visitsApi - .listVisits({ + .list({ limit: numVisitsTotal ?? 8, orderBy: [{ field: 'timestamp', direction: 'desc' }], }) @@ -73,7 +73,7 @@ export const Content = ({ } if (!visits && !loading && kind === 'top') { return await visitsApi - .listVisits({ + .list({ limit: numVisitsTotal ?? 8, orderBy: [{ field: 'hits', direction: 'desc' }], }) diff --git a/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx b/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx index 0dd9c9e873..19861bf58e 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx @@ -87,8 +87,8 @@ const visits: Array<Visit> = [ ]; const mockVisitsApi = { - saveVisit: async () => visits[0], - listUserVisits: async () => visits, + save: async () => visits[0], + list: async () => visits, }; export default { From 64caa4bf2068ec5a8fe822aa67db4f74c079d50d Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Mon, 18 Sep 2023 10:37:24 +0200 Subject: [PATCH 165/207] refactoring(plugins/home): Remove unnecessary injection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes the injection of localStorage and randomUUID. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> Co-authored-by: Fredrik Adelöw <freben@gmail.com> --- plugins/home/api-report.md | 7 +------ plugins/home/src/api/CoreStorageVisitsApi.ts | 4 +--- plugins/home/src/api/LocalStorageVisitsApi.ts | 9 ++------- plugins/home/src/api/VisitsApiFactory.test.ts | 4 +--- plugins/home/src/api/VisitsApiFactory.ts | 7 ++----- 5 files changed, 7 insertions(+), 24 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index a71916d8b3..38ae82aa7c 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -85,7 +85,6 @@ export class CoreStorageVisitsApi extends VisitsApiFactory { // @public (undocumented) export type CoreStorageVisitsApiOptions = { storageApi: StorageApi; - randomUUID?: Window['crypto']['randomUUID']; limit?: number; identityApi: IdentityApi; }; @@ -185,8 +184,6 @@ export class LocalStorageVisitsApi extends VisitsApiFactory { // @public (undocumented) export type LocalStorageVisitsApiOptions = { - localStorage?: Window['localStorage']; - randomUUID?: Window['crypto']['randomUUID']; limit?: number; identityApi: IdentityApi; }; @@ -269,7 +266,6 @@ export interface VisitsApi { // @public export class VisitsApiFactory implements VisitsApi { protected constructor({ - randomUUID, limit, retrieveAll, persistAll, @@ -281,7 +277,7 @@ export class VisitsApiFactory implements VisitsApi { // (undocumented) protected persistAll: (visits: Array<Visit>) => Promise<void>; // (undocumented) - protected readonly randomUUID: Window['crypto']['randomUUID']; + protected readonly randomUUID: () => `${string}-${string}-${string}-${string}-${string}`; // (undocumented) protected retrieveAll: () => Promise<Array<Visit>>; // (undocumented) @@ -290,7 +286,6 @@ export class VisitsApiFactory implements VisitsApi { // @public (undocumented) export type VisitsApiFactoryOptions = { - randomUUID: Window['crypto']['randomUUID']; limit: number; retrieveAll?: () => Promise<Array<Visit>>; persistAll?: (visits: Array<Visit>) => Promise<void>; diff --git a/plugins/home/src/api/CoreStorageVisitsApi.ts b/plugins/home/src/api/CoreStorageVisitsApi.ts index c4b70eff88..e392c2f30c 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.ts @@ -20,7 +20,6 @@ import { VisitsApiFactory } from './VisitsApiFactory'; /** @public */ export type CoreStorageVisitsApiOptions = { storageApi: StorageApi; - randomUUID?: Window['crypto']['randomUUID']; limit?: number; identityApi: IdentityApi; }; @@ -41,10 +40,9 @@ export class CoreStorageVisitsApi extends VisitsApiFactory { private constructor({ storageApi, identityApi, - randomUUID = window?.crypto?.randomUUID, limit = 100, }: CoreStorageVisitsApiOptions) { - super({ randomUUID, limit }); + super({ limit }); this.storageApi = storageApi; this.identityApi = identityApi; this.retrieveAll = async (): Promise<Array<Visit>> => { diff --git a/plugins/home/src/api/LocalStorageVisitsApi.ts b/plugins/home/src/api/LocalStorageVisitsApi.ts index 31cd30dc21..42f8495a5e 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.ts @@ -19,8 +19,6 @@ import { VisitsApiFactory } from './VisitsApiFactory'; /** @public */ export type LocalStorageVisitsApiOptions = { - localStorage?: Window['localStorage']; - randomUUID?: Window['crypto']['randomUUID']; limit?: number; identityApi: IdentityApi; }; @@ -30,7 +28,7 @@ export type LocalStorageVisitsApiOptions = { * This is a reference implementation of VisitsApi using window.localStorage. */ export class LocalStorageVisitsApi extends VisitsApiFactory { - private readonly localStorage: Window['localStorage']; + private readonly localStorage = window.localStorage; private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; private readonly identityApi: IdentityApi; @@ -39,13 +37,10 @@ export class LocalStorageVisitsApi extends VisitsApiFactory { } private constructor({ - localStorage = window?.localStorage, - randomUUID = window?.crypto?.randomUUID, limit = 100, identityApi, }: LocalStorageVisitsApiOptions) { - super({ randomUUID, limit }); - this.localStorage = localStorage; + super({ limit }); this.identityApi = identityApi; this.retrieveAll = async (): Promise<Array<Visit>> => { let visits: Array<Visit>; diff --git a/plugins/home/src/api/VisitsApiFactory.test.ts b/plugins/home/src/api/VisitsApiFactory.test.ts index 8c19a8e6a5..4e00b1432f 100644 --- a/plugins/home/src/api/VisitsApiFactory.test.ts +++ b/plugins/home/src/api/VisitsApiFactory.test.ts @@ -21,13 +21,11 @@ class MemoryVisitsApi extends VisitsApiFactory { private visits: Array<Visit> = []; constructor({ - randomUUID = window?.crypto?.randomUUID, limit = 100, }: { - randomUUID?: Window['crypto']['randomUUID']; limit?: number; } = {}) { - super({ randomUUID, limit }); + super({ limit }); this.retrieveAll = async (): Promise<Array<Visit>> => { let visits: Array<Visit>; try { diff --git a/plugins/home/src/api/VisitsApiFactory.ts b/plugins/home/src/api/VisitsApiFactory.ts index d54ed0c984..48952c0a1c 100644 --- a/plugins/home/src/api/VisitsApiFactory.ts +++ b/plugins/home/src/api/VisitsApiFactory.ts @@ -24,7 +24,6 @@ type ArrayElement<A> = A extends readonly (infer T)[] ? T : never; /** @public */ export type VisitsApiFactoryOptions = { - randomUUID: Window['crypto']['randomUUID']; limit: number; retrieveAll?: () => Promise<Array<Visit>>; persistAll?: (visits: Array<Visit>) => Promise<void>; @@ -38,18 +37,16 @@ export type VisitsApiFactoryOptions = { * See LocalStorageVisitsApi for an usage example. */ export class VisitsApiFactory implements VisitsApi { - protected readonly randomUUID: Window['crypto']['randomUUID']; + protected readonly randomUUID = window.crypto.randomUUID; protected readonly limit: number; protected retrieveAll: () => Promise<Array<Visit>>; protected persistAll: (visits: Array<Visit>) => Promise<void>; protected constructor({ - randomUUID = window?.crypto?.randomUUID, limit = 100, retrieveAll, persistAll, }: VisitsApiFactoryOptions) { - this.randomUUID = randomUUID; this.limit = Math.abs(limit); this.retrieveAll = retrieveAll ?? (async () => []); this.persistAll = persistAll ?? (async () => {}); @@ -90,7 +87,7 @@ export class VisitsApiFactory implements VisitsApi { const visit: Visit = { ...saveParams.visit, - id: this.randomUUID(), + id: window.crypto.randomUUID(), hits: 1, timestamp: Date.now(), }; From bc93253806f8db0a7c584bce56e703dc34942b96 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Mon, 18 Sep 2023 10:56:14 +0200 Subject: [PATCH 166/207] refactor(plugins/home): Keep api-report concise. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch remove parameter destructuring to simplify api-report reads. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> Co-authored-by: Fredrik Adelöw <freben@gmail.com> --- plugins/home/api-report.md | 6 +----- plugins/home/src/api/CoreStorageVisitsApi.ts | 12 ++++-------- plugins/home/src/api/LocalStorageVisitsApi.ts | 9 +++------ plugins/home/src/api/VisitsApiFactory.ts | 12 ++++-------- 4 files changed, 12 insertions(+), 27 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 38ae82aa7c..9271d00492 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -265,11 +265,7 @@ export interface VisitsApi { // @public export class VisitsApiFactory implements VisitsApi { - protected constructor({ - limit, - retrieveAll, - persistAll, - }: VisitsApiFactoryOptions); + protected constructor(options: VisitsApiFactoryOptions); // (undocumented) protected readonly limit: number; // (undocumented) diff --git a/plugins/home/src/api/CoreStorageVisitsApi.ts b/plugins/home/src/api/CoreStorageVisitsApi.ts index e392c2f30c..18cdaca90f 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.ts @@ -37,14 +37,10 @@ export class CoreStorageVisitsApi extends VisitsApiFactory { return new CoreStorageVisitsApi(options); } - private constructor({ - storageApi, - identityApi, - limit = 100, - }: CoreStorageVisitsApiOptions) { - super({ limit }); - this.storageApi = storageApi; - this.identityApi = identityApi; + private constructor(options: CoreStorageVisitsApiOptions) { + super({ limit: options.limit ?? 100 }); + this.storageApi = options.storageApi; + this.identityApi = options.identityApi; this.retrieveAll = async (): Promise<Array<Visit>> => { let visits: Array<Visit>; const { userEntityRef } = await this.identityApi.getBackstageIdentity(); diff --git a/plugins/home/src/api/LocalStorageVisitsApi.ts b/plugins/home/src/api/LocalStorageVisitsApi.ts index 42f8495a5e..44932b93f5 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.ts @@ -36,12 +36,9 @@ export class LocalStorageVisitsApi extends VisitsApiFactory { return new LocalStorageVisitsApi(options); } - private constructor({ - limit = 100, - identityApi, - }: LocalStorageVisitsApiOptions) { - super({ limit }); - this.identityApi = identityApi; + private constructor(options: LocalStorageVisitsApiOptions) { + super({ limit: options.limit ?? 100 }); + this.identityApi = options.identityApi; this.retrieveAll = async (): Promise<Array<Visit>> => { let visits: Array<Visit>; const { userEntityRef } = await this.identityApi.getBackstageIdentity(); diff --git a/plugins/home/src/api/VisitsApiFactory.ts b/plugins/home/src/api/VisitsApiFactory.ts index 48952c0a1c..e83bcef723 100644 --- a/plugins/home/src/api/VisitsApiFactory.ts +++ b/plugins/home/src/api/VisitsApiFactory.ts @@ -42,14 +42,10 @@ export class VisitsApiFactory implements VisitsApi { protected retrieveAll: () => Promise<Array<Visit>>; protected persistAll: (visits: Array<Visit>) => Promise<void>; - protected constructor({ - limit = 100, - retrieveAll, - persistAll, - }: VisitsApiFactoryOptions) { - this.limit = Math.abs(limit); - this.retrieveAll = retrieveAll ?? (async () => []); - this.persistAll = persistAll ?? (async () => {}); + protected constructor(options: VisitsApiFactoryOptions) { + this.limit = Math.abs(options.limit ?? 100); + this.retrieveAll = options.retrieveAll ?? (async () => []); + this.persistAll = options.persistAll ?? (async () => {}); } async list(queryParams?: VisitsApiQueryParams): Promise<Visit[]> { From a1a7885ca45353b804462c84dac757ef8b498445 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Tue, 19 Sep 2023 11:10:11 +0200 Subject: [PATCH 167/207] feature(plugins/home): Add support for the != operator This patch adds support for the != operator on the VisitsApi filterBy option. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/api-report.md | 2 +- plugins/home/src/api/VisitsApi.ts | 2 +- plugins/home/src/api/VisitsApiFactory.test.ts | 13 +++++++++++++ plugins/home/src/api/VisitsApiFactory.ts | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 9271d00492..f0a38506ca 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -296,7 +296,7 @@ export type VisitsApiQueryParams = { }>; filterBy?: Array<{ field: keyof Visit; - operator: '<' | '<=' | '==' | '>' | '>=' | 'contains'; + operator: '<' | '<=' | '==' | '!=' | '>' | '>=' | 'contains'; value: string | number; }>; }; diff --git a/plugins/home/src/api/VisitsApi.ts b/plugins/home/src/api/VisitsApi.ts index ab43d1c7a7..ad750d81f2 100644 --- a/plugins/home/src/api/VisitsApi.ts +++ b/plugins/home/src/api/VisitsApi.ts @@ -84,7 +84,7 @@ export type VisitsApiQueryParams = { */ filterBy?: Array<{ field: keyof Visit; - operator: '<' | '<=' | '==' | '>' | '>=' | 'contains'; + operator: '<' | '<=' | '==' | '!=' | '>' | '>=' | 'contains'; value: string | number; }>; }; diff --git a/plugins/home/src/api/VisitsApiFactory.test.ts b/plugins/home/src/api/VisitsApiFactory.test.ts index 4e00b1432f..416481be53 100644 --- a/plugins/home/src/api/VisitsApiFactory.test.ts +++ b/plugins/home/src/api/VisitsApiFactory.test.ts @@ -299,6 +299,19 @@ describe('new MemoryVisitsApi()', () => { expect(visits).toEqual([expect.objectContaining(visitsToSave[1])]); }); + it('filters by timestamp with !=', async () => { + const visits = await api.list({ + filterBy: [ + { field: 'timestamp', operator: '!=', value: baseDate + 360_000 }, + ], + }); + expect(visits).toHaveLength(2); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + it('filters by entityRef with contains', async () => { const visits = await api.list({ filterBy: [ diff --git a/plugins/home/src/api/VisitsApiFactory.ts b/plugins/home/src/api/VisitsApiFactory.ts index e83bcef723..9ba6a2fe79 100644 --- a/plugins/home/src/api/VisitsApiFactory.ts +++ b/plugins/home/src/api/VisitsApiFactory.ts @@ -69,6 +69,7 @@ export class VisitsApiFactory implements VisitsApi { if (filter.operator === '<') return field < filter.value; if (filter.operator === '<=') return field <= filter.value; if (filter.operator === '==') return field === filter.value; + if (filter.operator === '!=') return field !== filter.value; if (filter.operator === 'contains') return `${field}`.includes(`${filter.value}`); return false; From f997f771da3a9631e54dcb321c41bcf4516d9c5d Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Tue, 19 Sep 2023 16:40:36 +0200 Subject: [PATCH 168/207] changeset(plugins/home): Adds new Top/Recently Visited components Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- .changeset/happy-books-smoke.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/happy-books-smoke.md diff --git a/.changeset/happy-books-smoke.md b/.changeset/happy-books-smoke.md new file mode 100644 index 0000000000..b035f84cfd --- /dev/null +++ b/.changeset/happy-books-smoke.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': minor +--- + +Adds Top/Recently Visited components to homepage From 72f3ea7042fd9deb7e72ab36fdb03a7839248bdc Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Wed, 20 Sep 2023 10:27:41 +0200 Subject: [PATCH 169/207] refactor(plugins/home): Remove any type Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- .../home/src/homePageComponents/VisitedByType/Context.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/home/src/homePageComponents/VisitedByType/Context.tsx b/plugins/home/src/homePageComponents/VisitedByType/Context.tsx index 0d1c2100f2..cd316d8b75 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/Context.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/Context.tsx @@ -60,14 +60,15 @@ export const defaultContextValue: ContextValue = { export const Context = createContext<ContextValue>(defaultContextValue); const getFilteredSet = - ( + <T,>( setContext: Dispatch<SetStateAction<ContextValueOnly>>, contextKey: keyof ContextValueOnly, ) => - (e: SetStateAction<any>) => + (e: SetStateAction<T>) => setContext(state => ({ ...state, - [contextKey]: typeof e === 'function' ? e(state[contextKey]) : e, + [contextKey]: + typeof e === 'function' ? (e as Function)(state[contextKey]) : e, })); export const ContextProvider = ({ children }: { children: JSX.Element }) => { From baa8af646ca83c42d87e2e5fa34821735a5b15cc Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Wed, 20 Sep 2023 14:03:20 +0200 Subject: [PATCH 170/207] refactor(plugins/home): Implementations depend only on StorageApi This patch removes the VisitsApiFactory, promotes CoreStorageVisitsApi to the main implementation and LocalStorageVisitsApi starts to rely on WebStorage. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/README.md | 7 +- plugins/home/api-report.md | 36 +- plugins/home/package.json | 2 +- .../home/src/api/CoreStorageVisitsApi.test.ts | 312 ++++++++++++++-- plugins/home/src/api/CoreStorageVisitsApi.ts | 128 +++++-- .../src/api/LocalStorageVisitsApi.test.ts | 17 +- plugins/home/src/api/LocalStorageVisitsApi.ts | 47 +-- plugins/home/src/api/VisitsApiFactory.test.ts | 336 ------------------ plugins/home/src/api/VisitsApiFactory.ts | 120 ------- plugins/home/src/api/index.ts | 1 - 10 files changed, 429 insertions(+), 577 deletions(-) delete mode 100644 plugins/home/src/api/VisitsApiFactory.test.ts delete mode 100644 plugins/home/src/api/VisitsApiFactory.ts diff --git a/plugins/home/README.md b/plugins/home/README.md index f6a223701b..af3b3a12f6 100644 --- a/plugins/home/README.md +++ b/plugins/home/README.md @@ -280,7 +280,7 @@ import { } from '@backstage/plugin-home'; // ... export const apis: AnyApiFactory[] = [ - // Implementation that relies on the integration with storageApi + // Implementation that relies on a provided storageApi createApiFactory({ api: visitsApiRef, deps: { @@ -291,13 +291,14 @@ export const apis: AnyApiFactory[] = [ CoreStorageVisitsApi.create({ storageApi, identityApi }), }), - // Or a local data implementation, relies on the browser's window.localStorage + // Or a local data implementation, relies on WebStorage implementation of storageApi createApiFactory({ api: visitsApiRef, deps: { identityApi: identityApiRef, + errorApi: errorApiRef }, - factory: ({ identityApi }) => LocalStoreVisitsApi.create({ identityApi }), + factory: ({ identityApi, errorApi }) => LocalStoreVisitsApi.create({ identityApi, errorApi }), }), // ... ``` diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index f0a38506ca..5da8f912a5 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -14,6 +14,7 @@ import { CardSettings as CardSettings_2 } from '@backstage/plugin-home-react'; import { ComponentParts as ComponentParts_2 } from '@backstage/plugin-home-react'; import { ComponentRenderer as ComponentRenderer_2 } from '@backstage/plugin-home-react'; import { createCardExtension as createCardExtension_2 } from '@backstage/plugin-home-react'; +import { ErrorApi } from '@backstage/core-plugin-api'; import { IdentityApi } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; import { default as React_2 } from 'react'; @@ -77,15 +78,17 @@ export const ComponentTabs: (props: { }) => JSX_2.Element; // @public -export class CoreStorageVisitsApi extends VisitsApiFactory { +export class CoreStorageVisitsApi implements VisitsApi { // (undocumented) static create(options: CoreStorageVisitsApiOptions): CoreStorageVisitsApi; + list(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; + save(saveParams: VisitsApiSaveParams): Promise<Visit>; } // @public (undocumented) export type CoreStorageVisitsApiOptions = { - storageApi: StorageApi; limit?: number; + storageApi: StorageApi; identityApi: IdentityApi; }; @@ -177,15 +180,16 @@ export type LayoutConfiguration = { }; // @public -export class LocalStorageVisitsApi extends VisitsApiFactory { +export class LocalStorageVisitsApi { // (undocumented) - static create(options: LocalStorageVisitsApiOptions): LocalStorageVisitsApi; + static create(options: LocalStorageVisitsApiOptions): CoreStorageVisitsApi; } // @public (undocumented) export type LocalStorageVisitsApiOptions = { limit?: number; identityApi: IdentityApi; + errorApi: ErrorApi; }; // @public @deprecated (undocumented) @@ -263,30 +267,6 @@ export interface VisitsApi { save(saveParams: VisitsApiSaveParams): Promise<Visit>; } -// @public -export class VisitsApiFactory implements VisitsApi { - protected constructor(options: VisitsApiFactoryOptions); - // (undocumented) - protected readonly limit: number; - // (undocumented) - list(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; - // (undocumented) - protected persistAll: (visits: Array<Visit>) => Promise<void>; - // (undocumented) - protected readonly randomUUID: () => `${string}-${string}-${string}-${string}-${string}`; - // (undocumented) - protected retrieveAll: () => Promise<Array<Visit>>; - // (undocumented) - save(saveParams: VisitsApiSaveParams): Promise<Visit>; -} - -// @public (undocumented) -export type VisitsApiFactoryOptions = { - limit: number; - retrieveAll?: () => Promise<Array<Visit>>; - persistAll?: (visits: Array<Visit>) => Promise<void>; -}; - // @public export type VisitsApiQueryParams = { limit?: number; diff --git a/plugins/home/package.json b/plugins/home/package.json index 6a9c5306c1..80fb8496b1 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -36,6 +36,7 @@ "dependencies": { "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", + "@backstage/core-app-api": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", @@ -64,7 +65,6 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", - "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^8.0.0", diff --git a/plugins/home/src/api/CoreStorageVisitsApi.test.ts b/plugins/home/src/api/CoreStorageVisitsApi.test.ts index e1f39d8464..9118b2546b 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.test.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.test.ts @@ -17,8 +17,9 @@ import { BackstageUserIdentity, IdentityApi } from '@backstage/core-plugin-api'; import { CoreStorageVisitsApi } from './CoreStorageVisitsApi'; import { MockStorageApi } from '@backstage/test-utils'; +import { Visit, VisitsApi } from './VisitsApi'; -describe('CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create() })', () => { +describe('CoreStorageVisitsApi.create', () => { const mockRandomUUID = () => '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( /x/g, @@ -35,9 +36,12 @@ describe('CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create() })', beforeEach(() => { window.crypto.randomUUID = mockRandomUUID; + jest.useFakeTimers(); }); afterEach(() => { + jest.resetAllMocks(); + jest.useRealTimers(); window.localStorage.clear(); }); @@ -49,37 +53,287 @@ describe('CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create() })', expect(api).toBeTruthy(); }); - it('saves a visit', async () => { - const api = CoreStorageVisitsApi.create({ - storageApi: MockStorageApi.create(), - identityApi: mockIdentityApi, + describe('.save()', () => { + it('saves a visit', async () => { + const api = CoreStorageVisitsApi.create({ + storageApi: MockStorageApi.create(), + identityApi: mockIdentityApi, + }); + const visit = { + pathname: '/catalog/default/component/playback-order', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + const returnedVisit = await api.save({ visit }); + expect(returnedVisit).toEqual(expect.objectContaining(visit)); + expect(returnedVisit.id).toBeTruthy(); + expect(returnedVisit.timestamp).toBeTruthy(); + expect(returnedVisit.hits).toBeTruthy(); + }); + + it('can control the number of stored entities', async () => { + const api = CoreStorageVisitsApi.create({ + storageApi: MockStorageApi.create(), + identityApi: mockIdentityApi, + limit: 2, + }); + const baseDate = Date.now(); + const visit1 = { + pathname: '/catalog/default/component/playback-order-1', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + jest.setSystemTime(baseDate); + await api.save({ visit: visit1 }); + const visit2 = { + pathname: '/catalog/default/component/playback-order-2', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + jest.setSystemTime(baseDate + 360_000); + await api.save({ visit: visit2 }); + const visit3 = { + pathname: '/catalog/default/component/playback-order-3', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + jest.setSystemTime(baseDate + 360_000 * 2); + await api.save({ visit: visit3 }); + const visits = await api.list(); + expect(visits).toHaveLength(2); + expect(visits).toContainEqual(expect.objectContaining(visit2)); + expect(visits).toContainEqual(expect.objectContaining(visit3)); + }); + + it('correctly bumps the hits from a previous visit', async () => { + const api = CoreStorageVisitsApi.create({ + storageApi: MockStorageApi.create(), + identityApi: mockIdentityApi, + }); + const visit = { + pathname: '/catalog/default/component/playback-order', + entityRef: 'component:default/playback-order', + name: 'Playback Order', + }; + const visit1 = await api.save({ visit }); + const visit2 = await api.save({ visit }); + const visits = await api.list(); + expect(visits).toHaveLength(1); + expect(visits).toContainEqual(expect.objectContaining(visit)); + // keeps the original id created on the first visit + expect(visits).toContainEqual(expect.objectContaining({ id: visit1.id })); + // updates timestamp and hits + expect(visits).toContainEqual( + expect.objectContaining({ timestamp: visit2.timestamp, hits: 2 }), + ); }); - const visit = { - pathname: '/catalog/default/component/playback-order', - entityRef: 'component:default/playback-order', - name: 'Playback Order', - }; - const returnedVisit = await api.save({ visit }); - expect(returnedVisit).toEqual(expect.objectContaining(visit)); - expect(returnedVisit.id).toBeTruthy(); - expect(returnedVisit.timestamp).toBeTruthy(); - expect(returnedVisit.hits).toBeTruthy(); }); - it('retrieves visits', async () => { - const api = CoreStorageVisitsApi.create({ - storageApi: MockStorageApi.create(), - identityApi: mockIdentityApi, + describe('.list()', () => { + let api: VisitsApi; + let visitsToSave: Array<Omit<Visit, 'id' | 'hits' | 'timestamp'>>; + let baseDate: number; + + beforeEach(() => { + api = CoreStorageVisitsApi.create({ + storageApi: MockStorageApi.create(), + identityApi: mockIdentityApi, + }); + visitsToSave = [ + { + pathname: '/catalog/default/component/playback-order-1', + entityRef: 'component:default/playback-order-1', + name: 'Playback Order Odd', + }, + { + pathname: '/catalog/default/component/playback-order-2', + entityRef: 'component:default/playback-order-2', + name: 'Playback Order Even', + }, + { + pathname: '/catalog/default/component/playback-order-3', + entityRef: 'component:default/playback-order-3', + name: 'Playback Order Odd', + }, + ]; + baseDate = Date.now(); + // Chaining items to ensure the right setSystemTime + return visitsToSave.reduce( + (acc, visit, index) => + acc.then(() => { + jest.setSystemTime(baseDate + 360_000 * index); + return api.save({ visit }); + }), + Promise.resolve({}), + ); + }); + + it('retrieves visits', async () => { + const visits = await api.list(); + expect(visits).toHaveLength(3); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + + it('orders by timestamp asc', async () => { + const visits = await api.list({ + orderBy: [{ field: 'timestamp', direction: 'asc' }], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[0]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[2]), + ]); + }); + + it('orders by timestamp desc', async () => { + const visits = await api.list({ + orderBy: [{ field: 'timestamp', direction: 'desc' }], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + + it('orders by entityRef asc', async () => { + const visits = await api.list({ + orderBy: [{ field: 'entityRef', direction: 'asc' }], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[0]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[2]), + ]); + }); + + it('orders by entityRef desc', async () => { + const visits = await api.list({ + orderBy: [{ field: 'entityRef', direction: 'desc' }], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + + it('orders by name asc then by entityRef asc', async () => { + const visits = await api.list({ + orderBy: [ + { field: 'name', direction: 'asc' }, + { field: 'entityRef', direction: 'asc' }, + ], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[1]), // Playback Order Even, playback-order-2 + expect.objectContaining(visitsToSave[0]), // Playback Order Odd, playback-order-1 + expect.objectContaining(visitsToSave[2]), // Playback Order Odd, playback-order-3 + ]); + }); + + it('orders by name desc then by entityRef asc', async () => { + const visits = await api.list({ + orderBy: [ + { field: 'name', direction: 'desc' }, + { field: 'entityRef', direction: 'asc' }, + ], + }); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[0]), // Playback Order Odd, playback-order-1 + expect.objectContaining(visitsToSave[2]), // Playback Order Odd, playback-order-3 + expect.objectContaining(visitsToSave[1]), // Playback Order Even, playback-order-2 + ]); + }); + + it('filters by timestamp with >', async () => { + const visits = await api.list({ + filterBy: [{ field: 'timestamp', operator: '>', value: baseDate }], + }); + expect(visits).toHaveLength(2); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[1]), + ]); + }); + + it('filters by timestamp with >=', async () => { + const visits = await api.list({ + filterBy: [ + { field: 'timestamp', operator: '>=', value: baseDate + 360_000 * 2 }, + ], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[2])]); + }); + + it('filters by timestamp with <', async () => { + const visits = await api.list({ + filterBy: [{ field: 'timestamp', operator: '<', value: baseDate + 1 }], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[0])]); + }); + + it('filters by timestamp with <=', async () => { + const visits = await api.list({ + filterBy: [ + { field: 'timestamp', operator: '<=', value: baseDate + 360_000 }, + ], + }); + expect(visits).toHaveLength(2); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[1]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + + it('filters by timestamp with ==', async () => { + const visits = await api.list({ + filterBy: [ + { field: 'timestamp', operator: '==', value: baseDate + 360_000 }, + ], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[1])]); + }); + + it('filters by timestamp with !=', async () => { + const visits = await api.list({ + filterBy: [ + { field: 'timestamp', operator: '!=', value: baseDate + 360_000 }, + ], + }); + expect(visits).toHaveLength(2); + expect(visits).toEqual([ + expect.objectContaining(visitsToSave[2]), + expect.objectContaining(visitsToSave[0]), + ]); + }); + + it('filters by entityRef with contains', async () => { + const visits = await api.list({ + filterBy: [ + { field: 'entityRef', operator: 'contains', value: 'order-2' }, + ], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[1])]); + }); + + it('filters by timestamp with <= then by name with contains', async () => { + const visits = await api.list({ + filterBy: [ + { field: 'timestamp', operator: '<=', value: baseDate + 360_000 }, + { field: 'name', operator: 'contains', value: 'Odd' }, + ], + }); + expect(visits).toHaveLength(1); + expect(visits).toEqual([expect.objectContaining(visitsToSave[0])]); }); - const visit = { - pathname: '/catalog/default/component/playback-order', - entityRef: 'component:default/playback-order', - name: 'Playback Order', - }; - const returnedVisit = await api.save({ visit }); - const visits = await api.list(); - expect(visits).toHaveLength(1); - expect(visits).toEqual([expect.objectContaining(visit)]); - expect(visits).toEqual([returnedVisit]); }); }); diff --git a/plugins/home/src/api/CoreStorageVisitsApi.ts b/plugins/home/src/api/CoreStorageVisitsApi.ts index 18cdaca90f..2707a50b87 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.ts @@ -14,21 +14,31 @@ * limitations under the License. */ import { IdentityApi, StorageApi } from '@backstage/core-plugin-api'; -import { Visit } from './VisitsApi'; -import { VisitsApiFactory } from './VisitsApiFactory'; +import { + Visit, + VisitsApi, + VisitsApiQueryParams, + VisitsApiSaveParams, +} from './VisitsApi'; /** @public */ export type CoreStorageVisitsApiOptions = { - storageApi: StorageApi; limit?: number; + storageApi: StorageApi; identityApi: IdentityApi; }; +type ArrayElement<A> = A extends readonly (infer T)[] ? T : never; + /** * @public - * This is an implementation of VisitsApi that relies on a StorageApi + * This is an implementation of VisitsApi that relies on a StorageApi. + * Beware that filtering and ordering are done in memory therefore it is + * prudent to keep limit to a reasonable size. */ -export class CoreStorageVisitsApi extends VisitsApiFactory { +export class CoreStorageVisitsApi implements VisitsApi { + private readonly randomUUID = window.crypto.randomUUID; + private readonly limit: number; private readonly storageApi: StorageApi; private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; private readonly identityApi: IdentityApi; @@ -38,26 +48,104 @@ export class CoreStorageVisitsApi extends VisitsApiFactory { } private constructor(options: CoreStorageVisitsApiOptions) { - super({ limit: options.limit ?? 100 }); + this.limit = Math.abs(options.limit ?? 100); this.storageApi = options.storageApi; this.identityApi = options.identityApi; - this.retrieveAll = async (): Promise<Array<Visit>> => { - let visits: Array<Visit>; - const { userEntityRef } = await this.identityApi.getBackstageIdentity(); - const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; + } - try { - visits = this.storageApi.snapshot<Array<Visit>>(storageKey).value ?? []; - } catch { - visits = []; + /** + * Returns a list of visits through the visitsApi + */ + async list(queryParams?: VisitsApiQueryParams): Promise<Visit[]> { + let visits = [...(await this.retrieveAll())]; + + // reversing order to guarantee orderBy priority + (queryParams?.orderBy ?? []).reverse().forEach(order => { + if (order.direction === 'asc') { + visits.sort((a, b) => this.compare(order, a, b)); + } else { + visits.sort((a, b) => this.compare(order, b, a)); } - return visits; - }; - this.persistAll = async (visits: Array<Visit>) => { - const { userEntityRef } = await this.identityApi.getBackstageIdentity(); - const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; + }); - return this.storageApi.set<Array<Visit>>(storageKey, visits); + // reversing order to guarantee filterBy priority + (queryParams?.filterBy ?? []).reverse().forEach(filter => { + visits = visits.filter(visit => { + const field = visit[filter.field] as number | string; + if (filter.operator === '>') return field > filter.value; + if (filter.operator === '>=') return field >= filter.value; + if (filter.operator === '<') return field < filter.value; + if (filter.operator === '<=') return field <= filter.value; + if (filter.operator === '==') return field === filter.value; + if (filter.operator === '!=') return field !== filter.value; + if (filter.operator === 'contains') + return `${field}`.includes(`${filter.value}`); + return false; + }); + }); + + return visits; + } + + /** + * Saves a visit through the visitsApi + */ + async save(saveParams: VisitsApiSaveParams): Promise<Visit> { + const visits: Visit[] = [...(await this.retrieveAll())]; + + const visit: Visit = { + ...saveParams.visit, + id: this.randomUUID(), + hits: 1, + timestamp: Date.now(), }; + + // Updates entry if pathname is already registered + const visitIndex = visits.findIndex(e => e.pathname === visit.pathname); + if (visitIndex >= 0) { + visit.id = visits[visitIndex].id; + visit.hits = visits[visitIndex].hits + 1; + visits[visitIndex] = visit; + } else { + visits.push(visit); + } + + // Sort by time, most recent first + visits.sort((a, b) => b.timestamp - a.timestamp); + // Keep the most recent items up to limit + await this.persistAll(visits.splice(0, this.limit)); + return visit; + } + + private async persistAll(visits: Array<Visit>) { + const { userEntityRef } = await this.identityApi.getBackstageIdentity(); + const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; + + return this.storageApi.set<Array<Visit>>(storageKey, visits); + } + + private async retrieveAll(): Promise<Array<Visit>> { + const { userEntityRef } = await this.identityApi.getBackstageIdentity(); + const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; + let visits: Array<Visit>; + + try { + visits = this.storageApi.snapshot<Array<Visit>>(storageKey).value ?? []; + } catch { + visits = []; + } + return visits; + } + + // This assumes Visit fields are either numbers or strings + private compare( + order: ArrayElement<VisitsApiQueryParams['orderBy']>, + a: Visit, + b: Visit, + ): number { + const isNumber = typeof a[order.field] === 'number'; + return isNumber + ? (a[order.field] as number) - (b[order.field] as number) + : `${a[order.field]}`.localeCompare(`${b[order.field]}`); } } diff --git a/plugins/home/src/api/LocalStorageVisitsApi.test.ts b/plugins/home/src/api/LocalStorageVisitsApi.test.ts index eb19859055..b646af209e 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.test.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.test.ts @@ -32,6 +32,8 @@ describe('LocalStorageVisitsApi.create()', () => { getCredentials: jest.fn(), }; + const mockErrorApi = { post: jest.fn(), error$: jest.fn() }; + beforeEach(() => { window.crypto.randomUUID = mockRandomUUID; }); @@ -42,12 +44,18 @@ describe('LocalStorageVisitsApi.create()', () => { }); it('instantiates with only identitiyApi', () => { - const api = LocalStorageVisitsApi.create({ identityApi: mockIdentityApi }); + const api = LocalStorageVisitsApi.create({ + identityApi: mockIdentityApi, + errorApi: mockErrorApi, + }); expect(api).toBeTruthy(); }); it('saves a visit', async () => { - const api = LocalStorageVisitsApi.create({ identityApi: mockIdentityApi }); + const api = LocalStorageVisitsApi.create({ + identityApi: mockIdentityApi, + errorApi: mockErrorApi, + }); const visit = { pathname: '/catalog/default/component/playback-order', entityRef: 'component:default/playback-order', @@ -61,7 +69,10 @@ describe('LocalStorageVisitsApi.create()', () => { }); it('retrieves visits', async () => { - const api = LocalStorageVisitsApi.create({ identityApi: mockIdentityApi }); + const api = LocalStorageVisitsApi.create({ + identityApi: mockIdentityApi, + errorApi: mockErrorApi, + }); const visit = { pathname: '/catalog/default/component/playback-order', entityRef: 'component:default/playback-order', diff --git a/plugins/home/src/api/LocalStorageVisitsApi.ts b/plugins/home/src/api/LocalStorageVisitsApi.ts index 44932b93f5..01d57b93d9 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.ts @@ -13,52 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { IdentityApi } from '@backstage/core-plugin-api'; -import { Visit } from './VisitsApi'; -import { VisitsApiFactory } from './VisitsApiFactory'; +import { ErrorApi, IdentityApi } from '@backstage/core-plugin-api'; +import { CoreStorageVisitsApi } from './CoreStorageVisitsApi'; +import { WebStorage } from '@backstage/core-app-api'; /** @public */ export type LocalStorageVisitsApiOptions = { limit?: number; identityApi: IdentityApi; + errorApi: ErrorApi; }; /** * @public - * This is a reference implementation of VisitsApi using window.localStorage. + * This is a reference implementation of VisitsApi using WebStorage. */ -export class LocalStorageVisitsApi extends VisitsApiFactory { - private readonly localStorage = window.localStorage; - private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; - private readonly identityApi: IdentityApi; - +export class LocalStorageVisitsApi { static create(options: LocalStorageVisitsApiOptions) { - return new LocalStorageVisitsApi(options); - } - - private constructor(options: LocalStorageVisitsApiOptions) { - super({ limit: options.limit ?? 100 }); - this.identityApi = options.identityApi; - this.retrieveAll = async (): Promise<Array<Visit>> => { - let visits: Array<Visit>; - const { userEntityRef } = await this.identityApi.getBackstageIdentity(); - const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; - - try { - visits = JSON.parse(this.localStorage.getItem(storageKey) ?? '[]'); - } catch { - visits = []; - } - return visits; - }; - this.persistAll = async (visits: Array<Visit>) => { - const { userEntityRef } = await this.identityApi.getBackstageIdentity(); - const storageKey = `${this.storageKeyPrefix}:${userEntityRef}`; - - return this.localStorage.setItem( - storageKey, - JSON.stringify(visits.splice(0, this.limit)), - ); - }; + return CoreStorageVisitsApi.create({ + limit: options.limit, + identityApi: options.identityApi, + storageApi: WebStorage.create({ errorApi: options.errorApi }), + }); } } diff --git a/plugins/home/src/api/VisitsApiFactory.test.ts b/plugins/home/src/api/VisitsApiFactory.test.ts deleted file mode 100644 index 416481be53..0000000000 --- a/plugins/home/src/api/VisitsApiFactory.test.ts +++ /dev/null @@ -1,336 +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 { Visit } from './VisitsApi'; -import { VisitsApiFactory } from './VisitsApiFactory'; - -class MemoryVisitsApi extends VisitsApiFactory { - private visits: Array<Visit> = []; - - constructor({ - limit = 100, - }: { - limit?: number; - } = {}) { - super({ limit }); - this.retrieveAll = async (): Promise<Array<Visit>> => { - let visits: Array<Visit>; - try { - visits = this.visits; - } catch { - visits = []; - } - return visits; - }; - this.persistAll = async (visits: Array<Visit>) => { - this.visits = visits; - }; - } -} - -describe('new MemoryVisitsApi()', () => { - const mockRandomUUID = () => - '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( - /x/g, - () => Math.floor(Math.random() * 16).toString(16), // 0x0 to 0xf - ) as `${string}-${string}-${string}-${string}-${string}`; - - beforeEach(() => { - jest.useFakeTimers(); - window.crypto.randomUUID = mockRandomUUID; - }); - - afterEach(() => { - jest.resetAllMocks(); - jest.useRealTimers(); - window.localStorage.clear(); - }); - - it('instantiates with no configuration', () => { - const api = new MemoryVisitsApi(); - expect(api).toBeTruthy(); - }); - - describe('.save()', () => { - it('saves a visit', async () => { - const api = new MemoryVisitsApi(); - const visit = { - pathname: '/catalog/default/component/playback-order', - entityRef: 'component:default/playback-order', - name: 'Playback Order', - }; - const returnedVisit = await api.save({ visit }); - expect(returnedVisit).toEqual(expect.objectContaining(visit)); - expect(returnedVisit.id).toBeTruthy(); - expect(returnedVisit.timestamp).toBeTruthy(); - expect(returnedVisit.hits).toBeTruthy(); - }); - - it('can control the number of stored entities', async () => { - const api = new MemoryVisitsApi({ limit: 2 }); - const baseDate = Date.now(); - const visit1 = { - pathname: '/catalog/default/component/playback-order-1', - entityRef: 'component:default/playback-order', - name: 'Playback Order', - }; - jest.setSystemTime(baseDate); - await api.save({ visit: visit1 }); - const visit2 = { - pathname: '/catalog/default/component/playback-order-2', - entityRef: 'component:default/playback-order', - name: 'Playback Order', - }; - jest.setSystemTime(baseDate + 360_000); - await api.save({ visit: visit2 }); - const visit3 = { - pathname: '/catalog/default/component/playback-order-3', - entityRef: 'component:default/playback-order', - name: 'Playback Order', - }; - jest.setSystemTime(baseDate + 360_000 * 2); - await api.save({ visit: visit3 }); - const visits = await api.list(); - expect(visits).toHaveLength(2); - expect(visits).toContainEqual(expect.objectContaining(visit2)); - expect(visits).toContainEqual(expect.objectContaining(visit3)); - }); - - it('correctly bumps the hits from a previous visit', async () => { - const api = new MemoryVisitsApi(); - const visit = { - pathname: '/catalog/default/component/playback-order', - entityRef: 'component:default/playback-order', - name: 'Playback Order', - }; - const visit1 = await api.save({ visit }); - const visit2 = await api.save({ visit }); - const visits = await api.list(); - expect(visits).toHaveLength(1); - expect(visits).toContainEqual(expect.objectContaining(visit)); - // keeps the original id created on the first visit - expect(visits).toContainEqual(expect.objectContaining({ id: visit1.id })); - // updates timestamp and hits - expect(visits).toContainEqual( - expect.objectContaining({ timestamp: visit2.timestamp, hits: 2 }), - ); - }); - }); - - describe('.list()', () => { - let api: MemoryVisitsApi; - let visitsToSave: Array<Omit<Visit, 'id' | 'hits' | 'timestamp'>>; - let baseDate: number; - beforeEach(() => { - api = new MemoryVisitsApi(); - visitsToSave = [ - { - pathname: '/catalog/default/component/playback-order-1', - entityRef: 'component:default/playback-order-1', - name: 'Playback Order Odd', - }, - { - pathname: '/catalog/default/component/playback-order-2', - entityRef: 'component:default/playback-order-2', - name: 'Playback Order Even', - }, - { - pathname: '/catalog/default/component/playback-order-3', - entityRef: 'component:default/playback-order-3', - name: 'Playback Order Odd', - }, - ]; - baseDate = Date.now(); - // Chaining items to ensure the right setSystemTime - return visitsToSave.reduce( - (acc, visit, index) => - acc.then(() => { - jest.setSystemTime(baseDate + 360_000 * index); - return api.save({ visit }); - }), - Promise.resolve({}), - ); - }); - - it('retrieves visits', async () => { - const visits = await api.list(); - expect(visits).toHaveLength(3); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[2]), - expect.objectContaining(visitsToSave[1]), - expect.objectContaining(visitsToSave[0]), - ]); - }); - - it('orders by timestamp asc', async () => { - const visits = await api.list({ - orderBy: [{ field: 'timestamp', direction: 'asc' }], - }); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[0]), - expect.objectContaining(visitsToSave[1]), - expect.objectContaining(visitsToSave[2]), - ]); - }); - - it('orders by timestamp desc', async () => { - const visits = await api.list({ - orderBy: [{ field: 'timestamp', direction: 'desc' }], - }); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[2]), - expect.objectContaining(visitsToSave[1]), - expect.objectContaining(visitsToSave[0]), - ]); - }); - - it('orders by entityRef asc', async () => { - const visits = await api.list({ - orderBy: [{ field: 'entityRef', direction: 'asc' }], - }); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[0]), - expect.objectContaining(visitsToSave[1]), - expect.objectContaining(visitsToSave[2]), - ]); - }); - - it('orders by entityRef desc', async () => { - const visits = await api.list({ - orderBy: [{ field: 'entityRef', direction: 'desc' }], - }); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[2]), - expect.objectContaining(visitsToSave[1]), - expect.objectContaining(visitsToSave[0]), - ]); - }); - - it('orders by name asc then by entityRef asc', async () => { - const visits = await api.list({ - orderBy: [ - { field: 'name', direction: 'asc' }, - { field: 'entityRef', direction: 'asc' }, - ], - }); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[1]), // Playback Order Even, playback-order-2 - expect.objectContaining(visitsToSave[0]), // Playback Order Odd, playback-order-1 - expect.objectContaining(visitsToSave[2]), // Playback Order Odd, playback-order-3 - ]); - }); - - it('orders by name desc then by entityRef asc', async () => { - const visits = await api.list({ - orderBy: [ - { field: 'name', direction: 'desc' }, - { field: 'entityRef', direction: 'asc' }, - ], - }); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[0]), // Playback Order Odd, playback-order-1 - expect.objectContaining(visitsToSave[2]), // Playback Order Odd, playback-order-3 - expect.objectContaining(visitsToSave[1]), // Playback Order Even, playback-order-2 - ]); - }); - - it('filters by timestamp with >', async () => { - const visits = await api.list({ - filterBy: [{ field: 'timestamp', operator: '>', value: baseDate }], - }); - expect(visits).toHaveLength(2); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[2]), - expect.objectContaining(visitsToSave[1]), - ]); - }); - - it('filters by timestamp with >=', async () => { - const visits = await api.list({ - filterBy: [ - { field: 'timestamp', operator: '>=', value: baseDate + 360_000 * 2 }, - ], - }); - expect(visits).toHaveLength(1); - expect(visits).toEqual([expect.objectContaining(visitsToSave[2])]); - }); - - it('filters by timestamp with <', async () => { - const visits = await api.list({ - filterBy: [{ field: 'timestamp', operator: '<', value: baseDate + 1 }], - }); - expect(visits).toHaveLength(1); - expect(visits).toEqual([expect.objectContaining(visitsToSave[0])]); - }); - - it('filters by timestamp with <=', async () => { - const visits = await api.list({ - filterBy: [ - { field: 'timestamp', operator: '<=', value: baseDate + 360_000 }, - ], - }); - expect(visits).toHaveLength(2); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[1]), - expect.objectContaining(visitsToSave[0]), - ]); - }); - - it('filters by timestamp with ==', async () => { - const visits = await api.list({ - filterBy: [ - { field: 'timestamp', operator: '==', value: baseDate + 360_000 }, - ], - }); - expect(visits).toHaveLength(1); - expect(visits).toEqual([expect.objectContaining(visitsToSave[1])]); - }); - - it('filters by timestamp with !=', async () => { - const visits = await api.list({ - filterBy: [ - { field: 'timestamp', operator: '!=', value: baseDate + 360_000 }, - ], - }); - expect(visits).toHaveLength(2); - expect(visits).toEqual([ - expect.objectContaining(visitsToSave[2]), - expect.objectContaining(visitsToSave[0]), - ]); - }); - - it('filters by entityRef with contains', async () => { - const visits = await api.list({ - filterBy: [ - { field: 'entityRef', operator: 'contains', value: 'order-2' }, - ], - }); - expect(visits).toHaveLength(1); - expect(visits).toEqual([expect.objectContaining(visitsToSave[1])]); - }); - - it('filters by timestamp with <= then by name with contains', async () => { - const visits = await api.list({ - filterBy: [ - { field: 'timestamp', operator: '<=', value: baseDate + 360_000 }, - { field: 'name', operator: 'contains', value: 'Odd' }, - ], - }); - expect(visits).toHaveLength(1); - expect(visits).toEqual([expect.objectContaining(visitsToSave[0])]); - }); - }); -}); diff --git a/plugins/home/src/api/VisitsApiFactory.ts b/plugins/home/src/api/VisitsApiFactory.ts deleted file mode 100644 index 9ba6a2fe79..0000000000 --- a/plugins/home/src/api/VisitsApiFactory.ts +++ /dev/null @@ -1,120 +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 { - Visit, - VisitsApi, - VisitsApiQueryParams, - VisitsApiSaveParams, -} from './VisitsApi'; - -type ArrayElement<A> = A extends readonly (infer T)[] ? T : never; - -/** @public */ -export type VisitsApiFactoryOptions = { - limit: number; - retrieveAll?: () => Promise<Array<Visit>>; - persistAll?: (visits: Array<Visit>) => Promise<void>; -}; - -/** - * @public - * This helps the creation of VisitApi implementations. Important to note - * that it implements features like orderBy and filterBy on memory, therefore - * is intended to handle few visits. The default is 100. - * See LocalStorageVisitsApi for an usage example. - */ -export class VisitsApiFactory implements VisitsApi { - protected readonly randomUUID = window.crypto.randomUUID; - protected readonly limit: number; - protected retrieveAll: () => Promise<Array<Visit>>; - protected persistAll: (visits: Array<Visit>) => Promise<void>; - - protected constructor(options: VisitsApiFactoryOptions) { - this.limit = Math.abs(options.limit ?? 100); - this.retrieveAll = options.retrieveAll ?? (async () => []); - this.persistAll = options.persistAll ?? (async () => {}); - } - - async list(queryParams?: VisitsApiQueryParams): Promise<Visit[]> { - let visits = await this.retrieveAll(); - - // reversing order to guarantee orderBy priority - (queryParams?.orderBy ?? []).reverse().forEach(order => { - if (order.direction === 'asc') { - visits.sort((a, b) => this.compare(order, a, b)); - } else { - visits.sort((a, b) => this.compare(order, b, a)); - } - }); - - // reversing order to guarantee filterBy priority - (queryParams?.filterBy ?? []).reverse().forEach(filter => { - visits = visits.filter(visit => { - const field = visit[filter.field] as number | string; - if (filter.operator === '>') return field > filter.value; - if (filter.operator === '>=') return field >= filter.value; - if (filter.operator === '<') return field < filter.value; - if (filter.operator === '<=') return field <= filter.value; - if (filter.operator === '==') return field === filter.value; - if (filter.operator === '!=') return field !== filter.value; - if (filter.operator === 'contains') - return `${field}`.includes(`${filter.value}`); - return false; - }); - }); - - return visits; - } - - async save(saveParams: VisitsApiSaveParams): Promise<Visit> { - const visits = await this.retrieveAll(); - - const visit: Visit = { - ...saveParams.visit, - id: window.crypto.randomUUID(), - hits: 1, - timestamp: Date.now(), - }; - - // Updates entry if pathname is already registered - const visitIndex = visits.findIndex(e => e.pathname === visit.pathname); - if (visitIndex >= 0) { - visit.id = visits[visitIndex].id; - visit.hits = visits[visitIndex].hits + 1; - visits[visitIndex] = visit; - } else { - visits.push(visit); - } - - // Sort by time, most recent first - visits.sort((a, b) => b.timestamp - a.timestamp); - // Keep the most recent items up to limit - await this.persistAll(visits.splice(0, this.limit)); - return visit; - } - - // This assumes Visit fields are either numbers or strings - private compare( - order: ArrayElement<VisitsApiQueryParams['orderBy']>, - a: Visit, - b: Visit, - ): number { - const isNumber = typeof a[order.field] === 'number'; - return isNumber - ? (a[order.field] as number) - (b[order.field] as number) - : `${a[order.field]}`.localeCompare(`${b[order.field]}`); - } -} diff --git a/plugins/home/src/api/index.ts b/plugins/home/src/api/index.ts index cb283aa2cf..50b48e3204 100644 --- a/plugins/home/src/api/index.ts +++ b/plugins/home/src/api/index.ts @@ -17,4 +17,3 @@ export * from './CoreStorageVisitsApi'; export * from './LocalStorageVisitsApi'; export * from './VisitsApi'; -export * from './VisitsApiFactory'; From 5514040b44b1a2c623668e5b42e87e2739169475 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Wed, 20 Sep 2023 14:16:48 +0200 Subject: [PATCH 171/207] rename(plugins/home): VisitsStorageApi and VisitsWebStorageApi Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> Co-authored-by: Avantika Iyer <chick157@gmail.com> --- plugins/home/README.md | 14 ++--- plugins/home/api-report.md | 56 +++++++++---------- ...tsApi.test.ts => VisitsStorageApi.test.ts} | 14 ++--- ...torageVisitsApi.ts => VisitsStorageApi.ts} | 13 ++--- ...pi.test.ts => VisitsWebStorageApi.test.ts} | 10 ++-- ...ageVisitsApi.ts => VisitsWebStorageApi.ts} | 10 ++-- plugins/home/src/api/index.ts | 4 +- plugins/home/src/plugin.ts | 4 +- 8 files changed, 62 insertions(+), 63 deletions(-) rename plugins/home/src/api/{CoreStorageVisitsApi.test.ts => VisitsStorageApi.test.ts} (97%) rename plugins/home/src/api/{CoreStorageVisitsApi.ts => VisitsStorageApi.ts} (92%) rename plugins/home/src/api/{LocalStorageVisitsApi.test.ts => VisitsWebStorageApi.test.ts} (91%) rename plugins/home/src/api/{LocalStorageVisitsApi.ts => VisitsWebStorageApi.ts} (81%) diff --git a/plugins/home/README.md b/plugins/home/README.md index af3b3a12f6..d70667e886 100644 --- a/plugins/home/README.md +++ b/plugins/home/README.md @@ -274,8 +274,8 @@ documentation for more information. Bellow you can see an example for two option // packages/app/src/apis.ts // ... import { - CoreStorageVisitsApi, - LocalStoreVisitsApi, + VisitsStorageApi, + VisitsWebStorageApi, visitsApiRef, } from '@backstage/plugin-home'; // ... @@ -288,17 +288,17 @@ export const apis: AnyApiFactory[] = [ identityApi: identityApiRef, }, factory: ({ storageApi, identityApi }) => - CoreStorageVisitsApi.create({ storageApi, identityApi }), + VisitsStorageApi.create({ storageApi, identityApi }), }), - // Or a local data implementation, relies on WebStorage implementation of storageApi + // Or a localStorage data implementation, relies on WebStorage implementation of storageApi createApiFactory({ api: visitsApiRef, deps: { identityApi: identityApiRef, errorApi: errorApiRef }, - factory: ({ identityApi, errorApi }) => LocalStoreVisitsApi.create({ identityApi, errorApi }), + factory: ({ identityApi, errorApi }) => VisitsWebStorageApi.create({ identityApi, errorApi }), }), // ... ``` @@ -308,14 +308,14 @@ See the example usage: ```ts // packages/app/src/App.tsx -import { VisitsListener } from '@backstage/plugin-home'; +import { VisitListener } from '@backstage/plugin-home'; // ... export default app.createRoot( <> <AlertDisplay /> <OAuthRequestDialog /> <AppRouter> - <VisitsListener /> + <VisitListener /> <Root>{routes}</Root> </AppRouter> </>, diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 5da8f912a5..e3f789c2af 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -77,21 +77,6 @@ export const ComponentTabs: (props: { }[]; }) => JSX_2.Element; -// @public -export class CoreStorageVisitsApi implements VisitsApi { - // (undocumented) - static create(options: CoreStorageVisitsApiOptions): CoreStorageVisitsApi; - list(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; - save(saveParams: VisitsApiSaveParams): Promise<Visit>; -} - -// @public (undocumented) -export type CoreStorageVisitsApiOptions = { - limit?: number; - storageApi: StorageApi; - identityApi: IdentityApi; -}; - // @public @deprecated (undocumented) export const createCardExtension: typeof createCardExtension_2; @@ -179,19 +164,6 @@ export type LayoutConfiguration = { resizable?: boolean; }; -// @public -export class LocalStorageVisitsApi { - // (undocumented) - static create(options: LocalStorageVisitsApiOptions): CoreStorageVisitsApi; -} - -// @public (undocumented) -export type LocalStorageVisitsApiOptions = { - limit?: number; - identityApi: IdentityApi; - errorApi: ErrorApi; -}; - // @public @deprecated (undocumented) export type RendererProps = RendererProps_2; @@ -289,6 +261,34 @@ export type VisitsApiSaveParams = { visit: Omit<Visit, 'id' | 'hits' | 'timestamp'>; }; +// @public +export class VisitsStorageApi implements VisitsApi { + // (undocumented) + static create(options: VisitsStorageApiOptions): VisitsStorageApi; + list(queryParams?: VisitsApiQueryParams): Promise<Visit[]>; + save(saveParams: VisitsApiSaveParams): Promise<Visit>; +} + +// @public (undocumented) +export type VisitsStorageApiOptions = { + limit?: number; + storageApi: StorageApi; + identityApi: IdentityApi; +}; + +// @public +export class VisitsWebStorageApi { + // (undocumented) + static create(options: VisitsWebStorageApiOptions): VisitsStorageApi; +} + +// @public (undocumented) +export type VisitsWebStorageApiOptions = { + limit?: number; + identityApi: IdentityApi; + errorApi: ErrorApi; +}; + // @public export const WelcomeTitle: ({ language, diff --git a/plugins/home/src/api/CoreStorageVisitsApi.test.ts b/plugins/home/src/api/VisitsStorageApi.test.ts similarity index 97% rename from plugins/home/src/api/CoreStorageVisitsApi.test.ts rename to plugins/home/src/api/VisitsStorageApi.test.ts index 9118b2546b..6faeb62350 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.test.ts +++ b/plugins/home/src/api/VisitsStorageApi.test.ts @@ -15,11 +15,11 @@ */ import { BackstageUserIdentity, IdentityApi } from '@backstage/core-plugin-api'; -import { CoreStorageVisitsApi } from './CoreStorageVisitsApi'; +import { VisitsStorageApi } from './VisitsStorageApi'; import { MockStorageApi } from '@backstage/test-utils'; import { Visit, VisitsApi } from './VisitsApi'; -describe('CoreStorageVisitsApi.create', () => { +describe('VisitsStorageApi.create', () => { const mockRandomUUID = () => '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( /x/g, @@ -46,7 +46,7 @@ describe('CoreStorageVisitsApi.create', () => { }); it('instantiates', () => { - const api = CoreStorageVisitsApi.create({ + const api = VisitsStorageApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); @@ -55,7 +55,7 @@ describe('CoreStorageVisitsApi.create', () => { describe('.save()', () => { it('saves a visit', async () => { - const api = CoreStorageVisitsApi.create({ + const api = VisitsStorageApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); @@ -72,7 +72,7 @@ describe('CoreStorageVisitsApi.create', () => { }); it('can control the number of stored entities', async () => { - const api = CoreStorageVisitsApi.create({ + const api = VisitsStorageApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, limit: 2, @@ -106,7 +106,7 @@ describe('CoreStorageVisitsApi.create', () => { }); it('correctly bumps the hits from a previous visit', async () => { - const api = CoreStorageVisitsApi.create({ + const api = VisitsStorageApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); @@ -135,7 +135,7 @@ describe('CoreStorageVisitsApi.create', () => { let baseDate: number; beforeEach(() => { - api = CoreStorageVisitsApi.create({ + api = VisitsStorageApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); diff --git a/plugins/home/src/api/CoreStorageVisitsApi.ts b/plugins/home/src/api/VisitsStorageApi.ts similarity index 92% rename from plugins/home/src/api/CoreStorageVisitsApi.ts rename to plugins/home/src/api/VisitsStorageApi.ts index 2707a50b87..daf24d716b 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.ts +++ b/plugins/home/src/api/VisitsStorageApi.ts @@ -22,7 +22,7 @@ import { } from './VisitsApi'; /** @public */ -export type CoreStorageVisitsApiOptions = { +export type VisitsStorageApiOptions = { limit?: number; storageApi: StorageApi; identityApi: IdentityApi; @@ -36,18 +36,17 @@ type ArrayElement<A> = A extends readonly (infer T)[] ? T : never; * Beware that filtering and ordering are done in memory therefore it is * prudent to keep limit to a reasonable size. */ -export class CoreStorageVisitsApi implements VisitsApi { - private readonly randomUUID = window.crypto.randomUUID; +export class VisitsStorageApi implements VisitsApi { private readonly limit: number; private readonly storageApi: StorageApi; private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; private readonly identityApi: IdentityApi; - static create(options: CoreStorageVisitsApiOptions) { - return new CoreStorageVisitsApi(options); + static create(options: VisitsStorageApiOptions) { + return new VisitsStorageApi(options); } - private constructor(options: CoreStorageVisitsApiOptions) { + private constructor(options: VisitsStorageApiOptions) { this.limit = Math.abs(options.limit ?? 100); this.storageApi = options.storageApi; this.identityApi = options.identityApi; @@ -95,7 +94,7 @@ export class CoreStorageVisitsApi implements VisitsApi { const visit: Visit = { ...saveParams.visit, - id: this.randomUUID(), + id: window.crypto.randomUUID(), hits: 1, timestamp: Date.now(), }; diff --git a/plugins/home/src/api/LocalStorageVisitsApi.test.ts b/plugins/home/src/api/VisitsWebStorageApi.test.ts similarity index 91% rename from plugins/home/src/api/LocalStorageVisitsApi.test.ts rename to plugins/home/src/api/VisitsWebStorageApi.test.ts index b646af209e..1cf1fa3129 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.test.ts +++ b/plugins/home/src/api/VisitsWebStorageApi.test.ts @@ -15,9 +15,9 @@ */ import { BackstageUserIdentity, IdentityApi } from '@backstage/core-plugin-api'; -import { LocalStorageVisitsApi } from './LocalStorageVisitsApi'; +import { VisitsWebStorageApi } from './VisitsWebStorageApi'; -describe('LocalStorageVisitsApi.create()', () => { +describe('VisitsWebStorageApi.create()', () => { const mockRandomUUID = () => '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( /x/g, @@ -44,7 +44,7 @@ describe('LocalStorageVisitsApi.create()', () => { }); it('instantiates with only identitiyApi', () => { - const api = LocalStorageVisitsApi.create({ + const api = VisitsWebStorageApi.create({ identityApi: mockIdentityApi, errorApi: mockErrorApi, }); @@ -52,7 +52,7 @@ describe('LocalStorageVisitsApi.create()', () => { }); it('saves a visit', async () => { - const api = LocalStorageVisitsApi.create({ + const api = VisitsWebStorageApi.create({ identityApi: mockIdentityApi, errorApi: mockErrorApi, }); @@ -69,7 +69,7 @@ describe('LocalStorageVisitsApi.create()', () => { }); it('retrieves visits', async () => { - const api = LocalStorageVisitsApi.create({ + const api = VisitsWebStorageApi.create({ identityApi: mockIdentityApi, errorApi: mockErrorApi, }); diff --git a/plugins/home/src/api/LocalStorageVisitsApi.ts b/plugins/home/src/api/VisitsWebStorageApi.ts similarity index 81% rename from plugins/home/src/api/LocalStorageVisitsApi.ts rename to plugins/home/src/api/VisitsWebStorageApi.ts index 01d57b93d9..56b3ae53c5 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.ts +++ b/plugins/home/src/api/VisitsWebStorageApi.ts @@ -14,11 +14,11 @@ * limitations under the License. */ import { ErrorApi, IdentityApi } from '@backstage/core-plugin-api'; -import { CoreStorageVisitsApi } from './CoreStorageVisitsApi'; +import { VisitsStorageApi } from './VisitsStorageApi'; import { WebStorage } from '@backstage/core-app-api'; /** @public */ -export type LocalStorageVisitsApiOptions = { +export type VisitsWebStorageApiOptions = { limit?: number; identityApi: IdentityApi; errorApi: ErrorApi; @@ -28,9 +28,9 @@ export type LocalStorageVisitsApiOptions = { * @public * This is a reference implementation of VisitsApi using WebStorage. */ -export class LocalStorageVisitsApi { - static create(options: LocalStorageVisitsApiOptions) { - return CoreStorageVisitsApi.create({ +export class VisitsWebStorageApi { + static create(options: VisitsWebStorageApiOptions) { + return VisitsStorageApi.create({ limit: options.limit, identityApi: options.identityApi, storageApi: WebStorage.create({ errorApi: options.errorApi }), diff --git a/plugins/home/src/api/index.ts b/plugins/home/src/api/index.ts index 50b48e3204..944fa65330 100644 --- a/plugins/home/src/api/index.ts +++ b/plugins/home/src/api/index.ts @@ -14,6 +14,6 @@ * limitations under the License. */ -export * from './CoreStorageVisitsApi'; -export * from './LocalStorageVisitsApi'; +export * from './VisitsStorageApi'; +export * from './VisitsWebStorageApi'; export * from './VisitsApi'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index 3bbfd9d544..d4ed401c86 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -25,7 +25,7 @@ import { import { createCardExtension } from '@backstage/plugin-home-react'; import { ToolkitContentProps, VisitedByTypeProps } from './homePageComponents'; import { rootRouteRef } from './routes'; -import { CoreStorageVisitsApi, visitsApiRef } from './api'; +import { VisitsStorageApi, visitsApiRef } from './api'; /** @public */ export const homePlugin = createPlugin({ @@ -38,7 +38,7 @@ export const homePlugin = createPlugin({ identityApi: identityApiRef, }, factory: ({ storageApi, identityApi }) => - CoreStorageVisitsApi.create({ storageApi, identityApi }), + VisitsStorageApi.create({ storageApi, identityApi }), }), ], routes: { From f4cb351de2928bad337559520fa28aa6776c6592 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Thu, 21 Sep 2023 13:39:52 +0200 Subject: [PATCH 172/207] fix(plugins/home): Get name for catalog entities fallback to title Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/src/components/VisitListener.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/home/src/components/VisitListener.tsx b/plugins/home/src/components/VisitListener.tsx index 4a7900a63a..4cddd307c5 100644 --- a/plugins/home/src/components/VisitListener.tsx +++ b/plugins/home/src/components/VisitListener.tsx @@ -57,7 +57,16 @@ const getToEntityRef = * for receiving a pathname and returning a string (name). The default * implementation ignores the pathname and uses the document.title . */ -export const getVisitName = (document: Document) => () => document.title; +export const getVisitName = + ({ rootPath = 'catalog', document = global.document } = {}) => + ({ pathname }: { pathname: string }) => { + const regex = new RegExp( + `^\/${rootPath}\/(?<namespace>[^\/]+)\/(?<kind>[^\/]+)\/(?<name>[^\/]+)`, + ); + const result = regex.exec(pathname); + if (result && result?.groups) return result.groups.name; + return document.title; + }; /** * @public @@ -76,7 +85,7 @@ export const VisitListener = ({ const visitsApi = useApi(visitsApiRef); const { pathname } = useLocation(); const toEntityRefImpl = toEntityRef ?? getToEntityRef(); - const visitNameImpl = visitName ?? getVisitName(document); + const visitNameImpl = visitName ?? getVisitName(); useEffect(() => { // Wait for the browser to finish with paint with the assumption react // has finished with dom reconciliation. From 7a8b0b4cf376842e6fc9cce25147d53b3fb9dc31 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Fri, 22 Sep 2023 09:49:38 +0200 Subject: [PATCH 173/207] refactoring(plugins/home): Separate TopVisited and RecentlyVisited This patch separates the two components to be easier to import them in the customizable homepage. Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/README.md | 13 +++++---- plugins/home/api-report.md | 17 +++++++++--- .../HomePageVisitedByType.stories.tsx | 11 +++++++- .../VisitedByType/RecentlyVisited.tsx | 27 +++++++++++++++++++ .../VisitedByType/TopVisited.tsx | 27 +++++++++++++++++++ plugins/home/src/index.ts | 3 ++- plugins/home/src/plugin.ts | 22 +++++++++++---- 7 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 plugins/home/src/homePageComponents/VisitedByType/RecentlyVisited.tsx create mode 100644 plugins/home/src/homePageComponents/VisitedByType/TopVisited.tsx diff --git a/plugins/home/README.md b/plugins/home/README.md index d70667e886..d41ae57162 100644 --- a/plugins/home/README.md +++ b/plugins/home/README.md @@ -242,24 +242,27 @@ const defaultConfig = [ <CustomHomepageGrid config={defaultConfig}> ``` -## Page visit homepage component (HomePageVisitedByType) +## Page visit homepage component (HomePageTopVisited / HomePageRecentlyVisited) This component shows the homepage user a view for "Recently visited" or "Top visited". -Being provided by the `<HomePageVisitedByType/>` component, see it in use on a homepage example below: +Being provided by the `<HomePageTopVisited/>` and `<HomePageRecentlyVisited/>` component, see it in use on a homepage example below: ```tsx // packages/app/src/components/home/HomePage.tsx import React from 'react'; import Grid from '@material-ui/core/Grid'; -import { HomePageVisitedByType } from '@backstage/plugin-home'; +import { + HomePageTopVisited, + HomePageRecentlyVisited, +} from '@backstage/plugin-home'; export const homePage = ( <Grid container spacing={3}> <Grid item xs={12} md={4}> - <HomePageVisitedByType kind="top" /> + <HomePageTopVisited /> </Grid> <Grid item xs={12} md={4}> - <HomePageVisitedByType kind="recent" /> + <HomePageRecentlyVisited /> </Grid> </Grid> ); diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index e3f789c2af..8b43f59811 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -102,7 +102,13 @@ export type CustomHomepageGridProps = { }; // @public -export const getVisitName: (document: Document) => () => string; +export const getVisitName: ({ + rootPath, + document, +}?: { + rootPath?: string | undefined; + document?: Document | undefined; +}) => ({ pathname }: { pathname: string }) => string; // @public export const HeaderWorldClock: (props: { @@ -129,6 +135,11 @@ export const HomePageRandomJoke: ( }>, ) => JSX_2.Element; +// @public +export const HomePageRecentlyVisited: ( + props: CardExtensionProps_2<Partial<VisitedByTypeProps>>, +) => JSX_2.Element; + // @public export const HomePageStarredEntities: ( props: CardExtensionProps_2<unknown>, @@ -140,8 +151,8 @@ export const HomePageToolkit: ( ) => JSX_2.Element; // @public -export const HomePageVisitedByType: ( - props: CardExtensionProps_2<VisitedByTypeProps>, +export const HomePageTopVisited: ( + props: CardExtensionProps_2<Partial<VisitedByTypeProps>>, ) => JSX_2.Element; // @public (undocumented) diff --git a/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx b/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx index 19861bf58e..d20d5344ae 100644 --- a/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx +++ b/plugins/home/src/homePageComponents/VisitedByType/HomePageVisitedByType.stories.tsx @@ -18,8 +18,10 @@ import React from 'react'; import { TestApiProvider, wrapInTestApp } from '@backstage/test-utils'; import { ComponentType, PropsWithChildren } from 'react'; import { Grid } from '@material-ui/core'; -import { HomePageVisitedByType } from '../../plugin'; +import { homePlugin } from '../../plugin'; import { Visit, visitsApiRef } from '../../api/VisitsApi'; +import { createCardExtension } from '@backstage/plugin-home-react'; +import { VisitedByTypeProps } from './Content'; const visits: Array<Visit> = [ { @@ -86,6 +88,13 @@ const visits: Array<Visit> = [ }, ]; +const HomePageVisitedByType = homePlugin.provide( + createCardExtension<VisitedByTypeProps>({ + name: 'HomePageTopVisited', + components: () => import('./'), + }), +); + const mockVisitsApi = { save: async () => visits[0], list: async () => visits, diff --git a/plugins/home/src/homePageComponents/VisitedByType/RecentlyVisited.tsx b/plugins/home/src/homePageComponents/VisitedByType/RecentlyVisited.tsx new file mode 100644 index 0000000000..a6896f4e91 --- /dev/null +++ b/plugins/home/src/homePageComponents/VisitedByType/RecentlyVisited.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. + */ + +export { Actions } from './Actions'; +export { ContextProvider } from './Context'; +export type { VisitedByTypeProps, VisitedByTypeKind } from './Content'; +import React from 'react'; +import { Content, VisitedByTypeProps } from './Content'; + +const RecentlyVisitedContent = (props: Partial<VisitedByTypeProps>) => ( + <Content {...props} kind="recent" /> +); + +export { RecentlyVisitedContent as Content }; diff --git a/plugins/home/src/homePageComponents/VisitedByType/TopVisited.tsx b/plugins/home/src/homePageComponents/VisitedByType/TopVisited.tsx new file mode 100644 index 0000000000..5a326abf51 --- /dev/null +++ b/plugins/home/src/homePageComponents/VisitedByType/TopVisited.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. + */ + +export { Actions } from './Actions'; +export { ContextProvider } from './Context'; +export type { VisitedByTypeProps, VisitedByTypeKind } from './Content'; +import React from 'react'; +import { Content, VisitedByTypeProps } from './Content'; + +const TopVisitedContent = (props: Partial<VisitedByTypeProps>) => ( + <Content {...props} kind="top" /> +); + +export { TopVisitedContent as Content }; diff --git a/plugins/home/src/index.ts b/plugins/home/src/index.ts index c60883d749..a80f8bd93d 100644 --- a/plugins/home/src/index.ts +++ b/plugins/home/src/index.ts @@ -32,7 +32,8 @@ export { ComponentTab, WelcomeTitle, HeaderWorldClock, - HomePageVisitedByType, + HomePageTopVisited, + HomePageRecentlyVisited, } from './plugin'; export * from './components'; export * from './assets'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index d4ed401c86..ab8c46baa1 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -189,12 +189,24 @@ export const HeaderWorldClock = homePlugin.provide( ); /** - * Display recently/top visited pages for the homepage + * Display top visited pages for the homepage * @public */ -export const HomePageVisitedByType = homePlugin.provide( - createCardExtension<VisitedByTypeProps>({ - name: 'HomePageVisitedByType', - components: () => import('./homePageComponents/VisitedByType'), +export const HomePageTopVisited = homePlugin.provide( + createCardExtension<Partial<VisitedByTypeProps>>({ + name: 'HomePageTopVisited', + components: () => import('./homePageComponents/VisitedByType/TopVisited'), + }), +); + +/** + * Display recently visited pages for the homepage + * @public + */ +export const HomePageRecentlyVisited = homePlugin.provide( + createCardExtension<Partial<VisitedByTypeProps>>({ + name: 'HomePageRecentlyVisited', + components: () => + import('./homePageComponents/VisitedByType/RecentlyVisited'), }), ); From 14db0dd105d3db5051132b51ab489ba3fed632a4 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Fri, 22 Sep 2023 09:51:14 +0200 Subject: [PATCH 174/207] feature(plugins/home): Improves title resolution Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- plugins/home/src/components/VisitListener.test.tsx | 7 ++----- plugins/home/src/components/VisitListener.tsx | 12 +++++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/plugins/home/src/components/VisitListener.test.tsx b/plugins/home/src/components/VisitListener.test.tsx index 7a0ce57de5..72c530071a 100644 --- a/plugins/home/src/components/VisitListener.test.tsx +++ b/plugins/home/src/components/VisitListener.test.tsx @@ -53,7 +53,6 @@ describe('<VisitListener/>', () => { afterEach(jest.resetAllMocks); it('registers a visit', async () => { - jest.spyOn(document, 'title', 'get').mockReturnValue('MockedTitle'); const pathname = '/catalog/default/component/playback-order'; await renderInTestApp( @@ -68,7 +67,7 @@ describe('<VisitListener/>', () => { visit: { pathname, entityRef: 'component:default/playback-order', - name: 'MockedTitle', + name: 'playback-order', }, }); }); @@ -86,7 +85,6 @@ describe('<VisitListener/>', () => { }); it('is able to override how visit names are defined', async () => { - jest.spyOn(document, 'title', 'get').mockReturnValue('MockedTitle'); const pathname = '/catalog/default/component/playback-order'; const visitNameOverride = ({ pathname: path }: { pathname: string }) => @@ -111,7 +109,6 @@ describe('<VisitListener/>', () => { }); it('is able to override how entityRefs are defined', async () => { - jest.spyOn(document, 'title', 'get').mockReturnValue('MockedTitle'); const pathname = '/catalog/default/component/playback-order'; const toEntityRefOverride = ({ pathname: path }: { pathname: string }) => @@ -129,7 +126,7 @@ describe('<VisitListener/>', () => { visit: { pathname, entityRef: pathname, - name: 'MockedTitle', + name: 'playback-order', }, }), ); diff --git a/plugins/home/src/components/VisitListener.tsx b/plugins/home/src/components/VisitListener.tsx index 4cddd307c5..de7d16e44f 100644 --- a/plugins/home/src/components/VisitListener.tsx +++ b/plugins/home/src/components/VisitListener.tsx @@ -54,17 +54,23 @@ const getToEntityRef = /** * @public * This function returns an implementation of visitName which is responsible - * for receiving a pathname and returning a string (name). The default - * implementation ignores the pathname and uses the document.title . + * for receiving a pathname and returning a string (name). */ export const getVisitName = ({ rootPath = 'catalog', document = global.document } = {}) => ({ pathname }: { pathname: string }) => { + // If it is a catalog entity, get the name from the path const regex = new RegExp( `^\/${rootPath}\/(?<namespace>[^\/]+)\/(?<kind>[^\/]+)\/(?<name>[^\/]+)`, ); - const result = regex.exec(pathname); + let result = regex.exec(pathname); if (result && result?.groups) return result.groups.name; + + // If it is a root pathname, get the name from there + result = /^\/(?<name>[^\/]+)$/.exec(pathname); + if (result && result?.groups) return result.groups.name; + + // Fallback to document title return document.title; }; From 0c927cab64f0306659c57271cbf70c791900db07 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho <aitherios@gmail.com> Date: Fri, 22 Sep 2023 09:53:02 +0200 Subject: [PATCH 175/207] feature(app): Adds TopVisited and RecentlyVisited to homepage This patch adds TopVisited and RecentlyVisited to the homepage example accessible in http://localhost:3000/home when running yarn dev Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com> --- packages/app/src/App.tsx | 3 ++- packages/app/src/components/home/HomePage.tsx | 4 ++++ packages/app/src/plugins.ts | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index a0a6419328..f2b7d66b21 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -61,7 +61,7 @@ import { import { orgPlugin } from '@backstage/plugin-org'; import { ExplorePage } from '@backstage/plugin-explore'; import { GcpProjectsPage } from '@backstage/plugin-gcp-projects'; -import { HomepageCompositionRoot } from '@backstage/plugin-home'; +import { HomepageCompositionRoot, VisitListener } from '@backstage/plugin-home'; import { LighthousePage } from '@backstage/plugin-lighthouse'; import { NewRelicPage } from '@backstage/plugin-newrelic'; import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha'; @@ -330,6 +330,7 @@ export default app.createRoot( <AlertDisplay transientTimeoutMs={2500} /> <OAuthRequestDialog /> <AppRouter> + <VisitListener /> <Root extensionTree={extensionTree}>{routes}</Root> </AppRouter> </>, diff --git a/packages/app/src/components/home/HomePage.tsx b/packages/app/src/components/home/HomePage.tsx index a8ddc0e0e2..5940b0ac6c 100644 --- a/packages/app/src/components/home/HomePage.tsx +++ b/packages/app/src/components/home/HomePage.tsx @@ -22,6 +22,8 @@ import { HomePageRandomJoke, HomePageStarredEntities, HomePageToolkit, + HomePageTopVisited, + HomePageRecentlyVisited, WelcomeTitle, } from '@backstage/plugin-home'; import { Content, Header, Page } from '@backstage/core-components'; @@ -111,6 +113,8 @@ export const homePage = ( }, ]} /> + <HomePageTopVisited /> + <HomePageRecentlyVisited /> </CustomHomepageGrid> </Content> </Page> diff --git a/packages/app/src/plugins.ts b/packages/app/src/plugins.ts index a1e952a07c..36f7a86acc 100644 --- a/packages/app/src/plugins.ts +++ b/packages/app/src/plugins.ts @@ -18,3 +18,4 @@ // ideally we have an API for the context menu that permits that. export { badgesPlugin } from '@backstage/plugin-badges'; export { shortcutsPlugin } from '@backstage/plugin-shortcuts'; +export { homePlugin } from '@backstage/plugin-home'; From d65cb238e8a661c05a11f9c66740e419a8d61384 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Mon, 2 Oct 2023 13:24:22 +0200 Subject: [PATCH 176/207] fix(home): changeset version Signed-off-by: Camila Belo <camilaibs@gmail.com> --- .changeset/happy-books-smoke.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/happy-books-smoke.md b/.changeset/happy-books-smoke.md index b035f84cfd..68ea19ea5e 100644 --- a/.changeset/happy-books-smoke.md +++ b/.changeset/happy-books-smoke.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-home': minor +'@backstage/plugin-home': patch --- Adds Top/Recently Visited components to homepage From e10a5eaae54540fa148ffb5234aca33d6c5e9342 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Mon, 2 Oct 2023 13:25:43 +0200 Subject: [PATCH 177/207] fix(home): annotate `getVisitName` as internal utility Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/home/api-report.md | 9 --------- plugins/home/src/components/VisitListener.tsx | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 8b43f59811..14f685cfc1 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -101,15 +101,6 @@ export type CustomHomepageGridProps = { preventCollision?: boolean; }; -// @public -export const getVisitName: ({ - rootPath, - document, -}?: { - rootPath?: string | undefined; - document?: Document | undefined; -}) => ({ pathname }: { pathname: string }) => string; - // @public export const HeaderWorldClock: (props: { clockConfigs: ClockConfig[]; diff --git a/plugins/home/src/components/VisitListener.tsx b/plugins/home/src/components/VisitListener.tsx index de7d16e44f..866fd69885 100644 --- a/plugins/home/src/components/VisitListener.tsx +++ b/plugins/home/src/components/VisitListener.tsx @@ -52,11 +52,11 @@ const getToEntityRef = }; /** - * @public + * @internal * This function returns an implementation of visitName which is responsible * for receiving a pathname and returning a string (name). */ -export const getVisitName = +const getVisitName = ({ rootPath = 'catalog', document = global.document } = {}) => ({ pathname }: { pathname: string }) => { // If it is a catalog entity, get the name from the path From ad97403fcac6a2dbdf419f07ba15196ce79bdde7 Mon Sep 17 00:00:00 2001 From: vdizengremel <victor.dizengremel@octo.com> Date: Mon, 2 Oct 2023 11:24:16 +0200 Subject: [PATCH 178/207] fix(#20232): refacto test to facilitate maintenance and the add of new cases Signed-off-by: vdizengremel <victor.dizengremel@octo.com> --- .../OwnershipCard/useGetEntities.test.ts | 105 ++++++++++-------- 1 file changed, 61 insertions(+), 44 deletions(-) diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts index 4b9389a7d4..27a6ef96ba 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts @@ -53,30 +53,19 @@ const catalogApiMock: Pick<CatalogApi, 'getEntities' | 'getEntitiesByRefs'> = { jest.mock('@backstage/core-plugin-api', () => ({ useApi: jest.fn(() => catalogApiMock), })); -jest.mock('@backstage/plugin-catalog-react', () => ({ - catalogApiRef: {}, - getEntityRelations: jest.fn(entity => { - if (entity?.metadata.name === givenParentGroup) { - return [ - { - kind: 'Group', - namespace: 'default', - name: givenLeafGroup, - } as CompoundEntityRef, - ]; - } else if (entity?.kind === 'User') { - return [ - { - kind: 'Group', - namespace: 'default', - name: givenLeafGroup, - } as CompoundEntityRef, - ]; - } - return []; - }) as typeof getEntityRelations, -})); +const getEntityRelationsMock: jest.Mock< + CompoundEntityRef[], + [Entity | undefined] +> = jest.fn(); +jest.mock('@backstage/plugin-catalog-react', () => { + return { + catalogApiRef: {}, + getEntityRelations: jest.fn(entity => { + return getEntityRelationsMock(entity); + }) as typeof getEntityRelations, + }; +}); describe('useGetEntities', () => { const ownersFilter = (...owners: string[]) => @@ -100,32 +89,60 @@ describe('useGetEntities', () => { await hook.waitForNextUpdate(); }; - it('given group entity should aggregate child ownership', async () => { - await whenHookIsCalledWith(givenParentGroupEntity); - expect(catalogApiMock.getEntities).toHaveBeenCalledWith( - ownersFilter( - `group:default/${givenParentGroup}`, - `group:default/${givenLeafGroup}`, - ), - ); + afterEach(() => { + getEntityRelationsMock.mockRestore(); }); - it('given group entity should retrieve child with their relations', async () => { - await whenHookIsCalledWith(givenParentGroupEntity); - expect(catalogApiMock.getEntitiesByRefs).toHaveBeenCalledWith({ - entityRefs: [`group:default/${givenLeafGroup}`], - fields: ['kind', 'metadata.namespace', 'metadata.name', 'relations'], + describe('when given entity is a group', () => { + beforeEach(() => { + getEntityRelationsMock + .mockReturnValueOnce([ + { + kind: 'Group', + namespace: 'default', + name: givenLeafGroup, + } as CompoundEntityRef, + ]) + .mockReturnValue([]); + }); + + it('should aggregate child ownership', async () => { + await whenHookIsCalledWith(givenParentGroupEntity); + expect(catalogApiMock.getEntities).toHaveBeenCalledWith( + ownersFilter( + `group:default/${givenParentGroup}`, + `group:default/${givenLeafGroup}`, + ), + ); + }); + + it('should retrieve child with their relations', async () => { + await whenHookIsCalledWith(givenParentGroupEntity); + expect(catalogApiMock.getEntitiesByRefs).toHaveBeenCalledWith({ + entityRefs: [`group:default/${givenLeafGroup}`], + fields: ['kind', 'metadata.namespace', 'metadata.name', 'relations'], + }); }); }); - it('given user entity should aggregate parent ownership and direct', async () => { - await whenHookIsCalledWith(givenUserEntity); - expect(catalogApiMock.getEntities).toHaveBeenCalledWith( - ownersFilter( - `group:default/${givenLeafGroup}`, - `user:default/${givenUser}`, - ), - ); + describe('when given entity is a user', () => { + it('should aggregate parent ownership and direct', async () => { + getEntityRelationsMock.mockReturnValue([ + { + kind: 'Group', + namespace: 'default', + name: givenLeafGroup, + } as CompoundEntityRef, + ]); + + await whenHookIsCalledWith(givenUserEntity); + expect(catalogApiMock.getEntities).toHaveBeenCalledWith( + ownersFilter( + `group:default/${givenLeafGroup}`, + `user:default/${givenUser}`, + ), + ); + }); }); }); From 88fa5516c30bbaaf73f2befad6edb105ec748161 Mon Sep 17 00:00:00 2001 From: vdizengremel <victor.dizengremel@octo.com> Date: Mon, 2 Oct 2023 12:22:10 +0200 Subject: [PATCH 179/207] fix(#20232): handle intermediate groups Signed-off-by: vdizengremel <victor.dizengremel@octo.com> --- plugins/org/package.json | 1 + .../OwnershipCard/useGetEntities.test.ts | 97 +++++++++++++++---- .../Cards/OwnershipCard/useGetEntities.ts | 27 +++--- yarn.lock | 1 + 4 files changed, 92 insertions(+), 34 deletions(-) diff --git a/plugins/org/package.json b/plugins/org/package.json index 7d931c4797..c68352b579 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -39,6 +39,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@types/react": "^16.13.1 || ^17.0.0", + "lodash": "^4.17.21", "p-limit": "^3.1.0", "pluralize": "^8.0.0", "qs": "^6.10.1", diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts index 27a6ef96ba..189aa4db30 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts @@ -22,18 +22,8 @@ import { getEntityRelations } from '@backstage/plugin-catalog-react'; const givenParentGroup = 'team.squad1'; const givenLeafGroup = 'team.squad2'; const givenUser = 'user.john'; -const givenParentGroupEntity = { - kind: 'Group', - metadata: { - name: givenParentGroup, - }, -} as Partial<Entity> as Entity; -const givenLeafGroupEntity = { - kind: 'Group', - metadata: { - name: givenLeafGroup, - }, -} as Partial<Entity> as Entity; +const givenParentGroupEntity = createGroupEntityFromName(givenParentGroup); +const givenLeafGroupEntity = createGroupEntityFromName(givenLeafGroup); const givenUserEntity = { kind: 'User', metadata: { @@ -41,13 +31,10 @@ const givenUserEntity = { }, } as Partial<Entity> as Entity; +const getEntitiesByRefsMock = jest.fn(); const catalogApiMock: Pick<CatalogApi, 'getEntities' | 'getEntitiesByRefs'> = { getEntities: jest.fn(async () => Promise.resolve({ items: [] })), - getEntitiesByRefs: jest.fn(async ({ entityRefs: [ref] }) => - ref.includes(givenParentGroup) - ? { items: [givenParentGroupEntity] } - : { items: [givenLeafGroupEntity] }, - ), + getEntitiesByRefs: getEntitiesByRefsMock, }; jest.mock('@backstage/core-plugin-api', () => ({ @@ -72,7 +59,7 @@ describe('useGetEntities', () => { expect.objectContaining({ filter: expect.arrayContaining([ expect.objectContaining({ - 'relations.ownedBy': owners, + 'relations.ownedBy': expect.arrayContaining(owners), }), ]), }); @@ -89,8 +76,17 @@ describe('useGetEntities', () => { await hook.waitForNextUpdate(); }; + beforeEach(() => { + getEntitiesByRefsMock.mockImplementation(async ({ entityRefs: [ref] }) => + ref.includes(givenParentGroup) + ? { items: [givenParentGroupEntity] } + : { items: [givenLeafGroupEntity] }, + ); + }); + afterEach(() => { getEntityRelationsMock.mockRestore(); + getEntitiesByRefsMock.mockRestore(); }); describe('when given entity is a group', () => { @@ -123,6 +119,62 @@ describe('useGetEntities', () => { fields: ['kind', 'metadata.namespace', 'metadata.name', 'relations'], }); }); + + it('should retrieve entities owned by any children', async () => { + const givenIntermediateGroup = 'intermediate-group'; + const givenIntermediateGroupEntity = createGroupEntityFromName( + givenIntermediateGroup, + ); + + getEntitiesByRefsMock.mockRestore(); + getEntitiesByRefsMock.mockImplementation( + async ({ entityRefs: [ref] }) => { + if (ref.includes(givenParentGroup)) { + return { items: [givenParentGroupEntity] }; + } + + if (ref.includes(givenIntermediateGroup)) { + return { items: [givenIntermediateGroupEntity] }; + } + + return { items: [givenLeafGroupEntity] }; + }, + ); + + getEntityRelationsMock.mockRestore(); + getEntityRelationsMock.mockImplementation(entity => { + if (entity?.metadata.name === givenParentGroup) { + return [ + { + kind: 'Group', + namespace: 'default', + name: givenIntermediateGroup, + }, + ]; + } + + if (entity?.metadata.name === givenIntermediateGroup) { + return [ + { + kind: 'Group', + namespace: 'default', + name: givenLeafGroup, + }, + ]; + } + + return []; + }); + + await whenHookIsCalledWith(givenParentGroupEntity); + expect(catalogApiMock.getEntities).toHaveBeenCalledWith( + ownersFilter( + `group:default/${givenParentGroup}`, + `group:default/${givenIntermediateGroup}`, + `group:default/${givenLeafGroup}`, + ), + ); + }); }); describe('when given entity is a user', () => { @@ -173,3 +225,12 @@ describe('useGetEntities', () => { }); }); }); + +function createGroupEntityFromName(name: String): Entity { + return { + kind: 'Group', + metadata: { + name: name, + }, + } as Partial<Entity> as Entity; +} diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts index 337e926971..cc2bb78a23 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts @@ -16,9 +16,9 @@ import { Entity, + parseEntityRef, RELATION_MEMBER_OF, RELATION_PARENT_OF, - parseEntityRef, stringifyEntityRef, } from '@backstage/catalog-model'; import { @@ -32,6 +32,7 @@ import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; import qs from 'qs'; import { EntityRelationAggregation as EntityRelationsAggregation } from './types'; +import { uniq } from 'lodash'; const limiter = limiterFactory(10); @@ -95,7 +96,7 @@ const getChildOwnershipEntityRefs = async ( }); const childGroupEntities = childGroupResponse.items.filter(isEntity); - return ( + const childrenRefs = ( await Promise.all( childGroupEntities.map(childGroupEntity => limiter(() => @@ -104,6 +105,8 @@ const getChildOwnershipEntityRefs = async ( ), ) ).flatMap(aggregated => aggregated); + + return uniq([...childrenRefs, stringifyEntityRef(entity)]); } return [stringifyEntityRef(entity)]; @@ -118,23 +121,15 @@ const getOwners = async ( const isAggregated = relations === 'aggregated'; const isUserEntity = entity.kind === 'User'; - const owners: string[] = []; - if (isAggregated && isGroup) { - const childEntityRefs = await getChildOwnershipEntityRefs( - entity, - catalogApi, - ); - owners.push(stringifyEntityRef(entity)); - owners.push.apply(owners, childEntityRefs); - } else if (isAggregated && isUserEntity) { - const parentEntityRefs = getMemberOfEntityRefs(entity); - owners.push.apply(owners, parentEntityRefs); - } else { - owners.push(stringifyEntityRef(entity)); + return getChildOwnershipEntityRefs(entity, catalogApi); } - return owners; + if (isAggregated && isUserEntity) { + return getMemberOfEntityRefs(entity); + } + + return [stringifyEntityRef(entity)]; }; const getOwnedEntitiesByOwners = ( diff --git a/yarn.lock b/yarn.lock index 02c4184f9c..a4c817ce7f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8139,6 +8139,7 @@ __metadata: "@testing-library/react-hooks": ^8.0.1 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 + lodash: ^4.17.21 msw: ^1.0.0 p-limit: ^3.1.0 pluralize: ^8.0.0 From ca3ab66bbeb93ff2cd39bea8b99f2260b916316f Mon Sep 17 00:00:00 2001 From: vdizengremel <victor.dizengremel@octo.com> Date: Mon, 2 Oct 2023 14:09:27 +0200 Subject: [PATCH 180/207] fix(#20232): handle circular relation Signed-off-by: vdizengremel <victor.dizengremel@octo.com> --- .../OwnershipCard/useGetEntities.test.ts | 131 ++++++++++-------- .../Cards/OwnershipCard/useGetEntities.ts | 19 ++- 2 files changed, 88 insertions(+), 62 deletions(-) diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts index 189aa4db30..587dc689e3 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts @@ -92,13 +92,7 @@ describe('useGetEntities', () => { describe('when given entity is a group', () => { beforeEach(() => { getEntityRelationsMock - .mockReturnValueOnce([ - { - kind: 'Group', - namespace: 'default', - name: givenLeafGroup, - } as CompoundEntityRef, - ]) + .mockReturnValueOnce([createGroupRefFromName(givenLeafGroup)]) .mockReturnValue([]); }); @@ -120,71 +114,84 @@ describe('useGetEntities', () => { }); }); - it('should retrieve entities owned by any children', async () => { + describe('when relations are deep (children of children)', () => { const givenIntermediateGroup = 'intermediate-group'; const givenIntermediateGroupEntity = createGroupEntityFromName( givenIntermediateGroup, ); - getEntitiesByRefsMock.mockRestore(); - getEntitiesByRefsMock.mockImplementation( - async ({ entityRefs: [ref] }) => { - if (ref.includes(givenParentGroup)) { - return { items: [givenParentGroupEntity] }; - } + beforeEach(() => { + getEntitiesByRefsMock.mockRestore(); + getEntitiesByRefsMock.mockImplementation( + async ({ entityRefs: [ref] }) => { + if (ref.includes(givenParentGroup)) { + return { items: [givenParentGroupEntity] }; + } - if (ref.includes(givenIntermediateGroup)) { - return { items: [givenIntermediateGroupEntity] }; - } + if (ref.includes(givenIntermediateGroup)) { + return { items: [givenIntermediateGroupEntity] }; + } - return { items: [givenLeafGroupEntity] }; - }, - ); - - getEntityRelationsMock.mockRestore(); - getEntityRelationsMock.mockImplementation(entity => { - if (entity?.metadata.name === givenParentGroup) { - return [ - { - kind: 'Group', - namespace: 'default', - name: givenIntermediateGroup, - }, - ]; - } - - if (entity?.metadata.name === givenIntermediateGroup) { - return [ - { - kind: 'Group', - namespace: 'default', - name: givenLeafGroup, - }, - ]; - } - - return []; + return { items: [givenLeafGroupEntity] }; + }, + ); }); - await whenHookIsCalledWith(givenParentGroupEntity); - expect(catalogApiMock.getEntities).toHaveBeenCalledWith( - ownersFilter( - `group:default/${givenParentGroup}`, - `group:default/${givenIntermediateGroup}`, - `group:default/${givenLeafGroup}`, - ), - ); + it('should retrieve entities owned by any children', async () => { + getEntityRelationsMock.mockRestore(); + getEntityRelationsMock.mockImplementation(entity => { + if (entity?.metadata.name === givenParentGroup) { + return [createGroupRefFromName(givenIntermediateGroup)]; + } + + if (entity?.metadata.name === givenIntermediateGroup) { + return [createGroupRefFromName(givenLeafGroup)]; + } + + return []; + }); + + await whenHookIsCalledWith(givenParentGroupEntity); + expect(catalogApiMock.getEntities).toHaveBeenCalledWith( + ownersFilter( + `group:default/${givenParentGroup}`, + `group:default/${givenIntermediateGroup}`, + `group:default/${givenLeafGroup}`, + ), + ); + }); + + it('should retrieve entities owned by any children when circular relation', async () => { + getEntityRelationsMock.mockRestore(); + getEntityRelationsMock.mockImplementation(entity => { + if (entity?.metadata.name === givenParentGroup) { + return [createGroupRefFromName(givenIntermediateGroup)]; + } + + if (entity?.metadata.name === givenIntermediateGroup) { + return [createGroupRefFromName(givenLeafGroup)]; + } + + // returns parent by default so givenLeafGroup will have the givenParentGroup as child + return [createGroupRefFromName(givenParentGroup)]; + }); + + await whenHookIsCalledWith(givenParentGroupEntity); + expect(catalogApiMock.getEntities).toHaveBeenCalledWith( + ownersFilter( + `group:default/${givenParentGroup}`, + `group:default/${givenIntermediateGroup}`, + `group:default/${givenLeafGroup}`, + ), + ); + }); }); }); describe('when given entity is a user', () => { it('should aggregate parent ownership and direct', async () => { getEntityRelationsMock.mockReturnValue([ - { - kind: 'Group', - namespace: 'default', - name: givenLeafGroup, - } as CompoundEntityRef, + createGroupRefFromName(givenLeafGroup), ]); await whenHookIsCalledWith(givenUserEntity); @@ -226,7 +233,7 @@ describe('useGetEntities', () => { }); }); -function createGroupEntityFromName(name: String): Entity { +function createGroupEntityFromName(name: string): Entity { return { kind: 'Group', metadata: { @@ -234,3 +241,11 @@ function createGroupEntityFromName(name: String): Entity { }, } as Partial<Entity> as Entity; } + +function createGroupRefFromName(name: string): CompoundEntityRef { + return { + kind: 'Group', + namespace: 'default', + name: name, + }; +} diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts index cc2bb78a23..b6fa9cbfd1 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts @@ -81,6 +81,7 @@ const isEntity = (entity: Entity | undefined): entity is Entity => const getChildOwnershipEntityRefs = async ( entity: Entity, catalogApi: CatalogApi, + alreadyRetrievedParentRefs: string[] = [], ): Promise<string[]> => { const childGroups = getEntityRelations(entity, RELATION_PARENT_OF, { kind: 'Group', @@ -88,6 +89,7 @@ const getChildOwnershipEntityRefs = async ( const hasChildGroups = childGroups.length > 0; + const entityRef = stringifyEntityRef(entity); if (hasChildGroups) { const entityRefs = childGroups.map(r => stringifyEntityRef(r)); const childGroupResponse = await catalogApi.getEntitiesByRefs({ @@ -96,20 +98,29 @@ const getChildOwnershipEntityRefs = async ( }); const childGroupEntities = childGroupResponse.items.filter(isEntity); + const unknownChildren = childGroupEntities.filter( + childGroupEntity => + !alreadyRetrievedParentRefs.includes( + stringifyEntityRef(childGroupEntity), + ), + ); const childrenRefs = ( await Promise.all( - childGroupEntities.map(childGroupEntity => + unknownChildren.map(childGroupEntity => limiter(() => - getChildOwnershipEntityRefs(childGroupEntity, catalogApi), + getChildOwnershipEntityRefs(childGroupEntity, catalogApi, [ + ...alreadyRetrievedParentRefs, + entityRef, + ]), ), ), ) ).flatMap(aggregated => aggregated); - return uniq([...childrenRefs, stringifyEntityRef(entity)]); + return uniq([...childrenRefs, entityRef]); } - return [stringifyEntityRef(entity)]; + return [entityRef]; }; const getOwners = async ( From ee31c4224e2d99bb6f2a13f9264e55630e8127c9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Mon, 2 Oct 2023 14:13:46 +0200 Subject: [PATCH 181/207] e2e: update stderr filtering, only log filtered lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- packages/e2e-test/src/commands/run.ts | 50 ++++++++++++--------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/packages/e2e-test/src/commands/run.ts b/packages/e2e-test/src/commands/run.ts index cf95f6856d..5d373b24cf 100644 --- a/packages/e2e-test/src/commands/run.ts +++ b/packages/e2e-test/src/commands/run.ts @@ -443,41 +443,35 @@ async function testBackendStart(appDir: string, ...args: string[]) { }); let successful = false; - const stdErrorHasErrors = (input: string) => { + const filterStderr = (input: string) => { const lines = input.split('\n').filter(Boolean); - return ( - lines.filter( - l => - !l.includes('Use of deprecated folder mapping') && - !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)', - ) && - !l.includes('Custom ESM Loaders is an experimental feature') && - !l.includes( - 'ExperimentalWarning: `globalPreload` is planned for removal', - ), - ).length !== 0 + return lines.filter( + l => + !l.includes( + 'ExperimentalWarning: Custom ESM Loaders is an experimental feature', // Node 16 + ) && + !l.includes( + 'ExperimentalWarning: `--experimental-loader` may be removed in the future;', // Node 18 + ) && + !l.includes("--import 'data:text/javascript,import") && // the new --experimental-loader replacement warning, printed after the above, Node 18 + !l.includes( + 'ExperimentalWarning: `globalPreload` is planned for removal in favor of `initialize`.', // Node 18 + ) && + !l.includes('node --trace-warnings ...'), ); }; try { await waitFor( - () => stdout.includes('Listening on ') || stdErrorHasErrors(stderr), + () => stdout.includes('Listening on ') || filterStderr(stderr).length > 0, ); - if (stdErrorHasErrors(stderr)) { - print(`Expected stderr to be clean, got ${stderr}`); + const stderrLines = filterStderr(stderr); + if (stderrLines.length > 0) { + print( + `Expected stderr to be clean, got ${stderr} \n\nThe following lines were unexpected:\n${stderrLines.join( + '\n', + )}`, + ); // Skipping the whole block throw new Error(stderr); } From 8e15e6a0f7d5d2914397098fc174b5863d6b1734 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey <aramiss@spotify.com> Date: Mon, 2 Oct 2023 09:55:30 -0400 Subject: [PATCH 182/207] update organization for sennyeya Signed-off-by: Aramis Sennyey <aramiss@spotify.com> --- OWNERS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OWNERS.md b/OWNERS.md index 4d09c29f0f..000a3e2444 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -114,7 +114,7 @@ Scope: Tooling for frontend and backend schema-first OpenAPI development. | Name | Organization | GitHub | Discord | | -------------- | ------------ | --------------------------------------- | ------------- | -| Aramis Sennyey | | [sennyeya](https://github.com/sennyeya) | `Aramis#7984` | +| Aramis Sennyey | Spotify | [sennyeya](https://github.com/sennyeya) | `Aramis#7984` | ## Sponsors @@ -132,7 +132,7 @@ Scope: Tooling for frontend and backend schema-first OpenAPI development. | Alex Crome | | [afscrome](https://github.com/afscrome) | `afscrome` | | Andre Wanlin | Keyloop | [awanlin](https://github.com/awanlin) | `ahhhndre` | | Andrew Thauer | Wealthsimple | [andrewthauer](https://github.com/andrewthauer) | `andrewthauer#3060` | -| Aramis Sennyey | | [sennyeya](https://github.com/sennyeya) | `Aramis#7984` | +| Aramis Sennyey | Spotify | [sennyeya](https://github.com/sennyeya) | `Aramis#7984` | | Brian Fletcher | Roadie.io | [punkle](https://github.com/punkle) | `Brian Fletcher#7051` | | Carlos Esteban Lopez Jaramillo | VMWare | [luchillo17](https://github.com/luchillo17) | `luchillo17#8777` | | David Tuite | Roadie.io | [dtuite](https://github.com/dtuite) | `David Tuite (roadie.io)#1010` | From 7ec10602ff6a35c1e7d2c302f2cc87897a2a5dc9 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino <vincenzos@spotify.com> Date: Mon, 2 Oct 2023 16:58:17 +0200 Subject: [PATCH 183/207] catalog-backend-module-github: fix defaultUserTransformer typings Signed-off-by: Vincenzo Scamporlino <vincenzos@spotify.com> --- docs/integrations/github/org.md | 7 +------ plugins/catalog-backend-module-github/api-report.md | 6 +++++- .../src/lib/defaultTransformers.ts | 5 +++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/integrations/github/org.md b/docs/integrations/github/org.md index 8d640e714e..1404b20559 100644 --- a/docs/integrations/github/org.md +++ b/docs/integrations/github/org.md @@ -270,12 +270,7 @@ const githubOrgProvider = GithubOrgEntityProvider.fromConfig(env.config, { /* highlight-add-start */ userTransformer: async (user, ctx) => { const entity = await defaultUserTransformer(user, ctx); - if ( - entity && - isUserEntity(entity) && - entity.spec.profile && - user.organizationVerifiedDomainEmails?.length - ) { + if (entity && user.organizationVerifiedDomainEmails?.length) { entity.spec.profile!.email = user.organizationVerifiedDomainEmails[0]; } return entity; diff --git a/plugins/catalog-backend-module-github/api-report.md b/plugins/catalog-backend-module-github/api-report.md index 12ab6d35e7..4c44f95b61 100644 --- a/plugins/catalog-backend-module-github/api-report.md +++ b/plugins/catalog-backend-module-github/api-report.md @@ -24,12 +24,16 @@ import { ScmIntegrationRegistry } from '@backstage/integration'; import { ScmLocationAnalyzer } from '@backstage/plugin-catalog-backend'; import { TaskRunner } from '@backstage/backend-tasks'; import { TokenManager } from '@backstage/backend-common'; +import { UserEntity } from '@backstage/catalog-model'; // @public export const defaultOrganizationTeamTransformer: TeamTransformer; // @public -export const defaultUserTransformer: UserTransformer; +export const defaultUserTransformer: ( + item: GithubUser, + _ctx: TransformerContext, +) => Promise<UserEntity | undefined>; // @public export class GithubDiscoveryProcessor implements CatalogProcessor { diff --git a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts index 71613d88d2..6befd32056 100644 --- a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts +++ b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts @@ -58,9 +58,10 @@ export type TeamTransformer = ( * * @public */ -export const defaultUserTransformer: UserTransformer = async ( +export const defaultUserTransformer = async ( item: GithubUser, -) => { + _ctx: TransformerContext, +): Promise<UserEntity | undefined> => { const entity: UserEntity = { apiVersion: 'backstage.io/v1alpha1', kind: 'User', From b94f32271e77246354852d8e6b417d4ea861f052 Mon Sep 17 00:00:00 2001 From: Mike Spiegel <mspiegel31@gmail.com> Date: Thu, 28 Sep 2023 15:47:58 -0400 Subject: [PATCH 184/207] support fetching tags Signed-off-by: Mike Spiegel <mspiegel31@gmail.com> --- .changeset/itchy-bobcats-fly.md | 5 +++++ packages/backend-common/api-report.md | 6 +++++- packages/backend-common/src/scm/git.test.ts | 4 +++- packages/backend-common/src/scm/git.ts | 9 +++++++-- 4 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 .changeset/itchy-bobcats-fly.md diff --git a/.changeset/itchy-bobcats-fly.md b/.changeset/itchy-bobcats-fly.md new file mode 100644 index 0000000000..e91d944478 --- /dev/null +++ b/.changeset/itchy-bobcats-fly.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index ab640ccd9b..36cb225a27 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -377,7 +377,11 @@ export class Git { }): Promise<string | undefined>; // (undocumented) deleteRemote(options: { dir: string; remote: string }): Promise<void>; - fetch(options: { dir: string; remote?: string }): Promise<void>; + fetch(options: { + dir: string; + remote?: string; + tags?: boolean; + }): Promise<void>; // (undocumented) static fromAuth: (options: { username?: string; diff --git a/packages/backend-common/src/scm/git.test.ts b/packages/backend-common/src/scm/git.test.ts index 629173f96e..5ec960fc53 100644 --- a/packages/backend-common/src/scm/git.test.ts +++ b/packages/backend-common/src/scm/git.test.ts @@ -264,13 +264,14 @@ describe('Git', () => { }; const git = Git.fromAuth(auth); - await git.fetch({ remote, dir }); + await git.fetch({ remote, dir, tags: true }); expect(isomorphic.fetch).toHaveBeenCalledWith({ fs, http, remote, dir, + tags: true, onProgress: expect.any(Function), headers: { 'user-agent': 'git/@isomorphic-git', @@ -294,6 +295,7 @@ describe('Git', () => { http, remote, dir, + tags: false, onProgress: expect.any(Function), headers: { Authorization: 'Bearer test', diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 234ae57d30..8ccdbeafbd 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -160,8 +160,12 @@ export class Git { } /** https://isomorphic-git.org/docs/en/fetch */ - async fetch(options: { dir: string; remote?: string }): Promise<void> { - const { dir, remote = 'origin' } = options; + async fetch(options: { + dir: string; + remote?: string; + tags?: boolean; + }): Promise<void> { + const { dir, remote = 'origin', tags = false } = options; this.config.logger?.info( `Fetching remote=${remote} for repository {dir=${dir}}`, ); @@ -172,6 +176,7 @@ export class Git { http, dir, remote, + tags, onProgress: this.onProgressHandler(), headers: this.headers, onAuth: this.onAuth, From a426ef77a5e126b43e055c9adf6d586f61178012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Mon, 4 Sep 2023 13:41:48 +0200 Subject: [PATCH 185/207] fix tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../components/CatalogGraphPage/CatalogGraphPage.test.tsx | 5 +---- plugins/gocd/src/components/Select/Select.test.tsx | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx index 17bec9a475..3d99c83966 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx @@ -194,10 +194,7 @@ describe('<CatalogGraphPage/>', () => { }, ); - expect(await screen.findAllByTestId('node')).toHaveLength(2); - - // We wait a bit here to reliably reproduce an issue where that requires the `baseVal` and `view` mocks - await new Promise(r => setTimeout(r, 100)); + await expect(screen.findAllByTestId('node')).resolves.toHaveLength(2); await userEvent.click(screen.getByText('b:d/e')); diff --git a/plugins/gocd/src/components/Select/Select.test.tsx b/plugins/gocd/src/components/Select/Select.test.tsx index 9d73194ed8..c93b5dd148 100644 --- a/plugins/gocd/src/components/Select/Select.test.tsx +++ b/plugins/gocd/src/components/Select/Select.test.tsx @@ -66,7 +66,7 @@ describe('Select', () => { />, ); user.tab(); - userEvent.keyboard('{enter}'); + await userEvent.keyboard('{enter}'); expect(rendered.getAllByText(testItems[0].label)).toHaveLength(2); expect(rendered.getByText(testItems[1].label)).toBeInTheDocument(); From 689457efd348cea3714c07aa3806873bf0cd1e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Tue, 5 Sep 2023 21:08:24 +0200 Subject: [PATCH 186/207] fix test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../CatalogGraphPage.test.tsx | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx index 3d99c83966..2e215e75f9 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx @@ -111,14 +111,14 @@ describe('<CatalogGraphPage/>', () => { await renderInTestApp(wrapper, { mountedRoutes: { - '/entity/{kind}/{namespace}/{name}': entityRouteRef, + '/entity/:kind/:namespace/:name': entityRouteRef, }, }); expect(screen.getByText('Catalog Graph')).toBeInTheDocument(); - expect(await screen.findByText('b:d/c')).toBeInTheDocument(); - expect(await screen.findByText('b:d/e')).toBeInTheDocument(); - expect(await screen.findAllByTestId('node')).toHaveLength(2); + await expect(screen.findByText('b:d/c')).resolves.toBeInTheDocument(); + await expect(screen.findByText('b:d/e')).resolves.toBeInTheDocument(); + await expect(screen.findAllByTestId('node')).resolves.toHaveLength(2); expect(catalog.getEntityByRef).toHaveBeenCalledTimes(2); }); @@ -129,7 +129,7 @@ describe('<CatalogGraphPage/>', () => { await renderInTestApp(wrapper, { mountedRoutes: { - '/entity/{kind}/{namespace}/{name}': entityRouteRef, + '/entity/:kind/:namespace/:name': entityRouteRef, }, }); @@ -147,15 +147,15 @@ describe('<CatalogGraphPage/>', () => { await renderInTestApp(wrapper, { mountedRoutes: { - '/entity/{kind}/{namespace}/{name}': entityRouteRef, + '/entity/:kind/:namespace/:name': entityRouteRef, }, }); - expect(await screen.findAllByTestId('node')).toHaveLength(2); + await expect(screen.findAllByTestId('node')).resolves.toHaveLength(2); await userEvent.click(screen.getByText('b:d/e')); - expect(await screen.findByText('hasPart')).toBeInTheDocument(); + await expect(screen.findByText('hasPart')).resolves.toBeInTheDocument(); }); test('should navigate to entity', async () => { @@ -165,16 +165,16 @@ describe('<CatalogGraphPage/>', () => { await renderInTestApp(wrapper, { mountedRoutes: { - '/entity/{kind}/{namespace}/{name}': entityRouteRef, + '/entity/:kind/:namespace/:name': entityRouteRef, }, }); - expect(await screen.findAllByTestId('node')).toHaveLength(2); + await expect(screen.findAllByTestId('node')).resolves.toHaveLength(2); const user = userEvent.setup(); await user.keyboard('{Shift>}'); await user.click(screen.getByText('b:d/e')); - expect(navigate).toHaveBeenCalledWith('/entity/{kind}/{namespace}/{name}'); + expect(navigate).toHaveBeenCalledWith('/entity/b/d/e'); }); test('should capture analytics event when selecting other entity', async () => { @@ -189,7 +189,7 @@ describe('<CatalogGraphPage/>', () => { </TestApiProvider>, { mountedRoutes: { - '/entity/{kind}/{namespace}/{name}': entityRouteRef, + '/entity/:kind/:namespace/:name': entityRouteRef, }, }, ); @@ -216,12 +216,12 @@ describe('<CatalogGraphPage/>', () => { </TestApiProvider>, { mountedRoutes: { - '/entity/{kind}/{namespace}/{name}': entityRouteRef, + '/entity/:kind/:namespace/:name': entityRouteRef, }, }, ); - expect(await screen.findAllByTestId('node')).toHaveLength(2); + await expect(screen.findAllByTestId('node')).resolves.toHaveLength(2); const user = userEvent.setup(); await user.keyboard('{Shift>}'); @@ -231,7 +231,7 @@ describe('<CatalogGraphPage/>', () => { action: 'click', subject: 'b:d/e', attributes: { - to: '/entity/{kind}/{namespace}/{name}', + to: '/entity/b/d/e', }, }); }); From ddd76ac98d50945f30987860d7c89c5be1cb7e04 Mon Sep 17 00:00:00 2001 From: Alec Jacobs <cajacobs5401@gmail.com> Date: Fri, 29 Sep 2023 11:06:21 -0700 Subject: [PATCH 187/207] fix(backend-tasks): prevent immediately triggering tasks out of band Signed-off-by: Alec Jacobs <cajacobs5401@gmail.com> --- .changeset/nine-garlics-attend.md | 5 + .../src/tasks/TaskWorker.test.ts | 108 +++++++++++++++++- .../backend-tasks/src/tasks/TaskWorker.ts | 47 ++++---- 3 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 .changeset/nine-garlics-attend.md diff --git a/.changeset/nine-garlics-attend.md b/.changeset/nine-garlics-attend.md new file mode 100644 index 0000000000..a9cdac4a32 --- /dev/null +++ b/.changeset/nine-garlics-attend.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-tasks': patch +--- + +Fix bug where backend tasks that are defined with HumanDuration are immediately triggered on application startup diff --git a/packages/backend-tasks/src/tasks/TaskWorker.test.ts b/packages/backend-tasks/src/tasks/TaskWorker.test.ts index 3022f59060..4e1e6dc23b 100644 --- a/packages/backend-tasks/src/tasks/TaskWorker.test.ts +++ b/packages/backend-tasks/src/tasks/TaskWorker.test.ts @@ -16,7 +16,7 @@ import { getVoidLogger } from '@backstage/backend-common'; import { TestDatabases } from '@backstage/backend-test-utils'; -import { Duration } from 'luxon'; +import { Duration, DateTime } from 'luxon'; import waitForExpect from 'wait-for-expect'; import { migrateBackendTasks } from '../database/migrateBackendTasks'; import { DbTasksRow, DB_TASKS_TABLE } from '../database/tables'; @@ -338,7 +338,7 @@ describe('TaskWorker', () => { ); it.each(databases.eachSupportedId())( - 'next_run_start_at is always the min between schedule changes, %p', + 'next_run_start_at is always the min between schedule changes from cron frequency, %p', async databaseId => { const knex = await databases.init(databaseId); await migrateBackendTasks(knex); @@ -376,4 +376,108 @@ describe('TaskWorker', () => { await knex.destroy(); }, ); + + it.each(databases.eachSupportedId())( + 'next_run_start_at is always the min between schedule changes when using human duration frequency, %p', + async databaseId => { + const knex = await databases.init(databaseId); + await migrateBackendTasks(knex); + + const fn = jest.fn( + async () => new Promise<void>(resolve => setTimeout(resolve, 50)), + ); + + const initialSettings: TaskSettingsV2 = { + version: 2, + cadence: 'PT120M', + timeoutAfterDuration: 'PT1M', + }; + + const worker = new TaskWorker('task99', fn, knex, logger); + await worker.persistTask(initialSettings); + // replicate task running, sets next_run_start_at based on cadence + await worker.tryClaimTask('ticket', initialSettings); + await worker.tryReleaseTask('ticket', initialSettings); + + // grab initial row for comparisons later + const initialRow = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + + const settings: TaskSettingsV2 = { + ...initialSettings, + cadence: 'PT60M', + }; + await worker.persistTask(settings); + const row1 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + + expect( + new Date(row1.next_run_start_at) < + new Date(initialRow.next_run_start_at), + ).toBeTruthy(); // ensure that next start at is sooner than initial + expect(new Date(row1.next_run_start_at) > new Date()).toBeTruthy(); // ensure that next start at is later than now + + const settings2 = { + ...settings, + }; + await worker.persistTask(settings2); + const row2 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + + expect(row2.next_run_start_at).toStrictEqual(row1.next_run_start_at); + + await knex.destroy(); + }, + ); + + it.each(databases.eachSupportedId())( + 'next_run_start_at is always the min between schedule changes when using human duration frequency with initial start delay, %p', + async databaseId => { + const knex = await databases.init(databaseId); + await migrateBackendTasks(knex); + + const fn = jest.fn( + async () => new Promise<void>(resolve => setTimeout(resolve, 50)), + ); + + const initialSettings: TaskSettingsV2 = { + version: 2, + cadence: 'PT120M', + initialDelayDuration: 'PT2M', + timeoutAfterDuration: 'PT1M', + }; + + const worker = new TaskWorker('task99', fn, knex, logger); + await worker.persistTask(initialSettings); + // replicate task running, sets next_run_start_at based on cadence + await worker.tryClaimTask('ticket', initialSettings); + await worker.tryReleaseTask('ticket', initialSettings); + + // grab initial row for comparisons later + const initialRow = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + + const settings: TaskSettingsV2 = { + ...initialSettings, + cadence: 'PT60M', + }; + await worker.persistTask(settings); + const row1 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + + expect( + new Date(row1.next_run_start_at) < + new Date(initialRow.next_run_start_at), + ).toBeTruthy(); // ensure that next start at is sooner than initial + expect( + new Date(row1.next_run_start_at) > + DateTime.now().plus({ minutes: 3 }).toJSDate(), + ).toBeTruthy(); // ensure that next start at is later than initial delay start time since next run at should be an hour from now + + const settings2 = { + ...settings, + }; + await worker.persistTask(settings2); + const row2 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + + expect(row2.next_run_start_at).toStrictEqual(row1.next_run_start_at); + + await knex.destroy(); + }, + ); }); diff --git a/packages/backend-tasks/src/tasks/TaskWorker.ts b/packages/backend-tasks/src/tasks/TaskWorker.ts index c1007b4964..6e3a88410b 100644 --- a/packages/backend-tasks/src/tasks/TaskWorker.ts +++ b/packages/backend-tasks/src/tasks/TaskWorker.ts @@ -165,27 +165,26 @@ export class TaskWorker { const isCron = !settings?.cadence.startsWith('P'); - let startAt: Knex.Raw; + let startAt: Knex.Raw | undefined; + let nextStartAt: Knex.Raw | undefined; if (settings.initialDelayDuration) { startAt = nowPlus( Duration.fromISO(settings.initialDelayDuration), this.knex, ); - } else if (isCron) { + } + + if (isCron) { const time = new CronTime(settings.cadence) .sendAt() .minus({ seconds: 1 }) // immediately, if "* * * * * *" .toUTC(); - if (this.knex.client.config.client.includes('sqlite3')) { - startAt = this.knex.raw('datetime(?)', [time.toISO()]); - } else if (this.knex.client.config.client.includes('mysql')) { - startAt = this.knex.raw(`?`, [time.toSQL({ includeOffset: false })]); - } else { - startAt = this.knex.raw(`?`, [time.toISO()]); - } + nextStartAt = this.nextRunAtRaw(time); + startAt ||= nextStartAt; } else { - startAt = this.knex.fn.now(); + startAt ||= this.knex.fn.now(); + nextStartAt = nowPlus(Duration.fromISO(settings.cadence), this.knex); } this.logger.debug(`task: ${this.taskId} configured to run at: ${startAt}`); @@ -206,7 +205,12 @@ export class TaskWorker { settings_json: settingsJson, next_run_start_at: this.knex.raw( `CASE WHEN ?? < ?? THEN ?? ELSE ?? END`, - [startAt, 'next_run_start_at', startAt, 'next_run_start_at'], + [ + nextStartAt, + 'next_run_start_at', + nextStartAt, + 'next_run_start_at', + ], ), } : { @@ -214,9 +218,9 @@ export class TaskWorker { next_run_start_at: this.knex.raw( `CASE WHEN ?? < ?? THEN ?? ELSE ?? END`, [ - 'excluded.next_run_start_at', + nextStartAt, `${DB_TASKS_TABLE}.next_run_start_at`, - 'excluded.next_run_start_at', + nextStartAt, `${DB_TASKS_TABLE}.next_run_start_at`, ], ), @@ -308,13 +312,7 @@ export class TaskWorker { const time = new CronTime(settings.cadence).sendAt().toUTC(); this.logger.debug(`task: ${this.taskId} will next occur around ${time}`); - if (this.knex.client.config.client.includes('sqlite3')) { - nextRun = this.knex.raw('datetime(?)', [time.toISO()]); - } else if (this.knex.client.config.client.includes('mysql')) { - nextRun = this.knex.raw(`?`, [time.toSQL({ includeOffset: false })]); - } else { - nextRun = this.knex.raw(`?`, [time.toISO()]); - } + nextRun = this.nextRunAtRaw(time); } else { const dt = Duration.fromISO(settings.cadence).as('seconds'); this.logger.debug( @@ -351,4 +349,13 @@ export class TaskWorker { return rows === 1; } + + private nextRunAtRaw(time: DateTime): Knex.Raw { + if (this.knex.client.config.client.includes('sqlite3')) { + return this.knex.raw('datetime(?)', [time.toISO()]); + } else if (this.knex.client.config.client.includes('mysql')) { + return this.knex.raw(`?`, [time.toSQL({ includeOffset: false })]); + } + return this.knex.raw(`?`, [time.toISO()]); + } } From a285d5b6397b0fa9d6eda02273c5d77e2dafb826 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 08:46:33 +0200 Subject: [PATCH 188/207] feat(catalog): migrate search result item extension Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/catalog/package.json | 4 ++-- plugins/catalog/src/{alpha.ts => alpha.tsx} | 20 +++++++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) rename plugins/catalog/src/{alpha.ts => alpha.tsx} (75%) diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 4ef0db4910..8ae615ec36 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -10,13 +10,13 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", + "./alpha": "./src/alpha.tsx", "./package.json": "./package.json" }, "typesVersions": { "*": { "alpha": [ - "src/alpha.ts" + "src/alpha.tsx" ], "package.json": [ "package.json" diff --git a/plugins/catalog/src/alpha.ts b/plugins/catalog/src/alpha.tsx similarity index 75% rename from plugins/catalog/src/alpha.ts rename to plugins/catalog/src/alpha.tsx index 82e592d5b7..5e78a52f9b 100644 --- a/plugins/catalog/src/alpha.ts +++ b/plugins/catalog/src/alpha.tsx @@ -14,8 +14,6 @@ * limitations under the License. */ -export * from './translation'; - import { createApiFactory, discoveryApiRef, @@ -31,6 +29,7 @@ import { catalogApiRef, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; +import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; import { DefaultStarredEntitiesApi } from './apis'; /** @alpha */ @@ -55,8 +54,23 @@ export const StarredEntitiesApi = createApiExtension({ }), }); +/** @alpha */ +export const CatalogSearchResultListItemExtension = + createSearchResultListItemExtension({ + id: 'catalog', + predicate: result => result.type === 'software-catalog', + component: () => + import('./components/CatalogSearchResultListItem').then( + m => m.CatalogSearchResultListItem, + ), + }); + /** @alpha */ export default createPlugin({ id: 'catalog', - extensions: [CatalogApi, StarredEntitiesApi], + extensions: [ + CatalogApi, + StarredEntitiesApi, + CatalogSearchResultListItemExtension, + ], }); From b4b1cbf9fae39f335f7fd2cc18c1fe82fae5f81e Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino <vincenzos@spotify.com> Date: Mon, 2 Oct 2023 18:28:27 +0200 Subject: [PATCH 189/207] changeset Signed-off-by: Vincenzo Scamporlino <vincenzos@spotify.com> --- .changeset/polite-trainers-grin.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/polite-trainers-grin.md diff --git a/.changeset/polite-trainers-grin.md b/.changeset/polite-trainers-grin.md new file mode 100644 index 0000000000..878596702d --- /dev/null +++ b/.changeset/polite-trainers-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +--- + +Make `defaultUserTransformer` resolve to `UserEntity` instead of `Entity` From c3df534cfbab7ccf1b54d5cca7a30c73e37211a4 Mon Sep 17 00:00:00 2001 From: Yevhenii Huselietov <yevhenii.huselietov@gmail.com> Date: Mon, 2 Oct 2023 21:40:28 +0300 Subject: [PATCH 190/207] Update plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts Co-authored-by: Vincenzo Scamporlino <me@vinzscam.dev> Signed-off-by: Yevhenii Huselietov <yevhenii.huselietov@gmail.com> --- .../src/scaffolder/actions/builtin/publish/gitlab.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index a7da0555e2..25f78452a4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -188,6 +188,7 @@ export function createPublishGitlabAction(options: { `The namespace ${owner} is not found or the user doesn't have permissions to access it`, ); } + throw e; } const { id: userId } = (await client.Users.current()) as { From 06451c88d176c1e7e9cc7a7d70937c5a4c55089a Mon Sep 17 00:00:00 2001 From: Alec Jacobs <cajacobs5401@gmail.com> Date: Mon, 2 Oct 2023 12:14:41 -0700 Subject: [PATCH 191/207] test(backend-tasks): refine tests to be more explicit Signed-off-by: Alec Jacobs <cajacobs5401@gmail.com> --- .../src/tasks/TaskWorker.test.ts | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/packages/backend-tasks/src/tasks/TaskWorker.test.ts b/packages/backend-tasks/src/tasks/TaskWorker.test.ts index 4e1e6dc23b..efad4e649b 100644 --- a/packages/backend-tasks/src/tasks/TaskWorker.test.ts +++ b/packages/backend-tasks/src/tasks/TaskWorker.test.ts @@ -400,7 +400,9 @@ describe('TaskWorker', () => { await worker.tryReleaseTask('ticket', initialSettings); // grab initial row for comparisons later - const initialRow = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + const rowAfterClaimAndRelease = ( + await knex<DbTasksRow>(DB_TASKS_TABLE) + )[0]; const settings: TaskSettingsV2 = { ...initialSettings, @@ -409,11 +411,20 @@ describe('TaskWorker', () => { await worker.persistTask(settings); const row1 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + const rowAfterClaimAndReleaseNextStartAt = DateTime.fromJSDate( + new Date(rowAfterClaimAndRelease.next_run_start_at), + ); + const row1NextStartAt = DateTime.fromJSDate( + new Date(row1.next_run_start_at), + ); + const now = DateTime.now(); expect( - new Date(row1.next_run_start_at) < - new Date(initialRow.next_run_start_at), - ).toBeTruthy(); // ensure that next start at is sooner than initial - expect(new Date(row1.next_run_start_at) > new Date()).toBeTruthy(); // ensure that next start at is later than now + rowAfterClaimAndReleaseNextStartAt.diff(row1NextStartAt).as('minutes'), + ).toBeCloseTo(60, 1); // ensure that next start at is sooner than initial by one hour + expect(row1NextStartAt.diff(now).as('minutes')).toBeCloseTo(60, 1); // ensure that next start at is later than now by one hour + expect( + rowAfterClaimAndReleaseNextStartAt.diff(now).as('minutes'), + ).toBeCloseTo(120, 1); const settings2 = { ...settings, @@ -451,7 +462,9 @@ describe('TaskWorker', () => { await worker.tryReleaseTask('ticket', initialSettings); // grab initial row for comparisons later - const initialRow = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + const rowAfterClaimAndRelease = ( + await knex<DbTasksRow>(DB_TASKS_TABLE) + )[0]; const settings: TaskSettingsV2 = { ...initialSettings, @@ -460,14 +473,20 @@ describe('TaskWorker', () => { await worker.persistTask(settings); const row1 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; + const rowAfterClaimAndReleaseNextStartAt = DateTime.fromJSDate( + new Date(rowAfterClaimAndRelease.next_run_start_at), + ); + const row1NextStartAt = DateTime.fromJSDate( + new Date(row1.next_run_start_at), + ); + const now = DateTime.now(); expect( - new Date(row1.next_run_start_at) < - new Date(initialRow.next_run_start_at), - ).toBeTruthy(); // ensure that next start at is sooner than initial + rowAfterClaimAndReleaseNextStartAt.diff(row1NextStartAt).as('minutes'), + ).toBeCloseTo(62, 1); // ensure that next start at is sooner than initial by one hour, plus the 2 minute delay (set my tryReleaseTask) + expect(row1NextStartAt.diff(now).as('minutes')).toBeCloseTo(60, 1); // ensure that next start at is later than now by one hour (2 minute delay doesn't take effect here) expect( - new Date(row1.next_run_start_at) > - DateTime.now().plus({ minutes: 3 }).toJSDate(), - ).toBeTruthy(); // ensure that next start at is later than initial delay start time since next run at should be an hour from now + rowAfterClaimAndReleaseNextStartAt.diff(now).as('minutes'), + ).toBeCloseTo(122, 1); // includes 2 minute start delay (which is persisted from tryReleaseTask) const settings2 = { ...settings, From 79c3febee739705daa78cfd0c359a25a48bb60da Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Tue, 3 Oct 2023 10:07:38 +0200 Subject: [PATCH 192/207] .github/workflows: disable Node 20 tests Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .github/workflows/ci.yml | 6 +++--- .github/workflows/deploy_packages.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12c19075a6..dbf2dc6705 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [18.x, 20.x] + node-version: [18.x] env: CI: true @@ -49,7 +49,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [18.x, 20.x] + node-version: [18.x] env: CI: true @@ -139,7 +139,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [18.x, 20.x] + node-version: [18.x] name: Test ${{ matrix.node-version }} services: diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index 2329101eb0..91b25fb323 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [18.x, 20.x] + node-version: [18.x] services: postgres13: From 1ef5c2720dff91e898212ee95d967cc39ed94c71 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 22 Sep 2023 15:02:11 +0200 Subject: [PATCH 193/207] feat: turn on some simple monitoring with prometheus for now Signed-off-by: blam <ben@blam.sh> --- packages/backend-tasks/package.json | 1 + .../backend-tasks/src/tasks/TaskWorker.ts | 26 ++++++++++- packages/backend-tasks/src/tasks/metrics.ts | 46 +++++++++++++++++++ yarn.lock | 1 + 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 packages/backend-tasks/src/tasks/metrics.ts diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index f4118b8098..221e1f3a69 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -41,6 +41,7 @@ "knex": "^2.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", + "prom-client": "^14.0.1", "uuid": "^8.0.0", "winston": "^3.2.1", "zod": "^3.21.4" diff --git a/packages/backend-tasks/src/tasks/TaskWorker.ts b/packages/backend-tasks/src/tasks/TaskWorker.ts index 6e3a88410b..b5c4162f68 100644 --- a/packages/backend-tasks/src/tasks/TaskWorker.ts +++ b/packages/backend-tasks/src/tasks/TaskWorker.ts @@ -18,9 +18,11 @@ import { ConflictError, NotFoundError } from '@backstage/errors'; import { CronTime } from 'cron'; import { Knex } from 'knex'; import { DateTime, Duration } from 'luxon'; +import { Counter, Summary } from 'prom-client'; import { v4 as uuid } from 'uuid'; import { Logger } from 'winston'; import { DbTasksRow, DB_TASKS_TABLE } from '../database/tables'; +import { createCounterMetric, createSummaryMetric } from './metrics'; import { TaskFunction, TaskSettingsV2, taskSettingsV2Schema } from './types'; import { delegateAbortController, nowPlus, sleep } from './util'; @@ -32,13 +34,27 @@ const DEFAULT_WORK_CHECK_FREQUENCY = Duration.fromObject({ seconds: 5 }); * @private */ export class TaskWorker { + private readonly counter: Counter; + private readonly duration: Summary; + constructor( private readonly taskId: string, private readonly fn: TaskFunction, private readonly knex: Knex, private readonly logger: Logger, private readonly workCheckFrequency: Duration = DEFAULT_WORK_CHECK_FREQUENCY, - ) {} + ) { + this.counter = createCounterMetric({ + name: 'backstage_task_runs_total', + help: 'Total number of times a task has been run', + labelNames: ['task_id', 'result'], + }); + this.duration = createSummaryMetric({ + name: 'backstage_task_run_duration_seconds', + help: 'Duration of task runs in seconds', + labelNames: ['task_id', 'result'], + }); + } async start(settings: TaskSettingsV2, options?: { signal?: AbortSignal }) { try { @@ -50,9 +66,13 @@ export class TaskWorker { this.logger.info( `Task worker starting: ${this.taskId}, ${JSON.stringify(settings)}`, ); + this.counter.inc({ task_id: this.taskId, result: 'started' }, 1); + let attemptNum = 1; (async () => { for (;;) { + const endDuration = this.duration.startTimer(); + try { if (settings.initialDelayDuration) { await sleep( @@ -71,6 +91,8 @@ export class TaskWorker { } this.logger.info(`Task worker finished: ${this.taskId}`); + this.counter.inc({ task_id: this.taskId, result: 'completed' }, 1); + endDuration({ task_id: this.taskId, result: 'completed' }); attemptNum = 0; break; } catch (e) { @@ -78,6 +100,8 @@ export class TaskWorker { this.logger.warn( `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`, ); + this.counter.inc({ task_id: this.taskId, result: 'failed' }, 1); + endDuration({ task_id: this.taskId, result: 'failed' }); await sleep(Duration.fromObject({ seconds: 1 })); } } diff --git a/packages/backend-tasks/src/tasks/metrics.ts b/packages/backend-tasks/src/tasks/metrics.ts new file mode 100644 index 0000000000..574e64afcb --- /dev/null +++ b/packages/backend-tasks/src/tasks/metrics.ts @@ -0,0 +1,46 @@ +/* + * 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 { + Counter, + CounterConfiguration, + register, + Summary, + SummaryConfiguration, +} from 'prom-client'; + +export function createCounterMetric<T extends string>( + config: CounterConfiguration<T>, +): Counter<T> { + let metric = register.getSingleMetric(config.name); + if (!metric) { + metric = new Counter<T>(config); + register.registerMetric(metric); + } + return metric as Counter<T>; +} + +export function createSummaryMetric<T extends string>( + config: SummaryConfiguration<T>, +): Summary<T> { + let metric = register.getSingleMetric(config.name); + if (!metric) { + metric = new Summary<T>(config); + register.registerMetric(metric); + } + + return metric as Summary<T>; +} diff --git a/yarn.lock b/yarn.lock index de2a8d5ea7..fee4c29a3a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3628,6 +3628,7 @@ __metadata: knex: ^2.0.0 lodash: ^4.17.21 luxon: ^3.0.0 + prom-client: ^14.0.1 uuid: ^8.0.0 wait-for-expect: ^3.0.2 winston: ^3.2.1 From 7184708a2008b7195bbade884ce05343378138c7 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 22 Sep 2023 15:15:31 +0200 Subject: [PATCH 194/207] chore: tinker around a little bit Signed-off-by: blam <ben@blam.sh> --- packages/backend-tasks/src/tasks/TaskWorker.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/backend-tasks/src/tasks/TaskWorker.ts b/packages/backend-tasks/src/tasks/TaskWorker.ts index b5c4162f68..c83bccb197 100644 --- a/packages/backend-tasks/src/tasks/TaskWorker.ts +++ b/packages/backend-tasks/src/tasks/TaskWorker.ts @@ -71,8 +71,6 @@ export class TaskWorker { let attemptNum = 1; (async () => { for (;;) { - const endDuration = this.duration.startTimer(); - try { if (settings.initialDelayDuration) { await sleep( @@ -82,7 +80,12 @@ export class TaskWorker { } while (!options?.signal?.aborted) { + const endDuration = this.duration.startTimer(); const runResult = await this.runOnce(options?.signal); + endDuration({ task_id: this.taskId, result: 'completed' }); + + this.counter.inc({ task_id: this.taskId, result: 'completed' }, 1); + if (runResult.result === 'abort') { break; } @@ -91,8 +94,7 @@ export class TaskWorker { } this.logger.info(`Task worker finished: ${this.taskId}`); - this.counter.inc({ task_id: this.taskId, result: 'completed' }, 1); - endDuration({ task_id: this.taskId, result: 'completed' }); + attemptNum = 0; break; } catch (e) { @@ -101,7 +103,6 @@ export class TaskWorker { `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`, ); this.counter.inc({ task_id: this.taskId, result: 'failed' }, 1); - endDuration({ task_id: this.taskId, result: 'failed' }); await sleep(Duration.fromObject({ seconds: 1 })); } } From 3748620277224dbdd078c7eecae64cf7b8ae994d Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 22 Sep 2023 16:36:20 +0200 Subject: [PATCH 195/207] feat: use OT metrics instead of prom-client Signed-off-by: blam <ben@blam.sh> --- packages/backend-tasks/package.json | 2 +- .../backend-tasks/src/tasks/TaskWorker.ts | 32 +++++++++---------- yarn.lock | 2 +- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 221e1f3a69..197caae774 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -36,12 +36,12 @@ "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/types": "workspace:^", + "@opentelemetry/api": "^1.3.0", "@types/luxon": "^3.0.0", "cron": "^2.0.0", "knex": "^2.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", - "prom-client": "^14.0.1", "uuid": "^8.0.0", "winston": "^3.2.1", "zod": "^3.21.4" diff --git a/packages/backend-tasks/src/tasks/TaskWorker.ts b/packages/backend-tasks/src/tasks/TaskWorker.ts index c83bccb197..a2ed75fef5 100644 --- a/packages/backend-tasks/src/tasks/TaskWorker.ts +++ b/packages/backend-tasks/src/tasks/TaskWorker.ts @@ -18,13 +18,12 @@ import { ConflictError, NotFoundError } from '@backstage/errors'; import { CronTime } from 'cron'; import { Knex } from 'knex'; import { DateTime, Duration } from 'luxon'; -import { Counter, Summary } from 'prom-client'; import { v4 as uuid } from 'uuid'; import { Logger } from 'winston'; import { DbTasksRow, DB_TASKS_TABLE } from '../database/tables'; -import { createCounterMetric, createSummaryMetric } from './metrics'; import { TaskFunction, TaskSettingsV2, taskSettingsV2Schema } from './types'; import { delegateAbortController, nowPlus, sleep } from './util'; +import { metrics, Counter, Histogram } from '@opentelemetry/api'; const DEFAULT_WORK_CHECK_FREQUENCY = Duration.fromObject({ seconds: 5 }); @@ -35,7 +34,7 @@ const DEFAULT_WORK_CHECK_FREQUENCY = Duration.fromObject({ seconds: 5 }); */ export class TaskWorker { private readonly counter: Counter; - private readonly duration: Summary; + private readonly duration: Histogram; constructor( private readonly taskId: string, @@ -44,15 +43,13 @@ export class TaskWorker { private readonly logger: Logger, private readonly workCheckFrequency: Duration = DEFAULT_WORK_CHECK_FREQUENCY, ) { - this.counter = createCounterMetric({ - name: 'backstage_task_runs_total', - help: 'Total number of times a task has been run', - labelNames: ['task_id', 'result'], + const meter = metrics.getMeter('default'); + this.counter = meter.createCounter('backend_task_runs_total', { + description: 'Total number of times a task has been run', }); - this.duration = createSummaryMetric({ - name: 'backstage_task_run_duration_seconds', - help: 'Duration of task runs in seconds', - labelNames: ['task_id', 'result'], + this.duration = meter.createHistogram('backend_task_run_duration', { + description: 'Histogram of task run durations', + unit: 'seconds', }); } @@ -66,7 +63,7 @@ export class TaskWorker { this.logger.info( `Task worker starting: ${this.taskId}, ${JSON.stringify(settings)}`, ); - this.counter.inc({ task_id: this.taskId, result: 'started' }, 1); + this.counter.add(1, { task_id: this.taskId, result: 'started' }); let attemptNum = 1; (async () => { @@ -80,11 +77,13 @@ export class TaskWorker { } while (!options?.signal?.aborted) { - const endDuration = this.duration.startTimer(); + const startTime = process.hrtime(); const runResult = await this.runOnce(options?.signal); - endDuration({ task_id: this.taskId, result: 'completed' }); + const delta = process.hrtime(startTime); + const endTime = delta[0] + delta[1] / 1e9; - this.counter.inc({ task_id: this.taskId, result: 'completed' }, 1); + this.duration.record(endTime, { task_id: this.taskId }); + this.counter.add(1, { task_id: this.taskId, result: 'completed' }); if (runResult.result === 'abort') { break; @@ -94,7 +93,6 @@ export class TaskWorker { } this.logger.info(`Task worker finished: ${this.taskId}`); - attemptNum = 0; break; } catch (e) { @@ -102,7 +100,7 @@ export class TaskWorker { this.logger.warn( `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`, ); - this.counter.inc({ task_id: this.taskId, result: 'failed' }, 1); + this.counter.add(1, { task_id: this.taskId, result: 'failed' }); await sleep(Duration.fromObject({ seconds: 1 })); } } diff --git a/yarn.lock b/yarn.lock index fee4c29a3a..79fa81b6f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3622,13 +3622,13 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/types": "workspace:^" + "@opentelemetry/api": ^1.3.0 "@types/cron": ^2.0.0 "@types/luxon": ^3.0.0 cron: ^2.0.0 knex: ^2.0.0 lodash: ^4.17.21 luxon: ^3.0.0 - prom-client: ^14.0.1 uuid: ^8.0.0 wait-for-expect: ^3.0.2 winston: ^3.2.1 From 1b85da3f9bcc26c9be29383207bc0d554951def1 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 22 Sep 2023 16:42:02 +0200 Subject: [PATCH 196/207] chore: move metrics collection to a different place to make it simpler Signed-off-by: blam <ben@blam.sh> --- packages/backend-tasks/src/tasks/TaskWorker.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/backend-tasks/src/tasks/TaskWorker.ts b/packages/backend-tasks/src/tasks/TaskWorker.ts index a2ed75fef5..ecf71c1db4 100644 --- a/packages/backend-tasks/src/tasks/TaskWorker.ts +++ b/packages/backend-tasks/src/tasks/TaskWorker.ts @@ -77,13 +77,7 @@ export class TaskWorker { } while (!options?.signal?.aborted) { - const startTime = process.hrtime(); const runResult = await this.runOnce(options?.signal); - const delta = process.hrtime(startTime); - const endTime = delta[0] + delta[1] / 1e9; - - this.duration.record(endTime, { task_id: this.taskId }); - this.counter.add(1, { task_id: this.taskId, result: 'completed' }); if (runResult.result === 'abort') { break; @@ -100,7 +94,6 @@ export class TaskWorker { this.logger.warn( `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`, ); - this.counter.add(1, { task_id: this.taskId, result: 'failed' }); await sleep(Duration.fromObject({ seconds: 1 })); } } @@ -164,10 +157,17 @@ export class TaskWorker { }, Duration.fromISO(taskSettings.timeoutAfterDuration).as('milliseconds')); try { + const startTime = process.hrtime(); await this.fn(taskAbortController.signal); + const delta = process.hrtime(startTime); + const endTime = delta[0] + delta[1] / 1e9; + + this.duration.record(endTime, { task_id: this.taskId }); + this.counter.add(1, { task_id: this.taskId, result: 'completed' }); taskAbortController.abort(); // releases resources } catch (e) { this.logger.error(e); + this.counter.add(1, { task_id: this.taskId, result: 'failed' }); await this.tryReleaseTask(ticket, taskSettings); return { result: 'failed' }; } finally { From 5db102bfdf18719ce8e55a7aae3364925f0337b3 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 22 Sep 2023 16:43:24 +0200 Subject: [PATCH 197/207] feat: instrumentation changeset Signed-off-by: blam <ben@blam.sh> --- .changeset/breezy-dryers-thank.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/breezy-dryers-thank.md diff --git a/.changeset/breezy-dryers-thank.md b/.changeset/breezy-dryers-thank.md new file mode 100644 index 0000000000..22be92f530 --- /dev/null +++ b/.changeset/breezy-dryers-thank.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-tasks': patch +--- + +Instrument `backend-tasks` with some counters and histograms for duration From caf288ff034bd9f8de9028772c9893d0025eabb7 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Mon, 25 Sep 2023 13:49:37 +0200 Subject: [PATCH 198/207] chore: remove unused metircs Signed-off-by: blam <ben@blam.sh> --- packages/backend-tasks/src/tasks/metrics.ts | 46 --------------------- 1 file changed, 46 deletions(-) delete mode 100644 packages/backend-tasks/src/tasks/metrics.ts diff --git a/packages/backend-tasks/src/tasks/metrics.ts b/packages/backend-tasks/src/tasks/metrics.ts deleted file mode 100644 index 574e64afcb..0000000000 --- a/packages/backend-tasks/src/tasks/metrics.ts +++ /dev/null @@ -1,46 +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 { - Counter, - CounterConfiguration, - register, - Summary, - SummaryConfiguration, -} from 'prom-client'; - -export function createCounterMetric<T extends string>( - config: CounterConfiguration<T>, -): Counter<T> { - let metric = register.getSingleMetric(config.name); - if (!metric) { - metric = new Counter<T>(config); - register.registerMetric(metric); - } - return metric as Counter<T>; -} - -export function createSummaryMetric<T extends string>( - config: SummaryConfiguration<T>, -): Summary<T> { - let metric = register.getSingleMetric(config.name); - if (!metric) { - metric = new Summary<T>(config); - register.registerMetric(metric); - } - - return metric as Summary<T>; -} From 6916c4b291b0fd0cec26bb4b3f1154089c00240b Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Tue, 26 Sep 2023 14:54:40 +0200 Subject: [PATCH 199/207] feat: move the implementation to the scheduler instead Signed-off-by: blam <ben@blam.sh> --- .../src/tasks/PluginTaskSchedulerImpl.ts | 44 +++++++++++++++++-- .../backend-tasks/src/tasks/TaskWorker.ts | 23 +--------- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts index b9ac80cb47..83acc9e972 100644 --- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts +++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts @@ -28,7 +28,8 @@ import { TaskSettingsV2, } from './types'; import { validateId } from './util'; - +import { TaskFunction } from './types'; +import { metrics, Counter, Histogram } from '@opentelemetry/api'; /** * Implements the actual task management. */ @@ -36,10 +37,22 @@ export class PluginTaskSchedulerImpl implements PluginTaskScheduler { private readonly localTasksById = new Map<string, LocalTaskWorker>(); private readonly allScheduledTasks: TaskDescriptor[] = []; + private readonly counter: Counter; + private readonly duration: Histogram; + constructor( private readonly databaseFactory: () => Promise<Knex>, private readonly logger: Logger, - ) {} + ) { + const meter = metrics.getMeter('default'); + this.counter = meter.createCounter('backend_task_runs_total', { + description: 'Total number of times a task has been run', + }); + this.duration = meter.createHistogram('backend_task_run_duration', { + description: 'Histogram of task run durations', + unit: 'seconds', + }); + } async triggerTask(id: string): Promise<void> { const localTask = this.localTasksById.get(id); @@ -70,7 +83,7 @@ export class PluginTaskSchedulerImpl implements PluginTaskScheduler { const knex = await this.databaseFactory(); const worker = new TaskWorker( task.id, - task.fn, + this.wrapInMetrics(task.fn, { labels: { taskId: task.id, scope } }), knex, this.logger.child({ task: task.id }), ); @@ -78,7 +91,7 @@ export class PluginTaskSchedulerImpl implements PluginTaskScheduler { } else { const worker = new LocalTaskWorker( task.id, - task.fn, + this.wrapInMetrics(task.fn, { labels: { taskId: task.id, scope } }), this.logger.child({ task: task.id }), ); worker.start(settings, { signal: task.signal }); @@ -103,6 +116,29 @@ export class PluginTaskSchedulerImpl implements PluginTaskScheduler { async getScheduledTasks(): Promise<TaskDescriptor[]> { return this.allScheduledTasks; } + + private wrapInMetrics( + fn: TaskFunction, + opts: { labels: Record<string, string> }, + ): TaskFunction { + return async abort => { + this.counter.add(1, { ...opts.labels, result: 'started' }); + + const startTime = process.hrtime(); + + try { + await fn(abort); + this.counter.add(1, { ...opts.labels, result: 'completed' }); + } catch (ex) { + this.counter.add(1, { ...opts.labels, result: 'failed' }); + throw ex; + } finally { + const delta = process.hrtime(startTime); + const endTime = delta[0] + delta[1] / 1e9; + this.duration.record(endTime, { ...opts.labels }); + } + }; + } } export function parseDuration( diff --git a/packages/backend-tasks/src/tasks/TaskWorker.ts b/packages/backend-tasks/src/tasks/TaskWorker.ts index ecf71c1db4..4e10f0b5b2 100644 --- a/packages/backend-tasks/src/tasks/TaskWorker.ts +++ b/packages/backend-tasks/src/tasks/TaskWorker.ts @@ -23,7 +23,6 @@ import { Logger } from 'winston'; import { DbTasksRow, DB_TASKS_TABLE } from '../database/tables'; import { TaskFunction, TaskSettingsV2, taskSettingsV2Schema } from './types'; import { delegateAbortController, nowPlus, sleep } from './util'; -import { metrics, Counter, Histogram } from '@opentelemetry/api'; const DEFAULT_WORK_CHECK_FREQUENCY = Duration.fromObject({ seconds: 5 }); @@ -33,25 +32,13 @@ const DEFAULT_WORK_CHECK_FREQUENCY = Duration.fromObject({ seconds: 5 }); * @private */ export class TaskWorker { - private readonly counter: Counter; - private readonly duration: Histogram; - constructor( private readonly taskId: string, private readonly fn: TaskFunction, private readonly knex: Knex, private readonly logger: Logger, private readonly workCheckFrequency: Duration = DEFAULT_WORK_CHECK_FREQUENCY, - ) { - const meter = metrics.getMeter('default'); - this.counter = meter.createCounter('backend_task_runs_total', { - description: 'Total number of times a task has been run', - }); - this.duration = meter.createHistogram('backend_task_run_duration', { - description: 'Histogram of task run durations', - unit: 'seconds', - }); - } + ) {} async start(settings: TaskSettingsV2, options?: { signal?: AbortSignal }) { try { @@ -63,7 +50,6 @@ export class TaskWorker { this.logger.info( `Task worker starting: ${this.taskId}, ${JSON.stringify(settings)}`, ); - this.counter.add(1, { task_id: this.taskId, result: 'started' }); let attemptNum = 1; (async () => { @@ -157,17 +143,10 @@ export class TaskWorker { }, Duration.fromISO(taskSettings.timeoutAfterDuration).as('milliseconds')); try { - const startTime = process.hrtime(); await this.fn(taskAbortController.signal); - const delta = process.hrtime(startTime); - const endTime = delta[0] + delta[1] / 1e9; - - this.duration.record(endTime, { task_id: this.taskId }); - this.counter.add(1, { task_id: this.taskId, result: 'completed' }); taskAbortController.abort(); // releases resources } catch (e) { this.logger.error(e); - this.counter.add(1, { task_id: this.taskId, result: 'failed' }); await this.tryReleaseTask(ticket, taskSettings); return { result: 'failed' }; } finally { From 0dada05a787c1f74774920f125fe7e084f5c38eb Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Mon, 2 Oct 2023 14:06:50 +0200 Subject: [PATCH 200/207] chore: fixing changeset Signed-off-by: blam <ben@blam.sh> --- .changeset/breezy-dryers-thank.md | 7 ++++++- .../src/tasks/PluginTaskSchedulerImpl.ts | 13 +++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.changeset/breezy-dryers-thank.md b/.changeset/breezy-dryers-thank.md index 22be92f530..317d2316b1 100644 --- a/.changeset/breezy-dryers-thank.md +++ b/.changeset/breezy-dryers-thank.md @@ -2,4 +2,9 @@ '@backstage/backend-tasks': patch --- -Instrument `backend-tasks` with some counters and histograms for duration +Instrument `backend-tasks` with some counters and histograms for duration. + +`backend_task_runs_total`: Counter with the total number of times a task has been run. +`backend_task_run_duration`: Histogram with the run durations for each task. + +Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping andd diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts index 83acc9e972..9971d47ab6 100644 --- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts +++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts @@ -30,6 +30,7 @@ import { import { validateId } from './util'; import { TaskFunction } from './types'; import { metrics, Counter, Histogram } from '@opentelemetry/api'; + /** * Implements the actual task management. */ @@ -122,20 +123,24 @@ export class PluginTaskSchedulerImpl implements PluginTaskScheduler { opts: { labels: Record<string, string> }, ): TaskFunction { return async abort => { - this.counter.add(1, { ...opts.labels, result: 'started' }); + const labels = { + ...opts.labels, + }; + this.counter.add(1, { ...labels, result: 'started' }); const startTime = process.hrtime(); try { await fn(abort); - this.counter.add(1, { ...opts.labels, result: 'completed' }); + labels.result = 'completed'; } catch (ex) { - this.counter.add(1, { ...opts.labels, result: 'failed' }); + labels.result = 'failed'; throw ex; } finally { const delta = process.hrtime(startTime); const endTime = delta[0] + delta[1] / 1e9; - this.duration.record(endTime, { ...opts.labels }); + this.counter.add(1, labels); + this.duration.record(endTime, labels); } }; } From bbbd853875c614c138da8a260eed0e5bda027d64 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Tue, 3 Oct 2023 10:36:26 +0200 Subject: [PATCH 201/207] chore: update the metric names Signed-off-by: blam <ben@blam.sh> --- packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts index 9971d47ab6..38561c7a8c 100644 --- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts +++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts @@ -46,10 +46,10 @@ export class PluginTaskSchedulerImpl implements PluginTaskScheduler { private readonly logger: Logger, ) { const meter = metrics.getMeter('default'); - this.counter = meter.createCounter('backend_task_runs_total', { + this.counter = meter.createCounter('backend_tasks.task.runs.count', { description: 'Total number of times a task has been run', }); - this.duration = meter.createHistogram('backend_task_run_duration', { + this.duration = meter.createHistogram('backend_tasks.task.runs.duration', { description: 'Histogram of task run durations', unit: 'seconds', }); From e7d9d346f4bc90d05bfe5ca6953de7cf1fc42c82 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Tue, 3 Oct 2023 10:37:32 +0200 Subject: [PATCH 202/207] chore: fixing changeset Signed-off-by: blam <ben@blam.sh> --- .changeset/breezy-dryers-thank.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/breezy-dryers-thank.md b/.changeset/breezy-dryers-thank.md index 317d2316b1..7a742db1bf 100644 --- a/.changeset/breezy-dryers-thank.md +++ b/.changeset/breezy-dryers-thank.md @@ -4,7 +4,7 @@ Instrument `backend-tasks` with some counters and histograms for duration. -`backend_task_runs_total`: Counter with the total number of times a task has been run. -`backend_task_run_duration`: Histogram with the run durations for each task. +`backend_tasks.task.runs.count`: Counter with the total number of times a task has been run. +`backend_tasks.task.runs.duration`: Histogram with the run durations for each task. -Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping andd +Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping. From 22299c4fdbe026db6ab38149e80c7b611425c587 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino <vincenzos@spotify.com> Date: Tue, 3 Oct 2023 11:26:12 +0200 Subject: [PATCH 203/207] create-app: add missing eslintignore Signed-off-by: Vincenzo Scamporlino <vincenzos@spotify.com> --- packages/create-app/templates/default-app/.eslintignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/create-app/templates/default-app/.eslintignore diff --git a/packages/create-app/templates/default-app/.eslintignore b/packages/create-app/templates/default-app/.eslintignore new file mode 100644 index 0000000000..e5b19947ff --- /dev/null +++ b/packages/create-app/templates/default-app/.eslintignore @@ -0,0 +1 @@ +playwright.config.ts From 24bdbd035e76e77ef264626f226cb92914ac877a Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 08:48:51 +0200 Subject: [PATCH 204/207] docs(catalog): update api reports Signed-off-by: Camila Belo <camilaibs@gmail.com> --- plugins/catalog/alpha-api-report.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/alpha-api-report.md index 060baeccbf..e89807ac34 100644 --- a/plugins/catalog/alpha-api-report.md +++ b/plugins/catalog/alpha-api-report.md @@ -5,19 +5,14 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; -import { TranslationRef } from '@backstage/core-plugin-api/alpha'; // @alpha (undocumented) export const CatalogApi: Extension<{}>; // @alpha (undocumented) -export const catalogTranslationRef: TranslationRef< - 'catalog', - { - readonly catalog_page_title: '{{orgName}} Catalog'; - readonly catalog_page_create_button_title: 'Create'; - } ->; +export const CatalogSearchResultListItemExtension: Extension<{ + noTrack?: boolean | undefined; +}>; // @alpha (undocumented) const _default: BackstagePlugin; From 7c4a8e4d5fa2fc435e45d4e62d25a27338a7f233 Mon Sep 17 00:00:00 2001 From: Camila Belo <camilaibs@gmail.com> Date: Fri, 29 Sep 2023 08:50:56 +0200 Subject: [PATCH 205/207] chore: add changeset file Signed-off-by: Camila Belo <camilaibs@gmail.com> --- .changeset/eight-melons-cough.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/eight-melons-cough.md diff --git a/.changeset/eight-melons-cough.md b/.changeset/eight-melons-cough.md new file mode 100644 index 0000000000..23d7b901f1 --- /dev/null +++ b/.changeset/eight-melons-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Create an experimental `CatalogSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. From 8d2e640af4e634d4950de7e388736e12b0a9c56a Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino <vincenzos@spotify.com> Date: Tue, 3 Oct 2023 11:30:55 +0200 Subject: [PATCH 206/207] changeset Signed-off-by: Vincenzo Scamporlino <vincenzos@spotify.com> --- .changeset/yellow-numbers-own.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .changeset/yellow-numbers-own.md diff --git a/.changeset/yellow-numbers-own.md b/.changeset/yellow-numbers-own.md new file mode 100644 index 0000000000..3a6e8937eb --- /dev/null +++ b/.changeset/yellow-numbers-own.md @@ -0,0 +1,11 @@ +--- +'@backstage/create-app': patch +--- + +Added missing `.eslintignore` file + +To apply this change to an existing app, create a new `.eslintignore` file at the root of your project with the following content: + +```diff ++ playwright.config.ts +``` From f95345c84571a8ecd79291f4c17c6983517a5cca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:49:45 +0000 Subject: [PATCH 207/207] Version Packages (next) --- .changeset/pre.json | 36 +- docs/releases/v1.19.0-next.1-changelog.md | 2758 +++++++++++++++++ package.json | 2 +- packages/app-defaults/CHANGELOG.md | 12 + packages/app-defaults/package.json | 2 +- packages/app-next-example-plugin/CHANGELOG.md | 8 + packages/app-next-example-plugin/package.json | 2 +- packages/app-next/CHANGELOG.md | 77 + packages/app-next/package.json | 2 +- packages/app/CHANGELOG.md | 76 + packages/app/package.json | 2 +- packages/backend-app-api/CHANGELOG.md | 17 + packages/backend-app-api/package.json | 2 +- packages/backend-common/CHANGELOG.md | 17 + packages/backend-common/package.json | 2 +- packages/backend-defaults/CHANGELOG.md | 9 + packages/backend-defaults/package.json | 2 +- packages/backend-dev-utils/CHANGELOG.md | 6 + packages/backend-dev-utils/package.json | 2 +- packages/backend-next/CHANGELOG.md | 37 + packages/backend-next/package.json | 2 +- packages/backend-plugin-api/CHANGELOG.md | 11 + packages/backend-plugin-api/package.json | 2 +- packages/backend-plugin-manager/CHANGELOG.md | 23 + packages/backend-plugin-manager/package.json | 2 +- packages/backend-tasks/CHANGELOG.md | 18 + packages/backend-tasks/package.json | 2 +- packages/backend-test-utils/CHANGELOG.md | 12 + packages/backend-test-utils/package.json | 2 +- packages/backend/CHANGELOG.md | 59 + packages/backend/package.json | 2 +- packages/cli/CHANGELOG.md | 17 + packages/cli/package.json | 2 +- packages/core-app-api/CHANGELOG.md | 11 + packages/core-app-api/package.json | 2 +- packages/core-components/CHANGELOG.md | 16 + packages/core-components/package.json | 2 +- packages/create-app/CHANGELOG.md | 15 + 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/frontend-app-api/CHANGELOG.md | 16 + packages/frontend-app-api/package.json | 2 +- packages/frontend-plugin-api/CHANGELOG.md | 10 + packages/frontend-plugin-api/package.json | 2 +- packages/integration-react/CHANGELOG.md | 11 + packages/integration-react/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/CHANGELOG.md | 17 + plugins/adr/package.json | 2 +- plugins/airbrake-backend/CHANGELOG.md | 9 + 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/analytics-module-ga4/CHANGELOG.md | 10 + plugins/analytics-module-ga4/package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/apache-airflow/CHANGELOG.md | 8 + plugins/apache-airflow/package.json | 2 +- plugins/api-docs/CHANGELOG.md | 12 + 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/app-node/CHANGELOG.md | 7 + plugins/app-node/package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/auth-backend/CHANGELOG.md | 20 + plugins/auth-backend/package.json | 2 +- plugins/auth-node/CHANGELOG.md | 13 + plugins/auth-node/package.json | 2 +- plugins/azure-devops-backend/CHANGELOG.md | 10 + 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 | 14 + 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 | 18 + .../catalog-backend-module-aws/package.json | 2 +- .../catalog-backend-module-azure/CHANGELOG.md | 16 + .../catalog-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 17 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../catalog-backend-module-gcp/CHANGELOG.md | 12 + .../catalog-backend-module-gcp/package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 20 + .../package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../catalog-backend-module-ldap/CHANGELOG.md | 13 + .../catalog-backend-module-ldap/package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/catalog-backend/CHANGELOG.md | 26 + plugins/catalog-backend/package.json | 2 +- plugins/catalog-graph/CHANGELOG.md | 13 + plugins/catalog-graph/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 | 18 + plugins/catalog-react/package.json | 2 +- .../catalog-unprocessed-entities/CHANGELOG.md | 11 + .../catalog-unprocessed-entities/package.json | 2 +- plugins/catalog/CHANGELOG.md | 22 + 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 | 13 + plugins/code-coverage-backend/package.json | 2 +- plugins/code-coverage/CHANGELOG.md | 14 + 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/devtools-backend/CHANGELOG.md | 17 + plugins/devtools-backend/package.json | 2 +- plugins/devtools/CHANGELOG.md | 13 + plugins/devtools/package.json | 2 +- plugins/dynatrace/CHANGELOG.md | 11 + plugins/dynatrace/package.json | 2 +- plugins/entity-feedback-backend/CHANGELOG.md | 13 + 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 | 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 | 10 + plugins/events-backend/package.json | 2 +- plugins/events-node/CHANGELOG.md | 7 + 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 | 12 + plugins/explore-backend/package.json | 2 +- plugins/explore/CHANGELOG.md | 18 + plugins/explore/package.json | 2 +- plugins/firehydrant/CHANGELOG.md | 11 + 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 | 13 + 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 | 10 + plugins/gitops-profiles/package.json | 2 +- plugins/gocd/CHANGELOG.md | 12 + plugins/gocd/package.json | 2 +- plugins/graphiql/CHANGELOG.md | 10 + 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-react/CHANGELOG.md | 8 + plugins/home-react/package.json | 2 +- plugins/home/CHANGELOG.md | 16 + plugins/home/package.json | 2 +- plugins/ilert/CHANGELOG.md | 12 + plugins/ilert/package.json | 2 +- plugins/jenkins-backend/CHANGELOG.md | 15 + plugins/jenkins-backend/package.json | 2 +- plugins/jenkins/CHANGELOG.md | 13 + 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 | 19 + plugins/kubernetes-backend/package.json | 2 +- plugins/kubernetes-common/CHANGELOG.md | 15 + plugins/kubernetes-common/package.json | 2 +- plugins/kubernetes-react/CHANGELOG.md | 17 + plugins/kubernetes-react/package.json | 2 +- plugins/kubernetes/CHANGELOG.md | 20 + plugins/kubernetes/package.json | 2 +- plugins/lighthouse-backend/CHANGELOG.md | 15 + plugins/lighthouse-backend/package.json | 2 +- plugins/lighthouse/CHANGELOG.md | 13 + plugins/lighthouse/package.json | 2 +- plugins/linguist-backend/CHANGELOG.md | 17 + 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/nomad-backend/CHANGELOG.md | 9 + plugins/nomad-backend/package.json | 2 +- plugins/nomad/CHANGELOG.md | 12 + plugins/nomad/package.json | 2 +- plugins/octopus-deploy/CHANGELOG.md | 11 + plugins/octopus-deploy/package.json | 2 +- plugins/opencost/CHANGELOG.md | 9 + plugins/opencost/package.json | 2 +- plugins/org-react/CHANGELOG.md | 12 + plugins/org-react/package.json | 2 +- plugins/org/CHANGELOG.md | 13 + plugins/org/package.json | 2 +- plugins/pagerduty/CHANGELOG.md | 13 + 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 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- plugins/permission-backend/CHANGELOG.md | 13 + plugins/permission-backend/package.json | 2 +- plugins/permission-node/CHANGELOG.md | 12 + plugins/permission-node/package.json | 2 +- plugins/playlist-backend/CHANGELOG.md | 16 + plugins/playlist-backend/package.json | 2 +- plugins/playlist/CHANGELOG.md | 17 + plugins/playlist/package.json | 2 +- plugins/proxy-backend/CHANGELOG.md | 9 + plugins/proxy-backend/package.json | 2 +- plugins/puppetdb/CHANGELOG.md | 12 + plugins/puppetdb/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 | 12 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/scaffolder-backend/CHANGELOG.md | 28 + plugins/scaffolder-backend/package.json | 2 +- plugins/scaffolder-node/CHANGELOG.md | 13 + plugins/scaffolder-node/package.json | 2 +- plugins/scaffolder-react/CHANGELOG.md | 16 + plugins/scaffolder-react/package.json | 2 +- plugins/scaffolder/CHANGELOG.md | 21 + plugins/scaffolder/package.json | 2 +- .../CHANGELOG.md | 18 + .../package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- plugins/search-backend-module-pg/CHANGELOG.md | 11 + plugins/search-backend-module-pg/package.json | 2 +- .../CHANGELOG.md | 18 + .../package.json | 2 +- plugins/search-backend-node/CHANGELOG.md | 13 + plugins/search-backend-node/package.json | 2 +- plugins/search-backend/CHANGELOG.md | 17 + plugins/search-backend/package.json | 2 +- plugins/search-react/CHANGELOG.md | 15 + plugins/search-react/package.json | 2 +- plugins/search/CHANGELOG.md | 19 + 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 | 10 + plugins/sonarqube-backend/package.json | 2 +- plugins/sonarqube/CHANGELOG.md | 12 + 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 | 10 + plugins/stackstorm/package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- plugins/tech-insights-backend/CHANGELOG.md | 15 + 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 | 10 + plugins/tech-radar/package.json | 2 +- .../techdocs-addons-test-utils/CHANGELOG.md | 16 + .../techdocs-addons-test-utils/package.json | 2 +- plugins/techdocs-backend/CHANGELOG.md | 18 + 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 | 11 + plugins/techdocs-react/package.json | 2 +- plugins/techdocs/CHANGELOG.md | 21 + 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 | 10 + 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 +- 407 files changed, 5753 insertions(+), 204 deletions(-) create mode 100644 docs/releases/v1.19.0-next.1-changelog.md create mode 100644 plugins/kubernetes-react/CHANGELOG.md diff --git a/.changeset/pre.json b/.changeset/pre.json index 46230574ed..d767fe77f0 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -245,53 +245,87 @@ "@backstage/plugin-vault": "0.1.19", "@backstage/plugin-vault-backend": "0.3.8", "@backstage/plugin-xcmetrics": "0.2.43", - "@backstage/e2e-test-utils": "0.0.0" + "@backstage/e2e-test-utils": "0.0.0", + "@backstage/plugin-kubernetes-react": "0.0.0" }, "changesets": [ "angry-badgers-beg", "big-spies-beam", + "breezy-dryers-thank", "calm-scissors-rescue", "chatty-papayas-care", "clean-forks-love", + "cold-bees-jam", + "cold-seas-repeat", "dull-bugs-build", "dull-dolls-explode", "dull-experts-kiss", "dull-laws-camp", + "eight-melons-cough", "eighty-actors-type", + "fair-frogs-enjoy", "four-jars-protect", "four-onions-clap", + "four-pans-sin", "fresh-kangaroos-tap", "gentle-elephants-fold", "gentle-spies-deny", + "happy-books-smoke", + "heavy-forks-tie", + "itchy-bobcats-fly", + "itchy-monkeys-reply", "itchy-rabbits-exist", "large-comics-knock", + "late-papayas-push", + "lazy-doors-wink", "lemon-cups-wait", + "lemon-masks-greet", "lovely-coins-occur", "lovely-fans-sniff", + "many-swans-eat", + "mean-dancers-burn", "moody-lobsters-rescue", + "nervous-hounds-sleep", "nice-clocks-smash", "nice-dancers-explain", + "nine-garlics-attend", + "olive-cars-rescue", "perfect-pumas-protect", "plenty-llamas-double", "polite-cooks-perform", "polite-donuts-fail", + "polite-trainers-grin", + "popular-dots-design", "pretty-apes-sneeze", "pretty-steaks-serve", "purple-chefs-wait", + "purple-forks-fetch", "quick-weeks-explode", + "red-bees-try", + "renovate-a1c52e8", "shy-clouds-reflect", + "shy-seas-sip", "silent-years-bake", + "silly-swans-invent", "small-pugs-build", + "spicy-chairs-film", "spotty-badgers-wash", + "strong-falcons-tickle", + "stupid-drinks-trade", "stupid-eagles-shave", + "tasty-avocados-hope", "tasty-doors-switch", "ten-seals-wait", "thirty-coins-sneeze", "tiny-garlics-cheer", "twelve-clouds-design", + "violet-beers-cross", + "warm-drinks-argue", "wet-olives-wave", "wet-timers-chew", + "wicked-rings-flash", "wild-jobs-greet", + "yellow-numbers-own", "yellow-rings-invent" ] } diff --git a/docs/releases/v1.19.0-next.1-changelog.md b/docs/releases/v1.19.0-next.1-changelog.md new file mode 100644 index 0000000000..1b6075095b --- /dev/null +++ b/docs/releases/v1.19.0-next.1-changelog.md @@ -0,0 +1,2758 @@ +# Release v1.19.0-next.1 + +## @backstage/plugin-kubernetes@0.11.0-next.1 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/plugin-kubernetes-react@0.1.0-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-kubernetes-common@0.7.0-next.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-kubernetes-react@0.1.0-next.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend@1.18.0-next.1 + +### Minor Changes + +- f41099bb31: Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.2-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-scaffolder-common@1.4.1 + +## @backstage/app-defaults@1.4.4-next.1 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/theme@0.4.2 + +## @backstage/backend-app-api@0.5.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + +## @backstage/backend-common@0.19.7-next.1 + +### Patch Changes + +- b94f32271e: Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository +- Updated dependencies + - @backstage/backend-dev-utils@0.1.2-next.0 + - @backstage/backend-app-api@0.5.5-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/backend-defaults@0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-app-api@0.5.5-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + +## @backstage/backend-dev-utils@0.1.2-next.0 + +### Patch Changes + +- afa48341fb: Fix an issue where early IPC responses would be lost. + +## @backstage/backend-plugin-api@0.6.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/backend-tasks@0.5.10-next.1 + +### Patch Changes + +- 5db102bfdf: Instrument `backend-tasks` with some counters and histograms for duration. + + `backend_tasks.task.runs.count`: Counter with the total number of times a task has been run. + `backend_tasks.task.runs.duration`: Histogram with the run durations for each task. + + Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping. + +- ddd76ac98d: Fix bug where backend tasks that are defined with HumanDuration are immediately triggered on application startup + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + +## @backstage/backend-test-utils@0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-app-api@0.5.5-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + +## @backstage/cli@0.23.0-next.1 + +### Patch Changes + +- d0f26cfa4f: Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows. +- Updated dependencies + - @backstage/config@1.1.0 + - @backstage/release-manifests@0.0.10 + - @backstage/catalog-model@1.4.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/errors@1.2.2 + - @backstage/eslint-plugin@0.1.3 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/core-app-api@1.10.1-next.1 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + +## @backstage/core-components@0.13.6-next.1 + +### Patch Changes + +- 4eab5cf901: The `TabbedLayout` component will now also navigate when clicking the active tab, which allows for navigation back from any sub routes. +- 997a71850c: Changed SupportButton menuitems to support text wrap +- 16126dbe6a: Change overlay header colors in the mobile menu to use navigation color from the theme +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/version-bridge@1.0.5 + +## @backstage/create-app@0.5.6-next.1 + +### Patch Changes + +- 8d2e640af4: Added missing `.eslintignore` file + + To apply this change to an existing app, create a new `.eslintignore` file at the root of your project with the following content: + + ```diff + + playwright.config.ts + ``` + +- Updated dependencies + - @backstage/cli-common@0.1.13-next.0 + +## @backstage/dev-utils@1.0.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/app-defaults@1.4.4-next.1 + - @backstage/test-utils@1.4.4-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/frontend-app-api@0.2.0-next.1 + +### Patch Changes + +- 52366db5b3: Make themes configurable through extensions, and switched default themes to use extensions instead. +- e5a2956dd2: Register default api implementations when creating declarative integrated apps. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/plugin-graphiql@0.2.55-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + +## @backstage/frontend-plugin-api@0.1.1-next.1 + +### Patch Changes + +- d3a37f55c0: Add support for `SidebarGroup` on the sidebar item extension. +- 52366db5b3: Added `createThemeExtension` and `coreExtensionData.theme`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/types@1.1.1 + +## @backstage/integration-react@1.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + +## @techdocs/cli@1.5.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-techdocs-node@1.8.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/cli-common@0.1.13-next.0 + +## @backstage/test-utils@1.4.4-next.1 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- Updated dependencies + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-adr@0.6.8-next.1 + +### Patch Changes + +- 1204e7628e: Create an experimental `AdrSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-adr-common@0.2.16-next.0 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-adr-backend@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-adr-common@0.2.16-next.0 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-airbrake@0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/test-utils@1.4.4-next.1 + - @backstage/dev-utils@1.0.22-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-airbrake-backend@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + +## @backstage/plugin-allure@0.1.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-analytics-module-ga@0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-analytics-module-ga4@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-analytics-module-newrelic-browser@0.0.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + +## @backstage/plugin-apache-airflow@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + +## @backstage/plugin-api-docs@0.9.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-apollo-explorer@0.1.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-app-backend@0.3.53-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.5-next.1 + +## @backstage/plugin-app-node@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + +## @backstage/plugin-auth-backend@0.19.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.1.2-next.1 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.2-next.1 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.2-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.1.2-next.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.2-next.1 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-backend-module-github-provider@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + +## @backstage/plugin-auth-backend-module-google-provider@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + +## @backstage/plugin-auth-node@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-azure-devops@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-devops-backend@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-sites@0.1.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-azure-sites-backend@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-badges@0.2.49-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-badges-backend@0.3.2-next.1 + +### Patch Changes + +- 817f2acbb1: Make sure the default badge factory is used if nothing is defined +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + +## @backstage/plugin-bazaar@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/cli@0.23.0-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-bazaar-backend@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + +## @backstage/plugin-bitrise@0.1.52-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-catalog@1.14.0-next.1 + +### Patch Changes + +- 7c4a8e4d5f: Create an experimental `CatalogSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- e5a2956dd2: Migrate catalog api to declarative integration system, it is exported from `/alpha` subpath. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-scaffolder-common@1.4.1 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-catalog-backend@1.14.0-next.1 + +### Patch Changes + +- 7a2e2924c7: Marked the `LocationEntityProcessor` as deprecated, as it is no longer used internally since way back and can even be harmful at this point. +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.9-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/backend-openapi-utils@0.0.4 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-events-node@0.2.14-next.1 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-scaffolder-common@1.4.1 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-catalog-backend-module-aws@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + +## @backstage/plugin-catalog-backend-module-azure@0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.13-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.13-next.0 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + +## @backstage/plugin-catalog-backend-module-github@0.4.3-next.1 + +### Patch Changes + +- b4b1cbf9fa: Make `defaultUserTransformer` resolve to `UserEntity` instead of `Entity` +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.3.2-next.1 + +### Patch Changes + +- 6ae7f12abb: Make sure the archived projects are skipped with the Gitlab API +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/plugin-events-node@0.2.14-next.1 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-catalog-common@1.0.16 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-scaffolder-common@1.4.1 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/catalog-model@1.4.2 + +## @backstage/plugin-catalog-graph@0.2.37-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-import@0.10.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-catalog-common@1.0.16 + +## @backstage/plugin-catalog-node@1.4.6-next.1 + +### Patch Changes + +- 7a2e2924c7: Added docs to `processingResult` +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + +## @backstage/plugin-catalog-react@1.8.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-cicd-statistics@0.1.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-cicd-statistics@0.1.27-next.1 + +## @backstage/plugin-circleci@0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-cloudbuild@0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-code-climate@0.1.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-code-coverage@0.2.18-next.1 + +### Patch Changes + +- 88b0b32547: Fixed the coverage history statistics to compare newest with oldest record +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-code-coverage-backend@0.2.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + +## @backstage/plugin-codescene@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-config-schema@0.1.46-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-cost-insights@0.12.14-next.1 + +### Patch Changes + +- ba4820883c: Updated dependency `@types/pluralize` to `^0.0.31`. +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-cost-insights-common@0.1.2 + +## @backstage/plugin-devtools@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.4 + +## @backstage/plugin-devtools-backend@0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.4 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-dynatrace@7.0.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-entity-feedback@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-feedback-backend@0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-validation@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-catalog-common@1.0.16 + +## @backstage/plugin-events-backend@0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-events-backend-module-azure@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-events-backend-module-gerrit@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-events-backend-module-github@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-events-backend-module-gitlab@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-events-backend-test-utils@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.14-next.1 + +## @backstage/plugin-events-node@0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + +## @backstage/plugin-explore@0.4.11-next.1 + +### Patch Changes + +- 0f10c53a05: Create an experimental `ExploreSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-explore-react@0.0.32-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-explore-backend@0.0.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.9-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-firehydrant@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-fossa@0.2.57-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-gcalendar@0.3.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-gcp-projects@0.3.42-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-git-release-manager@0.3.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-github-actions@0.6.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-github-deployments@0.1.56-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-github-issues@0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-github-pull-requests-board@0.1.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-gitops-profiles@0.3.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-gocd@0.1.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-graphiql@0.2.55-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-graphql-backend@0.1.43-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-catalog-graphql@0.3.23 + +## @backstage/plugin-graphql-voyager@0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-home@0.5.9-next.1 + +### Patch Changes + +- f997f771da: Adds Top/Recently Visited components to homepage +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-home-react@0.1.4-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-home-react@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + +## @backstage/plugin-ilert@0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-jenkins@0.8.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-jenkins-common@0.1.19 + +## @backstage/plugin-jenkins-backend@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/plugin-jenkins-common@0.1.19 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-kafka@0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-kafka-backend@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + +## @backstage/plugin-kubernetes-backend@0.12.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-lighthouse@0.4.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-lighthouse-common@0.1.3 + +## @backstage/plugin-lighthouse-backend@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.3 + +## @backstage/plugin-linguist@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-linguist-backend@0.5.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-microsoft-calendar@0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-newrelic@0.3.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-newrelic-dashboard@0.2.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + +## @backstage/plugin-nomad@0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-nomad-backend@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + +## @backstage/plugin-octopus-deploy@0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-opencost@0.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-org@0.6.15-next.1 + +### Patch Changes + +- dc5b6b971b: Fixed the display of OwnershipCard with aggregated relations by loading relations when getting children of entity. + This allows the already existing recursive method to work properly when children of entity have children themselves. +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-org-react@0.1.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-pagerduty@0.6.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-home-react@0.1.4-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-periskop@0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-periskop-backend@0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + +## @backstage/plugin-permission-backend@0.5.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-permission-node@0.7.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/plugin-playlist@0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-playlist-common@0.1.10 + +## @backstage/plugin-playlist-backend@0.3.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-playlist-common@0.1.10 + +## @backstage/plugin-proxy-backend@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + +## @backstage/plugin-puppetdb@0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-rollbar@0.4.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-rollbar-backend@0.1.50-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + +## @backstage/plugin-scaffolder@1.15.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-scaffolder-react@1.5.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-scaffolder-common@1.4.1 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-node@0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.1 + +## @backstage/plugin-scaffolder-react@1.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-scaffolder-common@1.4.1 + +## @backstage/plugin-search@1.4.1-next.1 + +### Patch Changes + +- e5a2956dd2: Create an experimental search plugin that is compatible with the declarative integration system, it is exported from `/alpha` subpath. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-search-backend@1.4.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/backend-openapi-utils@0.0.4 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-search-backend-module-catalog@0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-search-backend-module-explore@0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-search-backend-module-pg@0.5.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-search-backend-module-techdocs@0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-techdocs-node@1.8.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-search-backend-node@1.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-search-react@1.7.1-next.1 + +### Patch Changes + +- 703a4ffc5b: Create `createSearchResultListItem` alpha version that only supports declarative integration. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/frontend-app-api@0.2.0-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-sentry@0.5.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-shortcuts@0.3.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-sonarqube@0.7.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-sonarqube-react@0.1.9-next.0 + +## @backstage/plugin-sonarqube-backend@0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + +## @backstage/plugin-splunk-on-call@0.4.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-stack-overflow@0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-home-react@0.1.4-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-stack-overflow-backend@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-stackstorm@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-tech-insights@0.3.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend@0.5.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-tech-insights-node@0.4.11-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.37-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-tech-insights-node@0.4.11-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-node@0.4.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-radar@0.6.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-techdocs@1.7.1-next.1 + +### Patch Changes + +- 4918f65ab2: Create an experimental `TechDocsSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- df449a7a31: Add kind column by default to TechDocsTable +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/plugin-techdocs@1.7.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/test-utils@1.4.4-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-techdocs-backend@1.7.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.9-next.1 + - @backstage/plugin-techdocs-node@1.8.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + +## @backstage/plugin-techdocs-node@1.8.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-search-common@1.2.6 + +## @backstage/plugin-techdocs-react@1.1.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/version-bridge@1.0.5 + +## @backstage/plugin-todo@0.2.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-todo-backend@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/backend-openapi-utils@0.0.4 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + +## @backstage/plugin-user-settings@0.7.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-user-settings-backend@0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-vault@0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## @backstage/plugin-vault-backend@0.3.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + +## @backstage/plugin-xcmetrics@0.2.44-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + +## example-app@0.2.88-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-org@0.6.15-next.1 + - @backstage/plugin-code-coverage@0.2.18-next.1 + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/plugin-techdocs@1.7.1-next.1 + - @backstage/plugin-home@0.5.9-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/app-defaults@1.4.4-next.1 + - @backstage/frontend-app-api@0.2.0-next.1 + - @backstage/plugin-search@1.4.1-next.1 + - @backstage/cli@0.23.0-next.1 + - @backstage/plugin-cost-insights@0.12.14-next.1 + - @backstage/plugin-kubernetes@0.11.0-next.1 + - @backstage/plugin-adr@0.6.8-next.1 + - @backstage/plugin-explore@0.4.11-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-api-docs@0.9.12-next.1 + - @backstage/plugin-catalog-graph@0.2.37-next.1 + - @backstage/plugin-scaffolder@1.15.1-next.1 + - @backstage/plugin-scaffolder-react@1.5.6-next.1 + - @backstage/plugin-user-settings@0.7.11-next.1 + - @backstage/plugin-graphiql@0.2.55-next.1 + - @backstage/plugin-tech-radar@0.6.9-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-airbrake@0.3.25-next.1 + - @backstage/plugin-apache-airflow@0.2.16-next.1 + - @backstage/plugin-azure-devops@0.3.7-next.1 + - @backstage/plugin-azure-sites@0.1.14-next.1 + - @backstage/plugin-badges@0.2.49-next.1 + - @backstage/plugin-catalog-import@0.10.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.1 + - @backstage/plugin-circleci@0.3.25-next.1 + - @backstage/plugin-cloudbuild@0.3.25-next.1 + - @backstage/plugin-devtools@0.1.5-next.1 + - @backstage/plugin-dynatrace@7.0.5-next.1 + - @backstage/plugin-entity-feedback@0.2.8-next.1 + - @backstage/plugin-gcalendar@0.3.19-next.1 + - @backstage/plugin-gcp-projects@0.3.42-next.1 + - @backstage/plugin-github-actions@0.6.6-next.1 + - @backstage/plugin-gocd@0.1.31-next.1 + - @backstage/plugin-jenkins@0.8.7-next.1 + - @backstage/plugin-kafka@0.3.25-next.1 + - @backstage/plugin-lighthouse@0.4.10-next.1 + - @backstage/plugin-linguist@0.1.10-next.1 + - @backstage/plugin-microsoft-calendar@0.1.8-next.1 + - @backstage/plugin-newrelic@0.3.41-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.18-next.1 + - @backstage/plugin-nomad@0.1.6-next.1 + - @backstage/plugin-octopus-deploy@0.2.7-next.1 + - @backstage/plugin-pagerduty@0.6.6-next.1 + - @backstage/plugin-playlist@0.1.17-next.1 + - @backstage/plugin-puppetdb@0.1.8-next.1 + - @backstage/plugin-rollbar@0.4.25-next.1 + - @backstage/plugin-sentry@0.5.10-next.1 + - @backstage/plugin-shortcuts@0.3.15-next.1 + - @backstage/plugin-stack-overflow@0.1.21-next.1 + - @backstage/plugin-stackstorm@0.1.7-next.1 + - @backstage/plugin-tech-insights@0.3.17-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/plugin-todo@0.2.28-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.6 + +## example-app-next@0.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-org@0.6.15-next.1 + - @backstage/plugin-code-coverage@0.2.18-next.1 + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/plugin-techdocs@1.7.1-next.1 + - @backstage/plugin-home@0.5.9-next.1 + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/app-defaults@1.4.4-next.1 + - @backstage/frontend-app-api@0.2.0-next.1 + - @backstage/plugin-search@1.4.1-next.1 + - @backstage/cli@0.23.0-next.1 + - @backstage/plugin-cost-insights@0.12.14-next.1 + - @backstage/plugin-kubernetes@0.11.0-next.1 + - @backstage/plugin-adr@0.6.8-next.1 + - @backstage/plugin-explore@0.4.11-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-api-docs@0.9.12-next.1 + - @backstage/plugin-catalog-graph@0.2.37-next.1 + - @backstage/plugin-scaffolder@1.15.1-next.1 + - @backstage/plugin-scaffolder-react@1.5.6-next.1 + - @backstage/plugin-user-settings@0.7.11-next.1 + - app-next-example-plugin@0.0.2-next.1 + - @backstage/plugin-graphiql@0.2.55-next.1 + - @backstage/plugin-tech-radar@0.6.9-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-airbrake@0.3.25-next.1 + - @backstage/plugin-apache-airflow@0.2.16-next.1 + - @backstage/plugin-azure-devops@0.3.7-next.1 + - @backstage/plugin-azure-sites@0.1.14-next.1 + - @backstage/plugin-badges@0.2.49-next.1 + - @backstage/plugin-catalog-import@0.10.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.1 + - @backstage/plugin-circleci@0.3.25-next.1 + - @backstage/plugin-cloudbuild@0.3.25-next.1 + - @backstage/plugin-devtools@0.1.5-next.1 + - @backstage/plugin-dynatrace@7.0.5-next.1 + - @backstage/plugin-entity-feedback@0.2.8-next.1 + - @backstage/plugin-gcalendar@0.3.19-next.1 + - @backstage/plugin-gcp-projects@0.3.42-next.1 + - @backstage/plugin-github-actions@0.6.6-next.1 + - @backstage/plugin-gocd@0.1.31-next.1 + - @backstage/plugin-jenkins@0.8.7-next.1 + - @backstage/plugin-kafka@0.3.25-next.1 + - @backstage/plugin-lighthouse@0.4.10-next.1 + - @backstage/plugin-linguist@0.1.10-next.1 + - @backstage/plugin-microsoft-calendar@0.1.8-next.1 + - @backstage/plugin-newrelic@0.3.41-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.18-next.1 + - @backstage/plugin-octopus-deploy@0.2.7-next.1 + - @backstage/plugin-pagerduty@0.6.6-next.1 + - @backstage/plugin-playlist@0.1.17-next.1 + - @backstage/plugin-puppetdb@0.1.8-next.1 + - @backstage/plugin-rollbar@0.4.25-next.1 + - @backstage/plugin-sentry@0.5.10-next.1 + - @backstage/plugin-shortcuts@0.3.15-next.1 + - @backstage/plugin-stack-overflow@0.1.21-next.1 + - @backstage/plugin-stackstorm@0.1.7-next.1 + - @backstage/plugin-tech-insights@0.3.17-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/plugin-todo@0.2.28-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.6 + +## app-next-example-plugin@0.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + +## example-backend@0.2.88-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-scaffolder-backend@1.18.0-next.1 + - @backstage/plugin-badges-backend@0.3.2-next.1 + - @backstage/plugin-lighthouse-backend@0.3.2-next.1 + - @backstage/plugin-linguist-backend@0.5.2-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.9-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.9-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.9-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-tech-insights-backend@0.5.19-next.1 + - @backstage/plugin-tech-insights-node@0.4.11-next.1 + - example-app@0.2.88-next.1 + - @backstage/plugin-auth-backend@0.19.2-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.2-next.1 + - @backstage/plugin-kubernetes-backend@0.12.2-next.1 + - @backstage/plugin-todo-backend@0.3.3-next.1 + - @backstage/plugin-adr-backend@0.4.2-next.1 + - @backstage/plugin-app-backend@0.3.53-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-azure-devops-backend@0.4.2-next.1 + - @backstage/plugin-azure-sites-backend@0.1.15-next.1 + - @backstage/plugin-code-coverage-backend@0.2.19-next.1 + - @backstage/plugin-devtools-backend@0.2.2-next.1 + - @backstage/plugin-entity-feedback-backend@0.2.2-next.1 + - @backstage/plugin-events-backend@0.2.14-next.1 + - @backstage/plugin-explore-backend@0.0.15-next.1 + - @backstage/plugin-graphql-backend@0.1.43-next.1 + - @backstage/plugin-jenkins-backend@0.2.8-next.1 + - @backstage/plugin-kafka-backend@0.3.2-next.1 + - @backstage/plugin-nomad-backend@0.1.7-next.1 + - @backstage/plugin-permission-backend@0.5.28-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-playlist-backend@0.3.9-next.1 + - @backstage/plugin-proxy-backend@0.4.2-next.1 + - @backstage/plugin-rollbar-backend@0.1.50-next.1 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.6-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.22-next.1 + - @backstage/plugin-search-backend@1.4.5-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.8-next.1 + - @backstage/plugin-search-backend-module-pg@0.5.14-next.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.37-next.1 + - @backstage/plugin-techdocs-backend@1.7.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.2-next.1 + - @backstage/plugin-events-node@0.2.14-next.1 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + +## example-backend-next@0.0.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-scaffolder-backend@1.18.0-next.1 + - @backstage/plugin-badges-backend@0.3.2-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-lighthouse-backend@0.3.2-next.1 + - @backstage/plugin-linguist-backend@0.5.2-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.9-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.9-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.9-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.2-next.1 + - @backstage/plugin-kubernetes-backend@0.12.2-next.1 + - @backstage/plugin-todo-backend@0.3.3-next.1 + - @backstage/backend-defaults@0.2.5-next.1 + - @backstage/plugin-adr-backend@0.4.2-next.1 + - @backstage/plugin-app-backend@0.3.53-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-azure-devops-backend@0.4.2-next.1 + - @backstage/plugin-devtools-backend@0.2.2-next.1 + - @backstage/plugin-entity-feedback-backend@0.2.2-next.1 + - @backstage/plugin-permission-backend@0.5.28-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-playlist-backend@0.3.9-next.1 + - @backstage/plugin-proxy-backend@0.4.2-next.1 + - @backstage/plugin-search-backend@1.4.5-next.1 + - @backstage/plugin-sonarqube-backend@0.2.7-next.1 + - @backstage/plugin-techdocs-backend@1.7.2-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.2-next.1 + - @backstage/plugin-permission-common@0.7.8 + +## @backstage/backend-plugin-manager@0.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-events-backend@0.2.14-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.0 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.14-next.1 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + +## e2e-test@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.6-next.1 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/errors@1.2.2 + +## techdocs-cli-embedded-app@0.2.87-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/plugin-techdocs@1.7.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/app-defaults@1.4.4-next.1 + - @backstage/test-utils@1.4.4-next.1 + - @backstage/cli@0.23.0-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + +## @internal/plugin-todo-list@1.0.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + +## @internal/plugin-todo-list-backend@1.0.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 diff --git a/package.json b/package.json index 89a10072ef..7b7d962780 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "jest-haste-map@^29.4.3": "patch:jest-haste-map@npm%3A29.4.3#./.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch", "mock-fs@^5.2.0": "patch:mock-fs@npm%3A5.2.0#./.yarn/patches/mock-fs-npm-5.2.0-5103a7b507.patch" }, - "version": "1.19.0-next.0", + "version": "1.19.0-next.1", "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 4b37388ccd..573ef62905 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/app-defaults +## 1.4.4-next.1 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/theme@0.4.2 + ## 1.4.4-next.0 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 4a4578c94d..b583443902 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.4.4-next.0", + "version": "1.4.4-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app-next-example-plugin/CHANGELOG.md b/packages/app-next-example-plugin/CHANGELOG.md index 03e627520d..22136e2b59 100644 --- a/packages/app-next-example-plugin/CHANGELOG.md +++ b/packages/app-next-example-plugin/CHANGELOG.md @@ -1,5 +1,13 @@ # app-next-example-plugin +## 0.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + ## 0.0.2-next.0 ### Patch Changes diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index 300db8d39a..ad797aaeb7 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -1,7 +1,7 @@ { "name": "app-next-example-plugin", "description": "Backstage internal example plugin", - "version": "0.0.2-next.0", + "version": "0.0.2-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index b70579bbed..b9aa117f5b 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,82 @@ # example-app-next +## 0.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-org@0.6.15-next.1 + - @backstage/plugin-code-coverage@0.2.18-next.1 + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/plugin-techdocs@1.7.1-next.1 + - @backstage/plugin-home@0.5.9-next.1 + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/app-defaults@1.4.4-next.1 + - @backstage/frontend-app-api@0.2.0-next.1 + - @backstage/plugin-search@1.4.1-next.1 + - @backstage/cli@0.23.0-next.1 + - @backstage/plugin-cost-insights@0.12.14-next.1 + - @backstage/plugin-kubernetes@0.11.0-next.1 + - @backstage/plugin-adr@0.6.8-next.1 + - @backstage/plugin-explore@0.4.11-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-api-docs@0.9.12-next.1 + - @backstage/plugin-catalog-graph@0.2.37-next.1 + - @backstage/plugin-scaffolder@1.15.1-next.1 + - @backstage/plugin-scaffolder-react@1.5.6-next.1 + - @backstage/plugin-user-settings@0.7.11-next.1 + - app-next-example-plugin@0.0.2-next.1 + - @backstage/plugin-graphiql@0.2.55-next.1 + - @backstage/plugin-tech-radar@0.6.9-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-airbrake@0.3.25-next.1 + - @backstage/plugin-apache-airflow@0.2.16-next.1 + - @backstage/plugin-azure-devops@0.3.7-next.1 + - @backstage/plugin-azure-sites@0.1.14-next.1 + - @backstage/plugin-badges@0.2.49-next.1 + - @backstage/plugin-catalog-import@0.10.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.1 + - @backstage/plugin-circleci@0.3.25-next.1 + - @backstage/plugin-cloudbuild@0.3.25-next.1 + - @backstage/plugin-devtools@0.1.5-next.1 + - @backstage/plugin-dynatrace@7.0.5-next.1 + - @backstage/plugin-entity-feedback@0.2.8-next.1 + - @backstage/plugin-gcalendar@0.3.19-next.1 + - @backstage/plugin-gcp-projects@0.3.42-next.1 + - @backstage/plugin-github-actions@0.6.6-next.1 + - @backstage/plugin-gocd@0.1.31-next.1 + - @backstage/plugin-jenkins@0.8.7-next.1 + - @backstage/plugin-kafka@0.3.25-next.1 + - @backstage/plugin-lighthouse@0.4.10-next.1 + - @backstage/plugin-linguist@0.1.10-next.1 + - @backstage/plugin-microsoft-calendar@0.1.8-next.1 + - @backstage/plugin-newrelic@0.3.41-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.18-next.1 + - @backstage/plugin-octopus-deploy@0.2.7-next.1 + - @backstage/plugin-pagerduty@0.6.6-next.1 + - @backstage/plugin-playlist@0.1.17-next.1 + - @backstage/plugin-puppetdb@0.1.8-next.1 + - @backstage/plugin-rollbar@0.4.25-next.1 + - @backstage/plugin-sentry@0.5.10-next.1 + - @backstage/plugin-shortcuts@0.3.15-next.1 + - @backstage/plugin-stack-overflow@0.1.21-next.1 + - @backstage/plugin-stackstorm@0.1.7-next.1 + - @backstage/plugin-tech-insights@0.3.17-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/plugin-todo@0.2.28-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.6 + ## 0.0.2-next.0 ### Patch Changes diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 40e7d75c1e..50ebf77ec2 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.2-next.0", + "version": "0.0.2-next.1", "private": true, "backstage": { "role": "frontend" diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 9fe80276a6..7b14d026a0 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,81 @@ # example-app +## 0.2.88-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-org@0.6.15-next.1 + - @backstage/plugin-code-coverage@0.2.18-next.1 + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/plugin-techdocs@1.7.1-next.1 + - @backstage/plugin-home@0.5.9-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/app-defaults@1.4.4-next.1 + - @backstage/frontend-app-api@0.2.0-next.1 + - @backstage/plugin-search@1.4.1-next.1 + - @backstage/cli@0.23.0-next.1 + - @backstage/plugin-cost-insights@0.12.14-next.1 + - @backstage/plugin-kubernetes@0.11.0-next.1 + - @backstage/plugin-adr@0.6.8-next.1 + - @backstage/plugin-explore@0.4.11-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-api-docs@0.9.12-next.1 + - @backstage/plugin-catalog-graph@0.2.37-next.1 + - @backstage/plugin-scaffolder@1.15.1-next.1 + - @backstage/plugin-scaffolder-react@1.5.6-next.1 + - @backstage/plugin-user-settings@0.7.11-next.1 + - @backstage/plugin-graphiql@0.2.55-next.1 + - @backstage/plugin-tech-radar@0.6.9-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-airbrake@0.3.25-next.1 + - @backstage/plugin-apache-airflow@0.2.16-next.1 + - @backstage/plugin-azure-devops@0.3.7-next.1 + - @backstage/plugin-azure-sites@0.1.14-next.1 + - @backstage/plugin-badges@0.2.49-next.1 + - @backstage/plugin-catalog-import@0.10.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.1 + - @backstage/plugin-circleci@0.3.25-next.1 + - @backstage/plugin-cloudbuild@0.3.25-next.1 + - @backstage/plugin-devtools@0.1.5-next.1 + - @backstage/plugin-dynatrace@7.0.5-next.1 + - @backstage/plugin-entity-feedback@0.2.8-next.1 + - @backstage/plugin-gcalendar@0.3.19-next.1 + - @backstage/plugin-gcp-projects@0.3.42-next.1 + - @backstage/plugin-github-actions@0.6.6-next.1 + - @backstage/plugin-gocd@0.1.31-next.1 + - @backstage/plugin-jenkins@0.8.7-next.1 + - @backstage/plugin-kafka@0.3.25-next.1 + - @backstage/plugin-lighthouse@0.4.10-next.1 + - @backstage/plugin-linguist@0.1.10-next.1 + - @backstage/plugin-microsoft-calendar@0.1.8-next.1 + - @backstage/plugin-newrelic@0.3.41-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.18-next.1 + - @backstage/plugin-nomad@0.1.6-next.1 + - @backstage/plugin-octopus-deploy@0.2.7-next.1 + - @backstage/plugin-pagerduty@0.6.6-next.1 + - @backstage/plugin-playlist@0.1.17-next.1 + - @backstage/plugin-puppetdb@0.1.8-next.1 + - @backstage/plugin-rollbar@0.4.25-next.1 + - @backstage/plugin-sentry@0.5.10-next.1 + - @backstage/plugin-shortcuts@0.3.15-next.1 + - @backstage/plugin-stack-overflow@0.1.21-next.1 + - @backstage/plugin-stackstorm@0.1.7-next.1 + - @backstage/plugin-tech-insights@0.3.17-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/plugin-todo@0.2.28-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.6 + ## 0.2.88-next.0 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 5b17cc349e..e23da6c8dc 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.88-next.0", + "version": "0.2.88-next.1", "private": true, "backstage": { "role": "frontend" diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index e70c14d84e..cf24e558fd 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/backend-app-api +## 0.5.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + ## 0.5.5-next.0 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index d29b00d036..1b395ff77f 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.5.5-next.0", + "version": "0.5.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 6e761caa41..05aecf893b 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/backend-common +## 0.19.7-next.1 + +### Patch Changes + +- b94f32271e: Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository +- Updated dependencies + - @backstage/backend-dev-utils@0.1.2-next.0 + - @backstage/backend-app-api@0.5.5-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + ## 0.19.7-next.0 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index a887bdc8e7..344a9cdf25 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.19.7-next.0", + "version": "0.19.7-next.1", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 98f39ef7b6..885ea4ced9 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-defaults +## 0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-app-api@0.5.5-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + ## 0.2.5-next.0 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 3aee2f5708..00472e0a7d 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.2.5-next.0", + "version": "0.2.5-next.1", "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 6b505e917e..3710cf3bd5 100644 --- a/packages/backend-dev-utils/CHANGELOG.md +++ b/packages/backend-dev-utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/backend-dev-utils +## 0.1.2-next.0 + +### Patch Changes + +- afa48341fb: Fix an issue where early IPC responses would be lost. + ## 0.1.1 ### Patch Changes diff --git a/packages/backend-dev-utils/package.json b/packages/backend-dev-utils/package.json index 0928032977..8d461b46cf 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.1", + "version": "0.1.2-next.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 92a7b57513..8760f6cff2 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,42 @@ # example-backend-next +## 0.0.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-scaffolder-backend@1.18.0-next.1 + - @backstage/plugin-badges-backend@0.3.2-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-lighthouse-backend@0.3.2-next.1 + - @backstage/plugin-linguist-backend@0.5.2-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.9-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.9-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.9-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.2-next.1 + - @backstage/plugin-kubernetes-backend@0.12.2-next.1 + - @backstage/plugin-todo-backend@0.3.3-next.1 + - @backstage/backend-defaults@0.2.5-next.1 + - @backstage/plugin-adr-backend@0.4.2-next.1 + - @backstage/plugin-app-backend@0.3.53-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-azure-devops-backend@0.4.2-next.1 + - @backstage/plugin-devtools-backend@0.2.2-next.1 + - @backstage/plugin-entity-feedback-backend@0.2.2-next.1 + - @backstage/plugin-permission-backend@0.5.28-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-playlist-backend@0.3.9-next.1 + - @backstage/plugin-proxy-backend@0.4.2-next.1 + - @backstage/plugin-search-backend@1.4.5-next.1 + - @backstage/plugin-sonarqube-backend@0.2.7-next.1 + - @backstage/plugin-techdocs-backend@1.7.2-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.2-next.1 + - @backstage/plugin-permission-common@0.7.8 + ## 0.0.16-next.0 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 9e2dc78bfd..d0fc53ff58 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.16-next.0", + "version": "0.0.16-next.1", "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 684df46db9..ce19f9a798 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-plugin-api +## 0.6.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + ## 0.6.5-next.0 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index b0da3fc80a..8374a002b8 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.6.5-next.0", + "version": "0.6.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-plugin-manager/CHANGELOG.md b/packages/backend-plugin-manager/CHANGELOG.md index bbf909d421..6e1499eb1b 100644 --- a/packages/backend-plugin-manager/CHANGELOG.md +++ b/packages/backend-plugin-manager/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/backend-plugin-manager +## 0.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-events-backend@0.2.14-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.0 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.14-next.1 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + ## 0.0.2-next.0 ### Patch Changes diff --git a/packages/backend-plugin-manager/package.json b/packages/backend-plugin-manager/package.json index acf15928b0..67697981a1 100644 --- a/packages/backend-plugin-manager/package.json +++ b/packages/backend-plugin-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-manager", "description": "Backstage plugin management backend", - "version": "0.0.2-next.0", + "version": "0.0.2-next.1", "private": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index d8a7cc3754..bd1284aaf5 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/backend-tasks +## 0.5.10-next.1 + +### Patch Changes + +- 5db102bfdf: Instrument `backend-tasks` with some counters and histograms for duration. + + `backend_tasks.task.runs.count`: Counter with the total number of times a task has been run. + `backend_tasks.task.runs.duration`: Histogram with the run durations for each task. + + Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping. + +- ddd76ac98d: Fix bug where backend tasks that are defined with HumanDuration are immediately triggered on application startup +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + ## 0.5.10-next.0 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 197caae774..9a42aab169 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.5.10-next.0", + "version": "0.5.10-next.1", "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 ba53fae7f7..5bd1c6d498 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/backend-test-utils +## 0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-app-api@0.5.5-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + ## 0.2.6-next.0 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 5274b49ce2..04be07ed33 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.2.6-next.0", + "version": "0.2.6-next.1", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 5d89212a42..07105a0417 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,64 @@ # example-backend +## 0.2.88-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-scaffolder-backend@1.18.0-next.1 + - @backstage/plugin-badges-backend@0.3.2-next.1 + - @backstage/plugin-lighthouse-backend@0.3.2-next.1 + - @backstage/plugin-linguist-backend@0.5.2-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.9-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.9-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.9-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-tech-insights-backend@0.5.19-next.1 + - @backstage/plugin-tech-insights-node@0.4.11-next.1 + - example-app@0.2.88-next.1 + - @backstage/plugin-auth-backend@0.19.2-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.2-next.1 + - @backstage/plugin-kubernetes-backend@0.12.2-next.1 + - @backstage/plugin-todo-backend@0.3.3-next.1 + - @backstage/plugin-adr-backend@0.4.2-next.1 + - @backstage/plugin-app-backend@0.3.53-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-azure-devops-backend@0.4.2-next.1 + - @backstage/plugin-azure-sites-backend@0.1.15-next.1 + - @backstage/plugin-code-coverage-backend@0.2.19-next.1 + - @backstage/plugin-devtools-backend@0.2.2-next.1 + - @backstage/plugin-entity-feedback-backend@0.2.2-next.1 + - @backstage/plugin-events-backend@0.2.14-next.1 + - @backstage/plugin-explore-backend@0.0.15-next.1 + - @backstage/plugin-graphql-backend@0.1.43-next.1 + - @backstage/plugin-jenkins-backend@0.2.8-next.1 + - @backstage/plugin-kafka-backend@0.3.2-next.1 + - @backstage/plugin-nomad-backend@0.1.7-next.1 + - @backstage/plugin-permission-backend@0.5.28-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-playlist-backend@0.3.9-next.1 + - @backstage/plugin-proxy-backend@0.4.2-next.1 + - @backstage/plugin-rollbar-backend@0.1.50-next.1 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.6-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.22-next.1 + - @backstage/plugin-search-backend@1.4.5-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.8-next.1 + - @backstage/plugin-search-backend-module-pg@0.5.14-next.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.37-next.1 + - @backstage/plugin-techdocs-backend@1.7.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.2-next.1 + - @backstage/plugin-events-node@0.2.14-next.1 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + ## 0.2.88-next.0 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 2f2ae70e21..8519a5ed71 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.88-next.0", + "version": "0.2.88-next.1", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index f9a93b9b44..d9d7c426e3 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/cli +## 0.23.0-next.1 + +### Patch Changes + +- d0f26cfa4f: Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows. +- Updated dependencies + - @backstage/config@1.1.0 + - @backstage/release-manifests@0.0.10 + - @backstage/catalog-model@1.4.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/errors@1.2.2 + - @backstage/eslint-plugin@0.1.3 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + ## 0.23.0-next.0 ### Minor Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 2f9f6109f0..ee1eb52a2c 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.23.0-next.0", + "version": "0.23.0-next.1", "publishConfig": { "access": "public" }, diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index dca0c73af9..20c6013ee0 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/core-app-api +## 1.10.1-next.1 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + ## 1.10.1-next.0 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index ab8fc9a155..4d9e8f0430 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.10.1-next.0", + "version": "1.10.1-next.1", "publishConfig": { "access": "public" }, diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 9cf62f2694..1cab780f55 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/core-components +## 0.13.6-next.1 + +### Patch Changes + +- 4eab5cf901: The `TabbedLayout` component will now also navigate when clicking the active tab, which allows for navigation back from any sub routes. +- 997a71850c: Changed SupportButton menuitems to support text wrap +- 16126dbe6a: Change overlay header colors in the mobile menu to use navigation color from the theme +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/version-bridge@1.0.5 + ## 0.13.6-next.0 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 2d534609c2..155f0a09c4 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.13.6-next.0", + "version": "0.13.6-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 3d9f76e93d..fed5a6b936 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/create-app +## 0.5.6-next.1 + +### Patch Changes + +- 8d2e640af4: Added missing `.eslintignore` file + + To apply this change to an existing app, create a new `.eslintignore` file at the root of your project with the following content: + + ```diff + + playwright.config.ts + ``` + +- Updated dependencies + - @backstage/cli-common@0.1.13-next.0 + ## 0.5.6-next.0 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index c46d4f43fa..6ae88a8e4c 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.5.6-next.0", + "version": "0.5.6-next.1", "publishConfig": { "access": "public" }, diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 714ca3bd1f..300d3dad2f 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/dev-utils +## 1.0.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/app-defaults@1.4.4-next.1 + - @backstage/test-utils@1.4.4-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 1.0.22-next.0 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index fb2b086d44..dec37f3cea 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.22-next.0", + "version": "1.0.22-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index 1fdf65a72e..4c47b33e86 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,14 @@ # e2e-test +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.6-next.1 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/errors@1.2.2 + ## 0.2.8-next.0 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 1308c60d96..8b1499446a 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.8-next.0", + "version": "0.2.8-next.1", "private": true, "backstage": { "role": "cli" diff --git a/packages/frontend-app-api/CHANGELOG.md b/packages/frontend-app-api/CHANGELOG.md index a1228e084c..90d7ba70d2 100644 --- a/packages/frontend-app-api/CHANGELOG.md +++ b/packages/frontend-app-api/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/frontend-app-api +## 0.2.0-next.1 + +### Patch Changes + +- 52366db5b3: Make themes configurable through extensions, and switched default themes to use extensions instead. +- e5a2956dd2: Register default api implementations when creating declarative integrated apps. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/plugin-graphiql@0.2.55-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + ## 0.2.0-next.0 ### Minor Changes diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index 6c45e9239a..5fb84070d4 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-app-api", - "version": "0.2.0-next.0", + "version": "0.2.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/frontend-plugin-api/CHANGELOG.md b/packages/frontend-plugin-api/CHANGELOG.md index 22620aebe2..2295989418 100644 --- a/packages/frontend-plugin-api/CHANGELOG.md +++ b/packages/frontend-plugin-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/frontend-plugin-api +## 0.1.1-next.1 + +### Patch Changes + +- d3a37f55c0: Add support for `SidebarGroup` on the sidebar item extension. +- 52366db5b3: Added `createThemeExtension` and `coreExtensionData.theme`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/types@1.1.1 + ## 0.1.1-next.0 ### Patch Changes diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 8e71544393..7785b03b7d 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-plugin-api", - "version": "0.1.1-next.0", + "version": "0.1.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 1f6cd21668..8ef2df3709 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/integration-react +## 1.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + ## 1.1.20-next.0 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 89d7cf48e9..55e15f9b22 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.20-next.0", + "version": "1.1.20-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 2e07601451..45494ccba1 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.87-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/plugin-techdocs@1.7.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/app-defaults@1.4.4-next.1 + - @backstage/test-utils@1.4.4-next.1 + - @backstage/cli@0.23.0-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.2.87-next.0 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 7c5ceaf795..21eee41e19 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.87-next.0", + "version": "0.2.87-next.1", "private": true, "backstage": { "role": "frontend" diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index f24e216273..abafa808fc 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @techdocs/cli +## 1.5.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-techdocs-node@1.8.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/cli-common@0.1.13-next.0 + ## 1.5.2-next.0 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 6991e2a2c2..14120ab801 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.5.2-next.0", + "version": "1.5.2-next.1", "publishConfig": { "access": "public" }, diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index f65db68aff..4cab843d01 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/test-utils +## 1.4.4-next.1 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- Updated dependencies + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + ## 1.4.4-next.0 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 9c4c1642f6..b972a6a824 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.4.4-next.0", + "version": "1.4.4-next.1", "publishConfig": { "access": "public" }, diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index 16bf9fbc56..e2acb92554 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-adr-backend +## 0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-adr-common@0.2.16-next.0 + - @backstage/plugin-search-common@1.2.6 + ## 0.4.2-next.0 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index ebb9367362..580e3064af 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.4.2-next.0", + "version": "0.4.2-next.1", "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 0694cedf65..950e2c7ca3 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-adr +## 0.6.8-next.1 + +### Patch Changes + +- 1204e7628e: Create an experimental `AdrSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-adr-common@0.2.16-next.0 + - @backstage/plugin-search-common@1.2.6 + ## 0.6.8-next.0 ### Patch Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index d0db1a4ff2..94d8250993 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.6.8-next.0", + "version": "0.6.8-next.1", "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 ec047a0b83..ba6e94f7eb 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-airbrake-backend +## 0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + ## 0.3.2-next.0 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 3b3b21fbcb..e7bbcc9310 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.3.2-next.0", + "version": "0.3.2-next.1", "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 9e80ddf32d..712f785b2e 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-airbrake +## 0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/test-utils@1.4.4-next.1 + - @backstage/dev-utils@1.0.22-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.3.25-next.0 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 768c9c203e..003da7d232 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.25-next.0", + "version": "0.3.25-next.1", "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 04339609a4..956f4d79fa 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-allure +## 0.1.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.1.41-next.0 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index cf33ee8696..fde188d1c8 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.41-next.0", + "version": "0.1.41-next.1", "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 c84c40b236..251990d5c3 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.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + ## 0.1.34-next.0 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 006a36a490..86f0a4204e 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.34-next.0", + "version": "0.1.34-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga4/CHANGELOG.md b/plugins/analytics-module-ga4/CHANGELOG.md index 8f339c47e1..d79ec11dea 100644 --- a/plugins/analytics-module-ga4/CHANGELOG.md +++ b/plugins/analytics-module-ga4/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-ga4 +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index fd3f6de64f..ab9611f5e8 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga4", - "version": "0.1.5-next.0", + "version": "0.1.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-newrelic-browser/CHANGELOG.md b/plugins/analytics-module-newrelic-browser/CHANGELOG.md index 9b62fe7596..7bfaf1c262 100644 --- a/plugins/analytics-module-newrelic-browser/CHANGELOG.md +++ b/plugins/analytics-module-newrelic-browser/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-analytics-module-newrelic-browser +## 0.0.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + ## 0.0.3-next.0 ### Patch Changes diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index 0f2f01705a..c27be5f94e 100644 --- a/plugins/analytics-module-newrelic-browser/package.json +++ b/plugins/analytics-module-newrelic-browser/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-newrelic-browser", - "version": "0.0.3-next.0", + "version": "0.0.3-next.1", "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 76f6ea95ed..4c0f6a418d 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-apache-airflow +## 0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index ec4bf91916..28f8f81ab0 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.16-next.0", + "version": "0.2.16-next.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 60f00d29d5..021c55b807 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-api-docs +## 0.9.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.9.12-next.0 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index b9d7a1b6f5..f257d85d82 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.12-next.0", + "version": "0.9.12-next.1", "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 3b5dd74b31..869e487cff 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-apollo-explorer +## 0.1.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + ## 0.1.16-next.0 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index cebc6f8637..6c7eb11c50 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.16-next.0", + "version": "0.1.16-next.1", "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 d3ea6acc47..d54709fbc2 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-app-backend +## 0.3.53-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.5-next.1 + ## 0.3.53-next.0 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index cdbb36d23c..0c0ecc8f60 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.53-next.0", + "version": "0.3.53-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-node/CHANGELOG.md b/plugins/app-node/CHANGELOG.md index 48bdd793af..d1d2284dce 100644 --- a/plugins/app-node/CHANGELOG.md +++ b/plugins/app-node/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-app-node +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json index 9a722915c0..5e21650501 100644 --- a/plugins/app-node/package.json +++ b/plugins/app-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-node", "description": "Node.js library for the app plugin", - "version": "0.1.5-next.0", + "version": "0.1.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md index bc44a30fd2..8c14e20d07 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-auth-backend-module-gcp-iap-provider +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-gcp-iap-provider/package.json b/plugins/auth-backend-module-gcp-iap-provider/package.json index a115450273..7e9cd78fa4 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/package.json +++ b/plugins/auth-backend-module-gcp-iap-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-gcp-iap-provider", "description": "A GCP IAP auth provider module for the Backstage auth backend", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-github-provider/CHANGELOG.md b/plugins/auth-backend-module-github-provider/CHANGELOG.md index 3055ce643c..d98d330281 100644 --- a/plugins/auth-backend-module-github-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-github-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-github-provider +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-github-provider/package.json b/plugins/auth-backend-module-github-provider/package.json index b06ee136fa..25563c32c5 100644 --- a/plugins/auth-backend-module-github-provider/package.json +++ b/plugins/auth-backend-module-github-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-github-provider", "description": "The github-provider backend module for the auth plugin.", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md index 4a29c21c58..cafc7ec1a4 100644 --- a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-gitlab-provider +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-gitlab-provider/package.json b/plugins/auth-backend-module-gitlab-provider/package.json index e626a02d3a..e039faf1a2 100644 --- a/plugins/auth-backend-module-gitlab-provider/package.json +++ b/plugins/auth-backend-module-gitlab-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-gitlab-provider", "description": "The gitlab-provider backend module for the auth plugin.", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-google-provider/CHANGELOG.md b/plugins/auth-backend-module-google-provider/CHANGELOG.md index bdb1d576a5..974a3c1dfe 100644 --- a/plugins/auth-backend-module-google-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-google-provider/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-backend-module-google-provider +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-google-provider/package.json b/plugins/auth-backend-module-google-provider/package.json index e5dc87ca71..46adb1148e 100644 --- a/plugins/auth-backend-module-google-provider/package.json +++ b/plugins/auth-backend-module-google-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-google-provider", "description": "A Google auth provider module for the Backstage auth backend", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md index f15ef3bad8..f2437a2e73 100644 --- a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-oauth2-provider +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-provider/package.json b/plugins/auth-backend-module-oauth2-provider/package.json index e18e50f44d..3e53ba5954 100644 --- a/plugins/auth-backend-module-oauth2-provider/package.json +++ b/plugins/auth-backend-module-oauth2-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-provider", "description": "The oauth2-provider backend module for the auth plugin.", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "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 2460e7626c..f2eadd6c3d 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-auth-backend +## 0.19.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.1.2-next.1 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.2-next.1 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.2-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.1.2-next.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.2-next.1 + ## 0.19.2-next.0 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index e10568aaec..398814564e 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.19.2-next.0", + "version": "0.19.2-next.1", "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 c3bdb44cb1..2dcd93dc51 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-auth-node +## 0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + ## 0.3.2-next.0 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 64b2ab4558..91ae1b5e6a 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.3.2-next.0", + "version": "0.3.2-next.1", "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 629bcba049..f38133089c 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-azure-devops-backend +## 0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-azure-devops-common@0.3.1 + ## 0.4.2-next.0 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index bc8d07b040..1da72ae8dc 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.4.2-next.0", + "version": "0.4.2-next.1", "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 cc4f6f1e26..eee90fe4b2 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-azure-devops +## 0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-azure-devops-common@0.3.1 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index f338307ba0..f47811bf58 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.3.7-next.0", + "version": "0.3.7-next.1", "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 06c9538119..fe92430af1 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.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-azure-sites-common@0.1.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index 0aa06b3e4e..d1c9c6c2b7 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.15-next.0", + "version": "0.1.15-next.1", "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 ef4d64fbba..3f044f2243 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-azure-sites +## 0.1.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-azure-sites-common@0.1.1 + ## 0.1.14-next.0 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index 900fb54b08..d7a4826be1 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.14-next.0", + "version": "0.1.14-next.1", "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 34c2760f7b..3081811eca 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-badges-backend +## 0.3.2-next.1 + +### Patch Changes + +- 817f2acbb1: Make sure the default badge factory is used if nothing is defined +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + ## 0.3.2-next.0 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index c4ffb180c1..4137092f17 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.3.2-next.0", + "version": "0.3.2-next.1", "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 6b880b99eb..c20dd1af3e 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-badges +## 0.2.49-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.2.49-next.0 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index d4d591aa83..d0565cdaf9 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.49-next.0", + "version": "0.2.49-next.1", "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 0606865996..3f3bfb6eaf 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-bazaar-backend +## 0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + ## 0.3.2-next.0 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 1cab7c95d3..28358525ee 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.3.2-next.0", + "version": "0.3.2-next.1", "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 55fdd98b98..d7c48b8802 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-bazaar +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/cli@0.23.0-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.2.17-next.0 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 06613d6aae..4a6ac9530d 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.17-next.0", + "version": "0.2.17-next.1", "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 afc67834b3..6a1c85393c 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-bitrise +## 0.1.52-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.1.52-next.0 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index c94be4551d..bc88d84191 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.52-next.0", + "version": "0.1.52-next.1", "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 70f1e02899..cba33bfb38 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.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index c05a7c0de7..c4891dd2b7 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.2.8-next.0", + "version": "0.2.8-next.1", "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 9864f7ca09..6d1613bf1e 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + ## 0.1.24-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index ea3ae522ee..f8849b4925 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.24-next.0", + "version": "0.1.24-next.1", "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 96890c9c33..4a989d8214 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.13-next.0 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.1.20-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index eb371743c4..40f83d3717 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.20-next.0", + "version": "0.1.20-next.1", "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 245c481327..db98df3fc1 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + ## 0.1.18-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 03547d7883..d86127555f 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.18-next.0", + "version": "0.1.18-next.1", "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 49756558a8..756ad9f1dd 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.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.13-next.0 + ## 0.2.20-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index 64497a2854..41827dc369 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.20-next.0", + "version": "0.2.20-next.1", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/catalog-backend-module-gcp/CHANGELOG.md b/plugins/catalog-backend-module-gcp/CHANGELOG.md index 79bced28f5..0b50b8bf3b 100644 --- a/plugins/catalog-backend-module-gcp/CHANGELOG.md +++ b/plugins/catalog-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-gcp +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json index 66b195273c..dc3ae7395d 100644 --- a/plugins/catalog-backend-module-gcp/package.json +++ b/plugins/catalog-backend-module-gcp/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gcp", "description": "A Backstage catalog backend module that helps integrate towards GCP", - "version": "0.1.5-next.0", + "version": "0.1.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index 486b566635..cbfd993b9f 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + ## 0.1.21-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index a24644181f..9690978a3b 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.21-next.0", + "version": "0.1.21-next.1", "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 1851ecd90b..1cb45ad261 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.4.3-next.1 + +### Patch Changes + +- b4b1cbf9fa: Make `defaultUserTransformer` resolve to `UserEntity` instead of `Entity` +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.4.3-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index a909f1df44..8f22af5f62 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.4.3-next.0", + "version": "0.4.3-next.1", "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 c3457bbc09..6a3633aa8a 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.3.2-next.1 + +### Patch Changes + +- 6ae7f12abb: Make sure the archived projects are skipped with the Gitlab API +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + ## 0.3.2-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 5e81ed5ee6..b3fc853c26 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.3.2-next.0", + "version": "0.3.2-next.1", "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 616890d17b..870514fc08 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.4.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/plugin-events-node@0.2.14-next.1 + - @backstage/plugin-permission-common@0.7.8 + ## 0.4.9-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 93e85e3db5..1d0709b7da 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.4.9-next.0", + "version": "0.4.9-next.1", "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 50c1ea8496..cdf7473ff9 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + ## 0.5.20-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 61eee3a731..d38d746563 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.20-next.0", + "version": "0.5.20-next.1", "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 44924c65f1..7d7f6f3039 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-catalog-common@1.0.16 + ## 0.5.12-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 1fe61cd6b2..112d0b7c34 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.12-next.0", + "version": "0.5.12-next.1", "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 3f7801bd3f..b103bd920d 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + ## 0.1.22-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index cbbf6c8492..52659c8d03 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.22-next.0", + "version": "0.1.22-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index cd71bdec72..7e74c43039 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + ## 0.1.10-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index f54129bbcc..3ec71d1042 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", - "version": "0.1.10-next.0", + "version": "0.1.10-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md index bb3bbb898d..1be951bf47 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md +++ b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-scaffolder-entity-model +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-scaffolder-common@1.4.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/package.json b/plugins/catalog-backend-module-scaffolder-entity-model/package.json index cb8cbc16b5..35f573ec1e 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/package.json +++ b/plugins/catalog-backend-module-scaffolder-entity-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-scaffolder-entity-model", "description": "Adds support for the scaffolder specific entity model (e.g. the Template kind) to the catalog backend plugin.", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md index 2e15a14bfc..2c229f113e 100644 --- a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md +++ b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-backend-module-unprocessed +## 0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/catalog-model@1.4.2 + ## 0.3.2-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index 43e49e793d..2a923fdf87 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-unprocessed", "description": "Backstage Catalog module to view unprocessed entities", - "version": "0.3.2-next.0", + "version": "0.3.2-next.1", "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 305b7bd1d1..6e74d0d408 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-catalog-backend +## 1.14.0-next.1 + +### Patch Changes + +- 7a2e2924c7: Marked the `LocationEntityProcessor` as deprecated, as it is no longer used internally since way back and can even be harmful at this point. +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.9-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/backend-openapi-utils@0.0.4 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-events-node@0.2.14-next.1 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-scaffolder-common@1.4.1 + - @backstage/plugin-search-common@1.2.6 + ## 1.14.0-next.0 ### Minor Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 7ce5d40385..45826a1f39 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.14.0-next.0", + "version": "1.14.0-next.1", "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 456c1b13c9..a9fc8ea29d 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-graph +## 0.2.37-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + ## 0.2.37-next.0 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 6de95b8ec6..77cdee4476 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.37-next.0", + "version": "0.2.37-next.1", "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 1c8cf69ead..97a6070230 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-import +## 0.10.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-catalog-common@1.0.16 + ## 0.10.1-next.0 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index b2661288bd..a982b13373 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.10.1-next.0", + "version": "0.10.1-next.1", "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 4ab1791209..0126011e83 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-node +## 1.4.6-next.1 + +### Patch Changes + +- 7a2e2924c7: Added docs to `processingResult` +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + ## 1.4.6-next.0 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 6e11ee0820..61e9823ea6 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.4.6-next.0", + "version": "1.4.6-next.1", "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 8b1c4bf90e..467f134119 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-react +## 1.8.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + ## 1.8.5-next.0 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index c65be47791..637f83fcee 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.8.5-next.0", + "version": "1.8.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-unprocessed-entities/CHANGELOG.md b/plugins/catalog-unprocessed-entities/CHANGELOG.md index 8e384e95cd..612c02a9a1 100644 --- a/plugins/catalog-unprocessed-entities/CHANGELOG.md +++ b/plugins/catalog-unprocessed-entities/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-unprocessed-entities +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index 0ae64d4feb..735cb05f8d 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-unprocessed-entities", - "version": "0.1.4-next.0", + "version": "0.1.4-next.1", "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 a8fd34773f..648fa4d7a4 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog +## 1.14.0-next.1 + +### Patch Changes + +- 7c4a8e4d5f: Create an experimental `CatalogSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- e5a2956dd2: Migrate catalog api to declarative integration system, it is exported from `/alpha` subpath. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-scaffolder-common@1.4.1 + - @backstage/plugin-search-common@1.2.6 + ## 1.14.0-next.0 ### Minor Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 8ae615ec36..f779220669 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.14.0-next.0", + "version": "1.14.0-next.1", "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 e252bbe784..a1952616bb 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.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-cicd-statistics@0.1.27-next.1 + ## 0.1.21-next.0 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index 2d2062914b..afdd1cd758 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.21-next.0", + "version": "0.1.21-next.1", "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 b195c4bab4..4abb69de10 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cicd-statistics +## 0.1.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + ## 0.1.27-next.0 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index a4a6552cd2..60668da35a 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.27-next.0", + "version": "0.1.27-next.1", "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 c29eda8985..38e797dc35 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-circleci +## 0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.3.25-next.0 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index aca3879232..c1c4c07004 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.25-next.0", + "version": "0.3.25-next.1", "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 ced1a5b5aa..3affd61ba7 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-cloudbuild +## 0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.3.25-next.0 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 42b706ea2d..d09f2372ab 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.25-next.0", + "version": "0.3.25-next.1", "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 2728a0b8b4..9e32befc60 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-code-climate +## 0.1.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.1.25-next.0 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 5f6e89942f..800c97652f 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.25-next.0", + "version": "0.1.25-next.1", "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 3f34c973ce..817fe0d57d 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.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + ## 0.2.19-next.0 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index fb956403b1..761fccda23 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.19-next.0", + "version": "0.2.19-next.1", "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 099fcbd4df..3801f63f61 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-code-coverage +## 0.2.18-next.1 + +### Patch Changes + +- 88b0b32547: Fixed the coverage history statistics to compare newest with oldest record +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.2.18-next.0 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 05d035c45a..f47a44221a 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.18-next.0", + "version": "0.2.18-next.1", "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 45e23b905a..15f34acaf0 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-codescene +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.1.18-next.0 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index aa105dffd6..c57a9c53af 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.18-next.0", + "version": "0.1.18-next.1", "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 877bbe23c2..2c2ac53154 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-config-schema +## 0.1.46-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + ## 0.1.46-next.0 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 1428340190..c623a59dfa 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.46-next.0", + "version": "0.1.46-next.1", "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 5a29cfe729..a51c19f324 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-cost-insights +## 0.12.14-next.1 + +### Patch Changes + +- ba4820883c: Updated dependency `@types/pluralize` to `^0.0.31`. +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-cost-insights-common@0.1.2 + ## 0.12.14-next.0 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 0f3843ddb3..c204616fe4 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.14-next.0", + "version": "0.12.14-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/devtools-backend/CHANGELOG.md b/plugins/devtools-backend/CHANGELOG.md index 4b07850d2d..7fc9c01be5 100644 --- a/plugins/devtools-backend/CHANGELOG.md +++ b/plugins/devtools-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-devtools-backend +## 0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config-loader@1.5.1-next.0 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.4 + - @backstage/plugin-permission-common@0.7.8 + ## 0.2.2-next.0 ### Patch Changes diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index 085b0bf37c..f5311f9cf3 100644 --- a/plugins/devtools-backend/package.json +++ b/plugins/devtools-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools-backend", - "version": "0.2.2-next.0", + "version": "0.2.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/devtools/CHANGELOG.md b/plugins/devtools/CHANGELOG.md index 6d8cdb219d..b858ff2c61 100644 --- a/plugins/devtools/CHANGELOG.md +++ b/plugins/devtools/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-devtools +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.4 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index c1b4fb2f79..62ba643765 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools", - "version": "0.1.5-next.0", + "version": "0.1.5-next.1", "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 a4dc207110..dc1c8cd54d 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-dynatrace +## 7.0.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 7.0.5-next.0 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index c31e336e5c..83395cabb8 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "7.0.5-next.0", + "version": "7.0.5-next.1", "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 6c2224bfcf..8c0b27d2aa 100644 --- a/plugins/entity-feedback-backend/CHANGELOG.md +++ b/plugins/entity-feedback-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-entity-feedback-backend +## 0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.2-next.0 ### Patch Changes diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index 6cf4117995..320748501f 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.2.2-next.0", + "version": "0.2.2-next.1", "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 c5b67f10cf..c5ead7f611 100644 --- a/plugins/entity-feedback/CHANGELOG.md +++ b/plugins/entity-feedback/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-entity-feedback +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 032e6732bc..b04e438e34 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback", - "version": "0.2.8-next.0", + "version": "0.2.8-next.1", "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 985cc6656e..0cb48bd911 100644 --- a/plugins/entity-validation/CHANGELOG.md +++ b/plugins/entity-validation/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-entity-validation +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-catalog-common@1.0.16 + ## 0.1.10-next.0 ### Patch Changes diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index fe9ab02d0f..5f8368aeb0 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.10-next.0", + "version": "0.1.10-next.1", "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 f893794fdb..c45de40839 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.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index c4fad0d1e0..c9825edbff 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.2.8-next.0", + "version": "0.2.8-next.1", "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 f4d1657b0f..4883d87b10 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.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 07b62130a2..18d712e5c4 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.15-next.0", + "version": "0.1.15-next.1", "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 4dbb0932e5..21b4e7e6ca 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.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 4011a3f496..5d6563e8b6 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.15-next.0", + "version": "0.1.15-next.1", "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 96918cd580..aa368e48e4 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.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 89afd8a47c..9b05753c42 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.15-next.0", + "version": "0.1.15-next.1", "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 bcc3afa0ca..16979ed40b 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.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index a85ce50dee..c6cce93bda 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.15-next.0", + "version": "0.1.15-next.1", "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 140b3302ac..24f8a1c574 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.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index 0d8c036303..7e7ca5eb31 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.15-next.0", + "version": "0.1.15-next.1", "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 f98f330f5b..6df0dc6a05 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.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 945cbc2bf2..9d09d999f4 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.15-next.0", + "version": "0.1.15-next.1", "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 6fb1b224d2..9810584a6b 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-events-backend +## 0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-events-node@0.2.14-next.1 + ## 0.2.14-next.0 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index 808ee2b0ec..03028ae833 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.14-next.0", + "version": "0.2.14-next.1", "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 327c63a925..607651ad73 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-events-node +## 0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.5-next.1 + ## 0.2.14-next.0 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index eae224aa62..762b5237b0 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.14-next.0", + "version": "0.2.14-next.1", "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 5dfb9268a6..8c1c37256d 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.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + ## 1.0.18-next.0 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 2659de88bd..3a3a38a5c4 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.18-next.0", + "version": "1.0.18-next.1", "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 9d686f4ffc..04243ee26a 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.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + ## 1.0.18-next.0 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 7af06dc823..589689a59c 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.18-next.0", + "version": "1.0.18-next.1", "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 ec8dcd45cf..4e27d8f124 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-explore-backend +## 0.0.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.9-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.6 + ## 0.0.15-next.0 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index ba5995651a..1e8a4a456b 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.15-next.0", + "version": "0.0.15-next.1", "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 81041c46df..480d85437d 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-explore +## 0.4.11-next.1 + +### Patch Changes + +- 0f10c53a05: Create an experimental `ExploreSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-explore-react@0.0.32-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.6 + ## 0.4.11-next.0 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index dcf0b75577..0462d60884 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.11-next.0", + "version": "0.4.11-next.1", "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 0eab08760c..b1694c6717 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-firehydrant +## 0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.2.9-next.0 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index d6b02d8323..31848ee464 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.2.9-next.0", + "version": "0.2.9-next.1", "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 35aa7423aa..68a526db00 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-fossa +## 0.2.57-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.2.57-next.0 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 78c39595b4..7fbe7e5570 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.57-next.0", + "version": "0.2.57-next.1", "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 f8adef32ea..3e479c9bc4 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-gcalendar +## 0.3.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.3.19-next.0 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 6e0166402e..be9b02d4cc 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.19-next.0", + "version": "0.3.19-next.1", "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 4f7d8546cd..69584e9c89 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gcp-projects +## 0.3.42-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + ## 0.3.42-next.0 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 7c0a6f9240..888f2c7a16 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.42-next.0", + "version": "0.3.42-next.1", "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 58ee33695d..10c0d6770a 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.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + ## 0.3.38-next.0 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 64b0a65d87..869d39633d 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.38-next.0", + "version": "0.3.38-next.1", "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 1278f32354..e4bea23a68 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-github-actions +## 0.6.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + ## 0.6.6-next.0 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 2d48f24492..fa273363c9 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.6.6-next.0", + "version": "0.6.6-next.1", "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 ba62f6bdc4..637bb2ca7f 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-deployments +## 0.1.56-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + ## 0.1.56-next.0 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 71fa3a7459..edd3b6ff0e 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.56-next.0", + "version": "0.1.56-next.1", "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 a20c93cdeb..e6a848c39d 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-github-issues +## 0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + ## 0.2.14-next.0 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index 5b0d34effe..0a18bb22b9 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.14-next.0", + "version": "0.2.14-next.1", "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 89957b1232..cf06af7c0c 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.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + ## 0.1.19-next.0 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index c81a7c76d7..b7d320931b 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.19-next.0", + "version": "0.1.19-next.1", "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 81f51796c4..7783bf960b 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-gitops-profiles +## 0.3.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + ## 0.3.41-next.0 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 56364215c5..d254a70390 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.41-next.0", + "version": "0.3.41-next.1", "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 705ff97e0a..33c2d9bd14 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-gocd +## 0.1.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.1.31-next.0 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 4d6f41ec62..9da32e57b1 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.31-next.0", + "version": "0.1.31-next.1", "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 429ca2496b..0663cb0755 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-graphiql +## 0.2.55-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + ## 0.2.55-next.0 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 15fc394ba0..d0ce3982a6 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.55-next.0", + "version": "0.2.55-next.1", "publishConfig": { "access": "public" }, diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index fbe80e1091..c3991bd3a2 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphql-backend +## 0.1.43-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-catalog-graphql@0.3.23 + ## 0.1.43-next.0 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index 11fd377905..7ba1b47881 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.43-next.0", + "version": "0.1.43-next.1", "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 ef1eb4a5c1..5331c0a7fc 100644 --- a/plugins/graphql-voyager/CHANGELOG.md +++ b/plugins/graphql-voyager/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphql-voyager +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + ## 0.1.8-next.0 ### Patch Changes diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index 24901e8c17..bc62c158ac 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.8-next.0", + "version": "0.1.8-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/home-react/CHANGELOG.md b/plugins/home-react/CHANGELOG.md index 197ba61e80..2c2fce8504 100644 --- a/plugins/home-react/CHANGELOG.md +++ b/plugins/home-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-home-react +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index f01adae751..f6e9655849 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home-react", "description": "A Backstage plugin that contains react components helps you build a home page", - "version": "0.1.4-next.0", + "version": "0.1.4-next.1", "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 f8bd2aab50..2d826ed5d0 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-home +## 0.5.9-next.1 + +### Patch Changes + +- f997f771da: Adds Top/Recently Visited components to homepage +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-home-react@0.1.4-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + ## 0.5.9-next.0 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index 80fb8496b1..17c17cffe3 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.5.9-next.0", + "version": "0.5.9-next.1", "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 02d39b0594..31cace8de8 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-ilert +## 0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.2.14-next.0 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 83cde2ff54..f84a79375d 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.14-next.0", + "version": "0.2.14-next.1", "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 4bcb34c73c..b0aeddb339 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-jenkins-backend +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/plugin-jenkins-common@0.1.19 + - @backstage/plugin-permission-common@0.7.8 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 717d94733d..12fe2debe1 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.2.8-next.0", + "version": "0.2.8-next.1", "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 66f3d3b026..c7b92cbcdd 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-jenkins +## 0.8.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-jenkins-common@0.1.19 + ## 0.8.7-next.0 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index e3042ccb53..cfbac50ae5 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.8.7-next.0", + "version": "0.8.7-next.1", "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 d5e7101f55..bccda7319f 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-kafka-backend +## 0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + ## 0.3.2-next.0 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 7afdb219ab..d965258859 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.3.2-next.0", + "version": "0.3.2-next.1", "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 d741d0fe2d..adb941bc3f 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kafka +## 0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.3.25-next.0 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index b48ee3322e..5e699b3bcc 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.25-next.0", + "version": "0.3.25-next.1", "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 8fc7a281db..cef2f97198 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-kubernetes-backend +## 0.12.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + ## 0.12.2-next.0 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 54c5a35201..e0df3aa94b 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.12.2-next.0", + "version": "0.12.2-next.1", "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 83451a1999..4bd84d3ca7 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-kubernetes-common +## 0.7.0-next.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + ## 0.6.6 ### Patch Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 99d38b803e..baf24cea5d 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.6", + "version": "0.7.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-react/CHANGELOG.md b/plugins/kubernetes-react/CHANGELOG.md new file mode 100644 index 0000000000..f7ed7bb39d --- /dev/null +++ b/plugins/kubernetes-react/CHANGELOG.md @@ -0,0 +1,17 @@ +# @backstage/plugin-kubernetes-react + +## 0.1.0-next.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index 5c95b29870..e708e9e455 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-react", "description": "Web library for the kubernetes-react plugin", - "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/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 451825ca33..55fda1b465 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-kubernetes +## 0.11.0-next.1 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-kubernetes-common@0.7.0-next.0 + - @backstage/plugin-kubernetes-react@0.1.0-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + ## 0.10.4-next.0 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index fdc792fc52..8ed59595c2 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.10.4-next.0", + "version": "0.11.0-next.1", "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 420f70c1d2..32c2b599dd 100644 --- a/plugins/lighthouse-backend/CHANGELOG.md +++ b/plugins/lighthouse-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-lighthouse-backend +## 0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.3 + ## 0.3.2-next.0 ### Patch Changes diff --git a/plugins/lighthouse-backend/package.json b/plugins/lighthouse-backend/package.json index 4946391d4a..bd337e185a 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.3.2-next.0", + "version": "0.3.2-next.1", "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 9690efc150..4ae227281a 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-lighthouse +## 0.4.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-lighthouse-common@0.1.3 + ## 0.4.10-next.0 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index e23b8ae742..1b81e64511 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.10-next.0", + "version": "0.4.10-next.1", "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 037bba87c2..5bc5640704 100644 --- a/plugins/linguist-backend/CHANGELOG.md +++ b/plugins/linguist-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-linguist-backend +## 0.5.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + ## 0.5.2-next.0 ### Patch Changes diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index e75d9daef2..99ce86abd8 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist-backend", - "version": "0.5.2-next.0", + "version": "0.5.2-next.1", "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 eae430348d..b5f72d53ba 100644 --- a/plugins/linguist/CHANGELOG.md +++ b/plugins/linguist/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-linguist +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-linguist-common@0.1.2 + ## 0.1.10-next.0 ### Patch Changes diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index a748670653..4bdc89ce29 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist", - "version": "0.1.10-next.0", + "version": "0.1.10-next.1", "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 3ada5bb9d1..1b1942ce6f 100644 --- a/plugins/microsoft-calendar/CHANGELOG.md +++ b/plugins/microsoft-calendar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-microsoft-calendar +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.1.8-next.0 ### Patch Changes diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index 5f66f361fe..63ce1d7dfa 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.8-next.0", + "version": "0.1.8-next.1", "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 b7c866f7f8..c667e3594c 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-newrelic-dashboard +## 0.2.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + ## 0.2.18-next.0 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index d491e86ab7..af5003dc1a 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.18-next.0", + "version": "0.2.18-next.1", "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 e896702b4b..a0d122a18c 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-newrelic +## 0.3.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + ## 0.3.41-next.0 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 1ab21391da..da63717dda 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.41-next.0", + "version": "0.3.41-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/nomad-backend/CHANGELOG.md b/plugins/nomad-backend/CHANGELOG.md index 188bba8900..a5186f75f8 100644 --- a/plugins/nomad-backend/CHANGELOG.md +++ b/plugins/nomad-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-nomad-backend +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + ## 0.1.7-next.0 ### Patch Changes diff --git a/plugins/nomad-backend/package.json b/plugins/nomad-backend/package.json index ac16ab79ec..a9c86dc376 100644 --- a/plugins/nomad-backend/package.json +++ b/plugins/nomad-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-nomad-backend", - "version": "0.1.7-next.0", + "version": "0.1.7-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/nomad/CHANGELOG.md b/plugins/nomad/CHANGELOG.md index cf42bd5820..15f8fca004 100644 --- a/plugins/nomad/CHANGELOG.md +++ b/plugins/nomad/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-nomad +## 0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.1.6-next.0 ### Patch Changes diff --git a/plugins/nomad/package.json b/plugins/nomad/package.json index 7e7fc1a739..5a3964cdc1 100644 --- a/plugins/nomad/package.json +++ b/plugins/nomad/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-nomad", - "version": "0.1.6-next.0", + "version": "0.1.6-next.1", "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 index aa0f193a62..b9d7dc084f 100644 --- a/plugins/octopus-deploy/CHANGELOG.md +++ b/plugins/octopus-deploy/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-octopus-deploy +## 0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.2.7-next.0 ### Patch Changes diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index a82e7f74e1..5e0bf27520 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-octopus-deploy", - "version": "0.2.7-next.0", + "version": "0.2.7-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/opencost/CHANGELOG.md b/plugins/opencost/CHANGELOG.md index 960faf29e7..60edb74ed8 100644 --- a/plugins/opencost/CHANGELOG.md +++ b/plugins/opencost/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-opencost +## 0.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + ## 0.2.1-next.0 ### Patch Changes diff --git a/plugins/opencost/package.json b/plugins/opencost/package.json index 87b533f153..d733276152 100644 --- a/plugins/opencost/package.json +++ b/plugins/opencost/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-opencost", - "version": "0.2.1-next.0", + "version": "0.2.1-next.1", "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 71e1b94403..2d5f4fbd7e 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-org-react +## 0.1.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.1.14-next.0 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index a5e5a8562b..28876a6700 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.14-next.0", + "version": "0.1.14-next.1", "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 a2e7a2b60a..6ede70db1b 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-org +## 0.6.15-next.1 + +### Patch Changes + +- dc5b6b971b: Fixed the display of OwnershipCard with aggregated relations by loading relations when getting children of entity. + This allows the already existing recursive method to work properly when children of entity have children themselves. +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.6.15-next.0 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index c68352b579..4f01b5fa09 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.15-next.0", + "version": "0.6.15-next.1", "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 d9936c4f41..d37d6b4033 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-pagerduty +## 0.6.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-home-react@0.1.4-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.6.6-next.0 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 28682c2f2d..4ade1d9224 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.6.6-next.0", + "version": "0.6.6-next.1", "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 448a804f23..c4b41389b6 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-periskop-backend +## 0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + ## 0.2.2-next.0 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index ad0bcf0ad2..ff276b7a55 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.2.2-next.0", + "version": "0.2.2-next.1", "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 a38ca46956..7030b94dfc 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-periskop +## 0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.1.23-next.0 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index e2d7f6e74d..9d47082842 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.23-next.0", + "version": "0.1.23-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md index 49b6cfd3a0..127e39e251 100644 --- a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md +++ b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-backend-module-allow-all-policy +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-permission-common@0.7.8 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/permission-backend-module-policy-allow-all/package.json b/plugins/permission-backend-module-policy-allow-all/package.json index 12e60881af..2b309e852c 100644 --- a/plugins/permission-backend-module-policy-allow-all/package.json +++ b/plugins/permission-backend-module-policy-allow-all/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-backend-module-allow-all-policy", "description": "Allow all policy backend module for the permission plugin.", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "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 978552f3ed..d3419ba508 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-permission-backend +## 0.5.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/plugin-permission-common@0.7.8 + ## 0.5.28-next.0 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 0833e9e89b..2709204635 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.28-next.0", + "version": "0.5.28-next.1", "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 bcdf5ce358..e387547156 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-permission-node +## 0.7.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/plugin-permission-common@0.7.8 + ## 0.7.16-next.0 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 3bacf5e3ed..9f57f44886 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.16-next.0", + "version": "0.7.16-next.1", "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 0af03356ae..c7f001ae4b 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-playlist-backend +## 0.3.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-playlist-common@0.1.10 + ## 0.3.9-next.0 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index ac2ec35fb9..319206e6c6 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist-backend", - "version": "0.3.9-next.0", + "version": "0.3.9-next.1", "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 46888d22f0..301f289b8c 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-playlist +## 0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-playlist-common@0.1.10 + ## 0.1.17-next.0 ### Patch Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index c472d8cb0c..10a3c651ed 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.1.17-next.0", + "version": "0.1.17-next.1", "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 96693d55d3..22dae797a3 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-proxy-backend +## 0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + ## 0.4.2-next.0 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 5c2d9e82c5..9b21073dc7 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.4.2-next.0", + "version": "0.4.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/puppetdb/CHANGELOG.md b/plugins/puppetdb/CHANGELOG.md index c1da915673..5d9dc0be04 100644 --- a/plugins/puppetdb/CHANGELOG.md +++ b/plugins/puppetdb/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-puppetdb +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.1.8-next.0 ### Patch Changes diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index cb8a9898fd..ad23b77a8f 100644 --- a/plugins/puppetdb/package.json +++ b/plugins/puppetdb/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-puppetdb", "description": "Backstage plugin to visualize resource information and Puppet facts from PuppetDB.", - "version": "0.1.8-next.0", + "version": "0.1.8-next.1", "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 93b97226df..6d4b6b309e 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-rollbar-backend +## 0.1.50-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + ## 0.1.50-next.0 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 596a1cf096..019f851d04 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.50-next.0", + "version": "0.1.50-next.1", "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 6bd10a118f..69c38eead1 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-rollbar +## 0.4.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.4.25-next.0 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index fb3171d2dc..5a5159ceb6 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.25-next.0", + "version": "0.4.25-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md index a2d833056a..366698d2e6 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend-module-confluence-to-markdown +## 0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + ## 0.2.6-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json index 9160a70062..bb996d7da8 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown", "description": "The confluence-to-markdown module for @backstage/plugin-scaffolder-backend", - "version": "0.2.6-next.0", + "version": "0.2.6-next.1", "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 ee0b07ee8b..8a4dc42f44 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + ## 0.2.29-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 9ef5c6f3ec..908f907f13 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.29-next.0", + "version": "0.2.29-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md index fbb987bb11..3cd1812ca7 100644 --- a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-backend-module-gitlab +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index 71ee372afc..89d755f1dd 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitlab", - "version": "0.2.8-next.0", + "version": "0.2.8-next.1", "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 bc5965d9be..c51d36eb64 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + ## 0.4.22-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 586bc2e7dc..c58fb6a035 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.22-next.0", + "version": "0.4.22-next.1", "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 f13f300877..e07feaa885 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.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index 74e0d7b397..366f7a9126 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.13-next.0", + "version": "0.1.13-next.1", "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 14d2ef1c08..a24ec57bb3 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.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + ## 0.2.26-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index e4e6b2941c..cd4350f681 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.26-next.0", + "version": "0.2.26-next.1", "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 a512a87555..50fda07ce7 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-scaffolder-backend +## 1.18.0-next.1 + +### Minor Changes + +- f41099bb31: Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-backend@1.14.0-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.2-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/plugin-scaffolder-node@0.2.5-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-scaffolder-common@1.4.1 + ## 1.17.3-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 550ad90b47..cab9abae96 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.17.3-next.0", + "version": "1.18.0-next.1", "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 e4f43dd69e..c3a17eaf61 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-node +## 0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.1 + ## 0.2.5-next.0 ### Patch Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index b6d2bde6e9..b46d4207c5 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.2.5-next.0", + "version": "0.2.5-next.1", "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 dcb87e1497..77ef8b2d45 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-scaffolder-react +## 1.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-scaffolder-common@1.4.1 + ## 1.5.6-next.0 ### Patch Changes diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index eb8d886b9a..9722c366c4 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.5.6-next.0", + "version": "1.5.6-next.1", "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 4cb5125f4f..75417547a2 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-scaffolder +## 1.15.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-scaffolder-react@1.5.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/plugin-permission-react@0.4.16-next.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-scaffolder-common@1.4.1 + ## 1.15.1-next.0 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 086ef3cea1..841e6d61d6 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.15.1-next.0", + "version": "1.15.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-catalog/CHANGELOG.md b/plugins/search-backend-module-catalog/CHANGELOG.md index 46f3b4c9de..402b501695 100644 --- a/plugins/search-backend-module-catalog/CHANGELOG.md +++ b/plugins/search-backend-module-catalog/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-backend-module-catalog +## 0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + ## 0.1.9-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index 11f64cf817..4963708861 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-catalog", "description": "A module for the search backend that exports catalog modules", - "version": "0.1.9-next.0", + "version": "0.1.9-next.1", "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 f56b1f28da..0e92e7c3db 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.3.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/plugin-search-common@1.2.6 + ## 1.3.8-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 2750e1d2dc..36d66e827b 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.3.8-next.0", + "version": "1.3.8-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-explore/CHANGELOG.md b/plugins/search-backend-module-explore/CHANGELOG.md index 5260222ed3..c26bf84328 100644 --- a/plugins/search-backend-module-explore/CHANGELOG.md +++ b/plugins/search-backend-module-explore/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search-backend-module-explore +## 0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.6 + ## 0.1.9-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-explore/package.json b/plugins/search-backend-module-explore/package.json index a4a1dcf881..f70d70dd73 100644 --- a/plugins/search-backend-module-explore/package.json +++ b/plugins/search-backend-module-explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-explore", "description": "A module for the search backend that exports explore modules", - "version": "0.1.9-next.0", + "version": "0.1.9-next.1", "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 b49fb7aad9..10453b9500 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-search-common@1.2.6 + ## 0.5.14-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 10536678d5..ad9f9e0a3b 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.14-next.0", + "version": "0.5.14-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-techdocs/CHANGELOG.md b/plugins/search-backend-module-techdocs/CHANGELOG.md index 666fe0a7c3..5364e493c6 100644 --- a/plugins/search-backend-module-techdocs/CHANGELOG.md +++ b/plugins/search-backend-module-techdocs/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-backend-module-techdocs +## 0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-techdocs-node@1.8.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + ## 0.1.9-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index 075403d512..54e9b86afa 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-techdocs", "description": "A module for the search backend that exports techdocs modules", - "version": "0.1.9-next.0", + "version": "0.1.9-next.1", "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 bfdf91c150..880615383a 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search-backend-node +## 1.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + ## 1.2.9-next.0 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 3e87e29ce9..587b98cd61 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.2.9-next.0", + "version": "1.2.9-next.1", "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 af05809517..a1cae58b98 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-search-backend +## 1.4.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-node@1.2.9-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/plugin-permission-node@0.7.16-next.1 + - @backstage/config@1.1.0 + - @backstage/backend-openapi-utils@0.0.4 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + ## 1.4.5-next.0 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index c71356dda3..10c09a0178 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.4.5-next.0", + "version": "1.4.5-next.1", "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 7904129b3e..1cb3a0e329 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-search-react +## 1.7.1-next.1 + +### Patch Changes + +- 703a4ffc5b: Create `createSearchResultListItem` alpha version that only supports declarative integration. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/frontend-app-api@0.2.0-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-search-common@1.2.6 + ## 1.7.1-next.0 ### Patch Changes diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index da4092fcbd..3591e75e94 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.7.1-next.0", + "version": "1.7.1-next.1", "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 0a5b57b7a2..714e4ef1de 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-search +## 1.4.1-next.1 + +### Patch Changes + +- e5a2956dd2: Create an experimental search plugin that is compatible with the declarative integration system, it is exported from `/alpha` subpath. +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-search-common@1.2.6 + ## 1.4.1-next.0 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 8b90867a5a..6067d0004c 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.4.1-next.0", + "version": "1.4.1-next.1", "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 5f28cbf0fd..0e2a3d446c 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-sentry +## 0.5.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.5.10-next.0 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 242e26ff51..b6f502baee 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.10-next.0", + "version": "0.5.10-next.1", "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 1e168daa77..29eb3eefc5 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-shortcuts +## 0.3.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + ## 0.3.15-next.0 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 994dabbd1d..b3f3d53858 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.15-next.0", + "version": "0.3.15-next.1", "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 a7b8b4e171..d5f8999191 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-sonarqube-backend +## 0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + ## 0.2.7-next.0 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 89c96bfcf4..1ff45c2ac9 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-backend", - "version": "0.2.7-next.0", + "version": "0.2.7-next.1", "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 0fa5143c1a..d951104286 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-sonarqube +## 0.7.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + - @backstage/plugin-sonarqube-react@0.1.9-next.0 + ## 0.7.6-next.0 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 780b81468a..b68c28b76b 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.7.6-next.0", + "version": "0.7.6-next.1", "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 76bd4b9ddb..1117cfee3e 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.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/theme@0.4.2 + ## 0.4.14-next.0 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index ab6155e96c..b677f6f425 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.14-next.0", + "version": "0.4.14-next.1", "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 6eb8d27731..149dd6913f 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.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/plugin-search-common@1.2.6 + ## 0.2.9-next.0 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index f090c8d25f..57c8d6bcfc 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.2.9-next.0", + "version": "0.2.9-next.1", "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 12cf74570e..d0866a9211 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-stack-overflow +## 0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/plugin-home-react@0.1.4-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/theme@0.4.2 + - @backstage/plugin-search-common@1.2.6 + ## 0.1.21-next.0 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 7be47012e8..eef133b305 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.21-next.0", + "version": "0.1.21-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stackstorm/CHANGELOG.md b/plugins/stackstorm/CHANGELOG.md index c8056438d7..6734c7dd27 100644 --- a/plugins/stackstorm/CHANGELOG.md +++ b/plugins/stackstorm/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-stackstorm +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.1.7-next.0 ### Patch Changes diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index a65e8692e2..bd945feb36 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.7-next.0", + "version": "0.1.7-next.1", "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 a884f1dfc7..f8f70f1c0c 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.37-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-tech-insights-node@0.4.11-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.1.37-next.0 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index 8823de7697..bd7b2c2226 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.37-next.0", + "version": "0.1.37-next.1", "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 fe3f4ce37c..cbafe8f3b5 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-tech-insights-backend +## 0.5.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/plugin-tech-insights-node@0.4.11-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.5.19-next.0 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index 2b5a427eef..a89907fd62 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.19-next.0", + "version": "0.5.19-next.1", "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 2a29e65bf2..549c427075 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.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.4.11-next.0 ### Patch Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 80befca1d1..980acd1a4b 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.11-next.0", + "version": "0.4.11-next.1", "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 83bd2f6d1c..053f9d97ed 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-tech-insights +## 0.3.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.3.17-next.0 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index a0f74ff425..142a24cb9b 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.17-next.0", + "version": "0.3.17-next.1", "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 48369b1e49..a7684ba5c8 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-tech-radar +## 0.6.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + ## 0.6.9-next.0 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 7505fa0813..e99565bb67 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.9-next.0", + "version": "0.6.9-next.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 812543f3c8..ea84b35661 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0-next.1 + - @backstage/plugin-techdocs@1.7.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/test-utils@1.4.4-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/theme@0.4.2 + ## 1.0.22-next.0 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 0a88a3d99f..3a0f83ad6f 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.22-next.0", + "version": "1.0.22-next.1", "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 7566b7baff..2723867071 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-techdocs-backend +## 1.7.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.9-next.1 + - @backstage/plugin-techdocs-node@1.8.2-next.1 + - @backstage/config@1.1.0 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-catalog-common@1.0.16 + - @backstage/plugin-permission-common@0.7.8 + - @backstage/plugin-search-common@1.2.6 + ## 1.7.2-next.0 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 935990c305..821457e518 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.7.2-next.0", + "version": "1.7.2-next.1", "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 3f79ff32b8..3b4c893faa 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.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + ## 1.1.1-next.0 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 933f18eb48..53ccd6c244 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.1.1-next.0", + "version": "1.1.1-next.1", "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 dca68479be..a385a83136 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-techdocs-node +## 1.8.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/integration-aws-node@0.1.6 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/plugin-search-common@1.2.6 + ## 1.8.2-next.0 ### Patch Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 35feb3b0b4..f49ecf1baa 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.8.2-next.0", + "version": "1.8.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index f14e5b5a60..3e502df15d 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-techdocs-react +## 1.1.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/version-bridge@1.0.5 + ## 1.1.12-next.0 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 79ef7241f0..64df90080d 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.12-next.0", + "version": "1.1.12-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index e2256c8f15..c407d11028 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-techdocs +## 1.7.1-next.1 + +### Patch Changes + +- 4918f65ab2: Create an experimental `TechDocsSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- df449a7a31: Add kind column by default to TechDocsTable +- Updated dependencies + - @backstage/frontend-plugin-api@0.1.1-next.1 + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-search-react@1.7.1-next.1 + - @backstage/integration-react@1.1.20-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/plugin-techdocs-react@1.1.12-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/config@1.1.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + - @backstage/theme@0.4.2 + - @backstage/plugin-search-common@1.2.6 + ## 1.7.1-next.0 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 80951ed400..e7251a4eb2 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.7.1-next.0", + "version": "1.7.1-next.1", "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 e7afb9ecd0..4cbf70e538 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-todo-backend +## 0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.6-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/config@1.1.0 + - @backstage/backend-openapi-utils@0.0.4 + - @backstage/catalog-client@1.4.4 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/integration@1.7.1-next.0 + ## 0.3.3-next.0 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 1d4f396de1..c741984f2d 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.3.3-next.0", + "version": "0.3.3-next.1", "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 7e9e8c6933..68efd13892 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-todo +## 0.2.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.2.28-next.0 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index fa1d1d9e62..b255744e12 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.28-next.0", + "version": "0.2.28-next.1", "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 9af11fffbf..0dedc9dbce 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.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.7-next.1 + - @backstage/backend-plugin-api@0.6.5-next.1 + - @backstage/plugin-auth-node@0.3.2-next.1 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/types@1.1.1 + ## 0.2.3-next.0 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 0feaba734e..a8e8a711ae 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.2.3-next.0", + "version": "0.2.3-next.1", "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 9e81589e7d..dcd46282a1 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-user-settings +## 0.7.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-app-api@1.10.1-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + - @backstage/types@1.1.1 + ## 0.7.11-next.0 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index d2c9f440e6..251436e85a 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.11-next.0", + "version": "0.7.11-next.1", "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 fcb259e047..3253d8b99c 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-vault-backend +## 0.3.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.10-next.1 + - @backstage/backend-common@0.19.7-next.1 + - @backstage/config@1.1.0 + - @backstage/errors@1.2.2 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index f8de4e2845..6906b8124d 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.3.10-next.0", + "version": "0.3.10-next.1", "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 940345da8d..38121353c0 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-vault +## 0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/catalog-model@1.4.2 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.1.20-next.0 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index d571efe444..014e9b0d50 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.20-next.0", + "version": "0.1.20-next.1", "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 c296cc3e0b..f3bebcb916 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-xcmetrics +## 0.2.44-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.1 + - @backstage/core-plugin-api@1.7.0-next.0 + - @backstage/errors@1.2.2 + - @backstage/theme@0.4.2 + ## 0.2.44-next.0 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index b63915c1f0..c39c0e4963 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.44-next.0", + "version": "0.2.44-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0",