diff --git a/.changeset/backend-common-slips-away.md b/.changeset/backend-common-slips-away.md new file mode 100644 index 0000000000..93b77f1111 --- /dev/null +++ b/.changeset/backend-common-slips-away.md @@ -0,0 +1,7 @@ +--- +'@backstage/backend-common': patch +--- + +Added a `stream()` method to complement the `buffer()` method on `ReadUrlResponse`. A `ReadUrlResponseFactory` utility class is now also available, providing a simple, consistent way to provide a valid `ReadUrlResponse`. + +This method, though optional for now, will be required on the responses of `UrlReader.readUrl()` implementations in a future release. diff --git a/.changeset/beige-glasses-swim.md b/.changeset/beige-glasses-swim.md new file mode 100644 index 0000000000..9360bd5fdf --- /dev/null +++ b/.changeset/beige-glasses-swim.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Enabled select component to be enabled by keyboard diff --git a/.changeset/chatty-pears-nail.md b/.changeset/chatty-pears-nail.md new file mode 100644 index 0000000000..646841fb58 --- /dev/null +++ b/.changeset/chatty-pears-nail.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Fix wrong return type of the `isGroupEntity` function. diff --git a/.changeset/dirty-ducks-suffer.md b/.changeset/dirty-ducks-suffer.md new file mode 100644 index 0000000000..bcfef8550b --- /dev/null +++ b/.changeset/dirty-ducks-suffer.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Fixed overflow bug of name and email on EntitiyMembersListCard component which can occur on specific 'screen width' + ’character length' combinations diff --git a/.changeset/dry-scissors-dream.md b/.changeset/dry-scissors-dream.md new file mode 100644 index 0000000000..09965f0f59 --- /dev/null +++ b/.changeset/dry-scissors-dream.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration': minor +--- + +added the possibility to handle raw Gitlab URLs with nested namespaces diff --git a/.changeset/dull-waves-marry.md b/.changeset/dull-waves-marry.md new file mode 100644 index 0000000000..22d33238b4 --- /dev/null +++ b/.changeset/dull-waves-marry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Create a menu in the sub header of documentation pages, it is responsible for rendering TechDocs addons that allow users to customize their reading experience. diff --git a/.changeset/empty-planes-destroy.md b/.changeset/empty-planes-destroy.md new file mode 100644 index 0000000000..350dcc6b44 --- /dev/null +++ b/.changeset/empty-planes-destroy.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-bazaar': patch +--- + +Exported the SortView component from the Bazaar plugin for use directly diff --git a/.changeset/fluffy-sloths-deliver.md b/.changeset/fluffy-sloths-deliver.md new file mode 100644 index 0000000000..ba4e6e4fe5 --- /dev/null +++ b/.changeset/fluffy-sloths-deliver.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-kubernetes': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-kubernetes-common': patch +--- + +Add support for 'oidc' as authProvider for kubernetes authentication +and adds optional 'oidcTokenProvider' config value. This will allow +users to authenticate to kubernetes cluster using id tokens obtained +from the configured auth provider in their backstage instance. diff --git a/.changeset/gentle-penguins-kick.md b/.changeset/gentle-penguins-kick.md new file mode 100644 index 0000000000..c19834c6af --- /dev/null +++ b/.changeset/gentle-penguins-kick.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +'@backstage/plugin-scaffolder-common': minor +--- + +Added the ability to reference the user in the `template.yaml` manifest diff --git a/.changeset/good-beans-knock.md b/.changeset/good-beans-knock.md new file mode 100644 index 0000000000..91de53c128 --- /dev/null +++ b/.changeset/good-beans-knock.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Don't set the background color on an Avatar component that has a picture. diff --git a/.changeset/nice-parrots-lie.md b/.changeset/nice-parrots-lie.md new file mode 100644 index 0000000000..2a917b89f3 --- /dev/null +++ b/.changeset/nice-parrots-lie.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-techdocs-react': patch +--- + +Create a new addon location called "Settings", it is designed for addons that allow users to customize the reading experience in documentation pages. + +Usage example: + +```tsx +const TextSize = techdocsModuleAddonsContribPlugin.provide( + createTechDocsAddonExtension({ + name: 'TextSize', + location: TechDocsAddonLocations.Settings, + component: TextSizeAddon, + }), +); +``` diff --git a/.changeset/olive-eggs-accept.md b/.changeset/olive-eggs-accept.md new file mode 100644 index 0000000000..66d44d9c3e --- /dev/null +++ b/.changeset/olive-eggs-accept.md @@ -0,0 +1,16 @@ +--- +'@backstage/backend-common': patch +--- + +**DEPRECATION**: Server-to-server authentication tokens issued from a +`TokenManager` (specifically, `ServerTokenManager`) now has an expiry time set, +for one hour in the future from when issued. This improves security. The ability +to pass in and validate tokens that either have a missing `exp` claim, or an +`exp` claim that expired in the past, is now deprecated. Trying to do so will +lead to logged warnings, and in a future release will instead lead to errors. + +It was always the case that users of this interface were expected to call its +`getToken()` method for every outgoing call and never hold on to any given token +for reuse. But this now has become even more important advice to heed, and you +should verify that you do not hold on to and reuse tokens such as these in your +own code. diff --git a/.changeset/pre.json b/.changeset/pre.json index cdcad84ba8..dff929aeec 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -1,5 +1,5 @@ { - "mode": "pre", + "mode": "exit", "tag": "next", "initialVersions": { "example-app": "0.2.70", @@ -151,36 +151,53 @@ "@internal/plugin-todo-list": "1.0.0", "@internal/plugin-todo-list-backend": "1.0.0", "@internal/plugin-todo-list-common": "1.0.0", - "@backstage/plugin-techdocs-addons-test-utils": "0.0.0" + "@backstage/plugin-techdocs-addons-test-utils": "0.0.0", + "@backstage/plugin-codescene": "0.0.0" }, "changesets": [ "afraid-insects-do", + "backend-common-slips-away", + "backend-common-twist-your-ankle", + "beige-glasses-swim", "beige-panthers-dream", + "big-teachers-dress", "brave-starfishes-try", "breezy-days-prove", "bright-panthers-guess", "chatty-forks-bathe", + "chatty-pears-nail", "clever-trains-greet", "cool-mice-sit", "cool-ties-share", "curly-parrots-applaud", "cyan-boxes-double", + "dirty-clocks-poke", + "dirty-ducks-suffer", "dirty-eagles-hunt", + "dull-waves-marry", "early-crabs-help", "early-lemons-add", "eighty-chicken-retire", "empty-mugs-bow", + "empty-planes-destroy", "empty-poems-lick", "fair-kings-retire", "fair-pigs-mate", + "fast-stingrays-guess", + "fluffy-poems-sell", + "fluffy-sloths-deliver", + "fresh-panthers-arrive", "funny-lamps-turn", "fuzzy-seahorses-teach", + "gentle-penguins-kick", "giant-cheetahs-thank", + "good-beans-knock", "grumpy-panthers-peel", "hip-adults-collect", "hip-monkeys-hide", "honest-kids-live", "hot-peaches-give", + "hungry-chefs-return", "hungry-goats-mate", "kind-cats-clap", "lazy-zebras-pay", @@ -196,6 +213,7 @@ "nasty-humans-give", "nasty-paws-move", "new-beds-argue", + "nice-parrots-lie", "nine-actors-fly", "nine-geese-rest", "odd-apples-smash", @@ -204,14 +222,27 @@ "perfect-penguins-rescue", "pink-mayflies-rhyme", "polite-planets-learn", + "pretty-readers-grow", "renovate-05696d1", + "renovate-4b92131", "renovate-5970cc2", + "renovate-759d9d5", + "renovate-9466904", + "renovate-abcbd6e", + "renovate-abcbd6e2", "renovate-b063c4b", "renovate-bf43c44", + "renovate-bf63f74", "renovate-ca619fc", + "rotten-impalas-clap", "search-dry-wolves-join", "search-heavy-llamas-worry", + "search-the-worst-of-you", + "serious-apricots-collect", "seven-deers-rule", + "seven-panthers-pump", + "shiny-apes-design", + "shiny-moles-study", "shiny-students-approve", "short-chicken-act", "short-dodos-sparkle", @@ -219,9 +250,11 @@ "silver-readers-deliver", "six-buckets-tap", "sixty-llamas-change", + "small-eggs-guess", "smart-ghosts-search", "spotty-plums-rule", "stale-pigs-reply", + "stale-pugs-kiss", "strong-mangos-sell", "swift-bugs-share", "swift-parrots-hammer", @@ -229,16 +262,27 @@ "tasty-drinks-teach", "techdocs-changeset-not-found", "techdocs-five-hundred-ml", + "techdocs-hot-berries-collect", + "techdocs-loose-seal-blooth", "techdocs-low-calorie-drink", + "techdocs-money-banana-stand", "techdocs-nice-boats-wonder", "techdocs-quick-owls-smile", "techdocs-touch-screen-wipes", "techdocs-vitamin-well-reload", "thick-bees-brush", + "thick-tools-dream", + "three-tips-hunt", "tough-forks-carry", + "tricky-laws-thank", + "tricky-phones-sing", "violet-steaks-knock", + "warm-suns-wonder", "wicked-vans-press", "wild-pigs-work", - "wise-emus-wait" + "wise-countries-watch", + "wise-doors-hammer", + "wise-emus-wait", + "witty-lions-reply" ] } diff --git a/.changeset/pretty-readers-grow.md b/.changeset/pretty-readers-grow.md new file mode 100644 index 0000000000..f3193eb878 --- /dev/null +++ b/.changeset/pretty-readers-grow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-codescene': minor +--- + +Add CodeScene plugin diff --git a/.changeset/renovate-4b92131.md b/.changeset/renovate-4b92131.md new file mode 100644 index 0000000000..2926b306d4 --- /dev/null +++ b/.changeset/renovate-4b92131.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Updated dependency `use-immer` to `^0.7.0`. diff --git a/.changeset/renovate-759d9d5.md b/.changeset/renovate-759d9d5.md new file mode 100644 index 0000000000..4582111c29 --- /dev/null +++ b/.changeset/renovate-759d9d5.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-graphiql': patch +--- + +Updated dependency `@types/codemirror` to `^5.0.0`. diff --git a/.changeset/renovate-9008399.md b/.changeset/renovate-9008399.md new file mode 100644 index 0000000000..64e1dd07a8 --- /dev/null +++ b/.changeset/renovate-9008399.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-codescene': patch +--- + +Updated dependency `@testing-library/user-event` to `^14.0.0`. diff --git a/.changeset/renovate-9466904.md b/.changeset/renovate-9466904.md new file mode 100644 index 0000000000..e80c26e0ac --- /dev/null +++ b/.changeset/renovate-9466904.md @@ -0,0 +1,8 @@ +--- +'@backstage/cli-common': patch +'@backstage/config': patch +'@backstage/dev-utils': patch +'@backstage/release-manifests': patch +--- + +Updated dependency `@types/node` to `^16.0.0`. diff --git a/.changeset/renovate-abcbd6e.md b/.changeset/renovate-abcbd6e.md deleted file mode 100644 index e96d9ea875..0000000000 --- a/.changeset/renovate-abcbd6e.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-techdocs': patch ---- - -Updated dependency `event-source-polyfill` to `1.0.26`. diff --git a/.changeset/renovate-bf63f74.md b/.changeset/renovate-bf63f74.md new file mode 100644 index 0000000000..9b42c07c88 --- /dev/null +++ b/.changeset/renovate-bf63f74.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Updated dependency `@types/react-syntax-highlighter` to `^15.0.0`. diff --git a/.changeset/renovate-db1641c.md b/.changeset/renovate-db1641c.md new file mode 100644 index 0000000000..8d34bd3eb1 --- /dev/null +++ b/.changeset/renovate-db1641c.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-codescene': patch +'@backstage/plugin-sonarqube': patch +--- + +Updated dependency `rc-progress` to `3.3.2`. diff --git a/.changeset/rotten-impalas-clap.md b/.changeset/rotten-impalas-clap.md new file mode 100644 index 0000000000..6626a0a0bf --- /dev/null +++ b/.changeset/rotten-impalas-clap.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-catalog': patch +--- + +Sidebar NAV now includes aria-label. Component AboutField now uses h2 variant instead of subtitle2 (font properties unchanged) diff --git a/.changeset/search-the-worst-of-you.md b/.changeset/search-the-worst-of-you.md new file mode 100644 index 0000000000..29d9661f24 --- /dev/null +++ b/.changeset/search-the-worst-of-you.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-search-backend-node': patch +'@backstage/plugin-search-backend-module-elasticsearch': patch +'@backstage/plugin-search-backend-module-pg': patch +--- + +Search Engines will now index documents in batches of 1000 instead of 100 (under the hood). This may result in your Backstage backend consuming slightly more memory during index runs, but should dramatically improve indexing performance for large document sets. diff --git a/.changeset/serious-apricots-collect.md b/.changeset/serious-apricots-collect.md new file mode 100644 index 0000000000..77c5b87bdd --- /dev/null +++ b/.changeset/serious-apricots-collect.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Added sample catalog data to the template under a top-level `examples` directory. This includes some simple entities, org data, and a template. You can find the sample data at https://github.com/backstage/backstage/tree/master/packages/create-app/templates/default-app/examples. diff --git a/.changeset/seven-panthers-pump.md b/.changeset/seven-panthers-pump.md new file mode 100644 index 0000000000..856ab38d21 --- /dev/null +++ b/.changeset/seven-panthers-pump.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Add ARIA landmark(
), & label and a heading to OAuthRequestDialog. Removed nested interactive control (button). diff --git a/.changeset/shiny-apes-design.md b/.changeset/shiny-apes-design.md new file mode 100644 index 0000000000..69dfbf57ab --- /dev/null +++ b/.changeset/shiny-apes-design.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Updated parseEntityTransformParams to handle keys with '.' in them. This will allow for querying of entities based off annotations such as 'backstage.io/orgin-location' or other entity field keys that have '.' in them. diff --git a/.changeset/shiny-moles-study.md b/.changeset/shiny-moles-study.md new file mode 100644 index 0000000000..59ce7d560b --- /dev/null +++ b/.changeset/shiny-moles-study.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Properly highlight `SidebarSubmenuItem` dropdown items on hover, use ellipsis styling on long labels in `SidebarSubmenu`, allow `icon` and `to` properties to be optional on `SidebarSubmenuItem`, and fix `SidebarPage` padding to be responsive to pinned state diff --git a/.changeset/short-ears-sit.md b/.changeset/short-ears-sit.md new file mode 100644 index 0000000000..e75908a37d --- /dev/null +++ b/.changeset/short-ears-sit.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-graph': patch +--- + +Fix kind filter error in the dev app diff --git a/.changeset/shy-rings-mix.md b/.changeset/shy-rings-mix.md new file mode 100644 index 0000000000..de322fdf85 --- /dev/null +++ b/.changeset/shy-rings-mix.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-app-api': patch +--- + +Fix SAML session schema to no longer require the (deprecated) id, to unbreak session data storage. diff --git a/.changeset/sixty-bulldogs-hang.md b/.changeset/sixty-bulldogs-hang.md new file mode 100644 index 0000000000..61367aad08 --- /dev/null +++ b/.changeset/sixty-bulldogs-hang.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Add controls to Storybook stories diff --git a/.changeset/small-eggs-guess.md b/.changeset/small-eggs-guess.md new file mode 100644 index 0000000000..4738a8775a --- /dev/null +++ b/.changeset/small-eggs-guess.md @@ -0,0 +1,34 @@ +--- +'@backstage/plugin-techdocs-module-addons-contrib': patch +--- + +Create a TechDocs `` addon that allows users to set a font size in the browser's local storage for the text of documentation pages. + +Here's an example on how to use it in a Backstage app: + +```diff +import { + DefaultTechDocsHome, + TechDocsIndexPage, + TechDocsReaderPage, +} from '@backstage/plugin-techdocs'; +import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; ++import { TextSize } from '@backstage/plugin-techdocs-module-addons-contrib'; + +const AppRoutes = () => { + + // other plugin routes + }> + + + } + > + ++ + + + ; +}; +``` diff --git a/.changeset/stale-pugs-kiss.md b/.changeset/stale-pugs-kiss.md new file mode 100644 index 0000000000..db25d1ab2a --- /dev/null +++ b/.changeset/stale-pugs-kiss.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Display entity titles in `StarredEntities` home page card (if defined) and don't show entities which no longer exist diff --git a/.changeset/techdocs-bob-law-blog.md b/.changeset/techdocs-bob-law-blog.md new file mode 100644 index 0000000000..581ab19bec --- /dev/null +++ b/.changeset/techdocs-bob-law-blog.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-techdocs-react': major +'@backstage/plugin-techdocs-addons-test-utils': major +'@backstage/plugin-techdocs-module-addons-contrib': major +--- + +The TechDocs Addon framework is now generally available. diff --git a/.changeset/techdocs-hot-berries-collect.md b/.changeset/techdocs-hot-berries-collect.md new file mode 100644 index 0000000000..efb8dcc7c9 --- /dev/null +++ b/.changeset/techdocs-hot-berries-collect.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Loading SVGs correctly with `bota` with extended characters diff --git a/.changeset/techdocs-light-treason.md b/.changeset/techdocs-light-treason.md new file mode 100644 index 0000000000..52136a732d --- /dev/null +++ b/.changeset/techdocs-light-treason.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-node': patch +--- + +Updated the default version of the `@spotify/techdocs` container used when `techdocs.generator.runIn` is `docker` to `v1.0.3`. diff --git a/.changeset/techdocs-loose-seal-blooth.md b/.changeset/techdocs-loose-seal-blooth.md new file mode 100644 index 0000000000..fc6e809077 --- /dev/null +++ b/.changeset/techdocs-loose-seal-blooth.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-addons-test-utils': patch +--- + +Fixed a bug preventing testing of TechDocs Addons whose dom contained `` tags. diff --git a/.changeset/techdocs-money-banana-stand.md b/.changeset/techdocs-money-banana-stand.md new file mode 100644 index 0000000000..43cbfaafbf --- /dev/null +++ b/.changeset/techdocs-money-banana-stand.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-addons-test-utils': patch +--- + +The `TechDocsAddonTester` class may now be extended if custom test configuration is needed. diff --git a/.changeset/techdocs-steve-holt.md b/.changeset/techdocs-steve-holt.md new file mode 100644 index 0000000000..c456d48cf8 --- /dev/null +++ b/.changeset/techdocs-steve-holt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Hidden exports related to experimental TechDocs reader functionality have been removed and can no longer be imported. In the unlikely event you were using these exports, you can now take advantage of the officially supported and generally available TechDocs Addon framework instead. diff --git a/.changeset/techdocs-wee-britain.md b/.changeset/techdocs-wee-britain.md new file mode 100644 index 0000000000..661ff76fc5 --- /dev/null +++ b/.changeset/techdocs-wee-britain.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-addons-test-utils': patch +--- + +Fixed a type bug preventing `buildAddonsInTechDocs().withApis()` from being called with multiple partial API implementations. diff --git a/.changeset/thick-tools-dream.md b/.changeset/thick-tools-dream.md new file mode 100644 index 0000000000..4979c62787 --- /dev/null +++ b/.changeset/thick-tools-dream.md @@ -0,0 +1,40 @@ +--- +'@backstage/create-app': patch +--- + +Implement highlighting matching terms in search results. To enable this for an existing app, make the following changes: + +```diff +// packages/app/src/components/search/SearchPage.tsx +... +- {results.map(({ type, document }) => { ++ {results.map(({ type, document, highlight }) => { + switch (type) { + case 'software-catalog': + return ( + + ); + case 'techdocs': + return ( + + ); + default: + return ( + + ); + } + })} +... +``` diff --git a/.changeset/tricky-laws-thank.md b/.changeset/tricky-laws-thank.md new file mode 100644 index 0000000000..c9efa0c495 --- /dev/null +++ b/.changeset/tricky-laws-thank.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog': patch +'@backstage/plugin-search': patch +'@backstage/plugin-search-react': patch +'@backstage/plugin-techdocs': patch +--- + +Updated search result components to support rendering content with highlighted matched terms diff --git a/.changeset/warm-suns-wonder.md b/.changeset/warm-suns-wonder.md new file mode 100644 index 0000000000..9f52889fca --- /dev/null +++ b/.changeset/warm-suns-wonder.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': patch +'@backstage/plugin-search-backend-node': patch +'@backstage/plugin-search-common': patch +--- + +Support generating highlighted matched terms in search result data diff --git a/.changeset/wise-countries-watch.md b/.changeset/wise-countries-watch.md new file mode 100644 index 0000000000..e48e7bbecb --- /dev/null +++ b/.changeset/wise-countries-watch.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-azure-devops': patch +'@backstage/plugin-azure-devops-backend': patch +'@backstage/plugin-azure-devops-common': patch +--- + +Added entity view for Azure Git Tags, based on existing Pull Requests view diff --git a/.changeset/wise-doors-hammer.md b/.changeset/wise-doors-hammer.md new file mode 100644 index 0000000000..68160a3b64 --- /dev/null +++ b/.changeset/wise-doors-hammer.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Include namespace in `MyGroupSidebarItem` if not default and remove root item routing if there are multiple groups diff --git a/.changeset/witty-lions-reply.md b/.changeset/witty-lions-reply.md new file mode 100644 index 0000000000..d79937e027 --- /dev/null +++ b/.changeset/witty-lions-reply.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Make Menu item on filters accessible through keyboard diff --git a/.github/renovate.json5 b/.github/renovate.json5 index ff351a5e0f..a8bc3448a5 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -3,7 +3,7 @@ extends: ['config:base', ':disableDependencyDashboard', ':gitSignOff'], rangeStrategy: 'update-lockfile', // @elastic/elasticsearch is ignored due to licensing issues. See #10992 - ignoreDeps: ['@elastic/elasticsearch'], + ignoreDeps: ['@elastic/elasticsearch', 'event-source-polyfill'], packageRules: [ { matchSourceUrlPrefixes: ['https://github.com/spotify/web-scripts'], diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index 32044d66a1..34c33c3e8c 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -45,6 +45,8 @@ codeblocks Codecov codehilite Codehilite +codescene +CodeScene codemod codemods codeowners diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml index e829029525..3d616506e1 100644 --- a/.github/workflows/automate_area-labels.yml +++ b/.github/workflows/automate_area-labels.yml @@ -6,7 +6,7 @@ jobs: triage: runs-on: ubuntu-latest steps: - - uses: actions/labeler@v3 + - uses: actions/labeler@v4 with: repo-token: '${{ secrets.GITHUB_TOKEN }}' sync-labels: true diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index efcbaf210b..700eae7d0c 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -21,7 +21,7 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.pull_request.user.login != 'backstage-service' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: # Fetch the commit that's merged into the base rather than the target ref # This will let us diff only the contents of the PR, without fetching more history @@ -39,7 +39,7 @@ jobs: node generate.js FETCH_HEAD > feedback.txt - name: Post Feedback - uses: actions/github-script@v5 + uses: actions/github-script@v6 env: ISSUE_NUMBER: ${{ github.event.pull_request.number }} with: diff --git a/.github/workflows/automate_review-labels-scheduled.yaml b/.github/workflows/automate_review-labels-scheduled.yaml index 655581501a..3ba13cfd17 100644 --- a/.github/workflows/automate_review-labels-scheduled.yaml +++ b/.github/workflows/automate_review-labels-scheduled.yaml @@ -16,13 +16,13 @@ jobs: application_private_key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} organization: backstage - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: 14 - run: npm install codeowners - - uses: actions/github-script@v5 + - uses: actions/github-script@v6 id: fix-labels with: github-token: ${{ steps.get_workflow_token.outputs.token }} diff --git a/.github/workflows/automate_review-labels.yaml b/.github/workflows/automate_review-labels.yaml index 074d1271e0..cae71f6aaa 100644 --- a/.github/workflows/automate_review-labels.yaml +++ b/.github/workflows/automate_review-labels.yaml @@ -16,14 +16,14 @@ jobs: label: runs-on: ubuntu-latest steps: - - uses: actions/github-script@v5 + # THESE SCRIPTS SHOULD BE INLINED AND NOT IN REPO + # DUE TO THE TOKEN PERMISSIONS THAT ARE GIVEN + # TO THE WORKFLOW. THIS SCRIPT WILL AND SHOULD + # RUN FROM THE BASE REPO ALL TIMES. + - uses: actions/github-script@v6 id: fix-labels with: github-token: ${{ secrets.GITHUB_TOKEN }} - # THIS SCRIPT SHOULD BE INLINED AND NOT IN REPO - # DUE TO THE TOKEN PERMISSIONS THAT ARE GIVEN - # TO THE WORKFLOW. THIS SCRIPT WILL AND SHOULD - # RUN FROM THE BASE REPO ALL TIMES. script: | if (['opened', 'synchronize'].includes('${{ github.event.action }}')) { // if it's the author, always add awaiting-review label @@ -48,3 +48,37 @@ jobs: console.log(e) }); } + + - name: Add PRs to review board + uses: actions/github-script@v6 + if: github.event.action == 'opened' || github.event.action == 'reopened' + env: + PROJECT_ID: PN_kwDOBFKqdc02LQ + with: + github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} + script: | + const prLookup = await github.graphql(` + query($owner: String!, $repo: String!, $number: Int!){ + repository(owner: $owner, name: $repo) { + pullRequest(number: $number) { + id + } + } + } + `, context.issue); + + await github.graphql(` + mutation($projectId: ID!, $contentId: ID!) { + addProjectNextItem(input: { + projectId: $projectId, + contentId: $contentId, + }) { + projectNextItem { + id + } + } + } + `, { + projectId: process.env.PROJECT_ID, + contentId: prLookup.repository.pullRequest.id + }) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31a315d044..0718c8a8b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,14 +60,14 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: fetch branch master run: git fetch origin master # Beginning of yarn setup, keep in sync between all workflows. # TODO(Rugvip): move this to composite action once all features we use are supported - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -75,7 +75,7 @@ jobs: # Cache every node_modules folder inside the monorepo - name: cache all node_modules id: cache-modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: '**/node_modules' # We use both yarn.lock and package.json as cache keys to ensure that @@ -91,7 +91,7 @@ jobs: run: echo "::set-output name=dir::$(yarn cache dir)" - name: cache global yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: steps.cache-modules.outputs.cache-hit != 'true' with: path: ${{ steps.yarn-cache.outputs.dir }} diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index 7931f7ade5..d0f8dc1e79 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -17,10 +17,10 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -55,8 +55,7 @@ jobs: run: ls microsite/build/backstage && ls microsite/build/backstage/storybook - name: Deploy both microsite and storybook to gh-pages - uses: JamesIves/github-pages-deploy-action@3.7.1 + uses: JamesIves/github-pages-deploy-action@v4.3.3 with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: gh-pages - FOLDER: microsite/build/backstage + branch: gh-pages + folder: microsite/build/backstage diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index 85668bdc3a..c90894bce4 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -18,17 +18,17 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: cache all node_modules id: cache-modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: '**/node_modules' key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} @@ -37,7 +37,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: echo "::set-output name=dir::$(yarn cache dir)" - name: cache global yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: steps.cache-modules.outputs.cache-hit != 'true' with: path: ${{ steps.yarn-cache.outputs.dir }} diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index bcb4016ab9..b63507df0c 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -59,17 +59,17 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: cache all node_modules id: cache-modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: '**/node_modules' key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} @@ -78,7 +78,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: echo "::set-output name=dir::$(yarn cache dir)" - name: cache global yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: steps.cache-modules.outputs.cache-hit != 'true' with: path: ${{ steps.yarn-cache.outputs.dir }} @@ -155,17 +155,17 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: cache all node_modules id: cache-modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: '**/node_modules' key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} @@ -174,7 +174,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: echo "::set-output name=dir::$(yarn cache dir)" - name: cache global yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: steps.cache-modules.outputs.cache-hit != 'true' with: path: ${{ steps.yarn-cache.outputs.dir }} diff --git a/.github/workflows/sync_approve_renovate_pr.yaml b/.github/workflows/sync_approve_renovate_pr.yaml index e2eb6998cb..2d25bea223 100644 --- a/.github/workflows/sync_approve_renovate_pr.yaml +++ b/.github/workflows/sync_approve_renovate_pr.yaml @@ -18,12 +18,6 @@ jobs: const owner = 'backstage'; const repo = 'backstage'; - const date = new Date(); - if (date.getDay() === 2) { - console.log('Skipping auto approve because Tuesday is release day'); - return; - } - const r = await github.rest.pulls.listFiles({ owner, repo, diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index c1a4b9e1d0..b6fce0e68d 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -9,20 +9,20 @@ jobs: name: Autofix Markdown files using Prettier runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: # Fetch changes to previous commit - required for 'only_changed' in Prettier action fetch-depth: 0 # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: cache all node_modules id: cache-modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: '**/node_modules' key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} @@ -31,7 +31,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: echo "::set-output name=dir::$(yarn cache dir)" - name: cache global yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: steps.cache-modules.outputs.cache-hit != 'true' with: path: ${{ steps.yarn-cache.outputs.dir }} @@ -43,7 +43,7 @@ jobs: # End of yarn setup - name: Run Prettier on ADOPTERS.md - uses: creyD/prettier_action@v3.3 + uses: creyD/prettier_action@v4.2 with: # Modifies commit only if prettier autofixed the ADOPTERS.md prettier_options: --config docs/prettier.config.js --write ADOPTERS.md diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml index 58e0a1ac0f..d5f6f9a36c 100644 --- a/.github/workflows/sync_dependabot-changesets.yml +++ b/.github/workflows/sync_dependabot-changesets.yml @@ -11,7 +11,7 @@ jobs: if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage' steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -21,7 +21,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@v5 + uses: actions/github-script@v6 with: script: | const { promises: fs } = require('fs'); diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index 328c64fb58..816a3e632f 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: # Setup node & install deps before checkout, keeping install quick - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 with: node-version: 16 - name: Install dependencies @@ -19,7 +19,7 @@ jobs: run: npm install semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1 - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: backstage # 'v' prefix is added here for the tag, we keep it out of the manifest logic @@ -27,7 +27,7 @@ jobs: # Checkout backstage/versions into /backstage/versions, which is where store the output - name: Checkout versions - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: backstage/versions path: backstage/versions @@ -51,7 +51,7 @@ jobs: git push - name: Dispatch update-helper update - uses: actions/github-script@v5 + uses: actions/github-script@v6 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} # TODO(Rugvip): Remove the create-app dispatch once we've been on the release version for a while diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml index 60eabde769..cd67fa9954 100644 --- a/.github/workflows/sync_renovate-changesets.yml +++ b/.github/workflows/sync_renovate-changesets.yml @@ -11,7 +11,7 @@ jobs: if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage' steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -21,7 +21,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@v5 + uses: actions/github-script@v6 with: script: | const { promises: fs } = require("fs"); diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 0bf0340f68..e45a36c8e8 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -14,17 +14,17 @@ jobs: node-version: [14.x] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: cache all node_modules id: cache-modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: '**/node_modules' key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} @@ -33,7 +33,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: echo "::set-output name=dir::$(yarn cache dir)" - name: cache global yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: steps.cache-modules.outputs.cache-hit != 'true' with: path: ${{ steps.yarn-cache.outputs.dir }} diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index bf50748dc0..d6adca927e 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -18,7 +18,7 @@ jobs: sync: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Monitor and Synchronize Snyk Policies uses: snyk/actions/node@master with: @@ -45,6 +45,6 @@ jobs: env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - name: Upload Snyk report - uses: github/codeql-action/upload-sarif@v1 + uses: github/codeql-action/upload-sarif@v2 with: sarif_file: snyk.sarif diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml index a6a544e6a5..926906338f 100644 --- a/.github/workflows/sync_version-packages.yml +++ b/.github/workflows/sync_version-packages.yml @@ -9,7 +9,7 @@ jobs: name: Create Changeset PR runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index a275e357a4..f3417ac582 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -35,7 +35,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -43,7 +43,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -54,7 +54,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -68,4 +68,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/verify_dco.yaml b/.github/workflows/verify_dco.yaml index e2da767394..71bd322eca 100644 --- a/.github/workflows/verify_dco.yaml +++ b/.github/workflows/verify_dco.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Verify DCO status for open pull requests - uses: actions/github-script@v5 + uses: actions/github-script@v6 with: script: | const owner = "backstage"; diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml index ad2e92799f..fe8849a085 100644 --- a/.github/workflows/verify_docs-quality.yml +++ b/.github/workflows/verify_docs-quality.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Vale does not support file excludes, so we use the script to generate a list of files instead # The action also does not allow args or a local config file to be passed in, so the files array diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index f3e38dc68b..884d8bf172 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -38,17 +38,17 @@ jobs: name: Node ${{ matrix.node-version }} on ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: cache all node_modules id: cache-modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: '**/node_modules' key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} @@ -59,7 +59,7 @@ jobs: - name: setup chrome uses: browser-actions/setup-chrome@latest - name: cache global yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: steps.cache-modules.outputs.cache-hit != 'true' with: path: ${{ steps.yarn-cache.outputs.dir }} diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index b9dfdc23eb..c8f825796b 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -25,8 +25,8 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 - name: install dependencies run: yarn install --frozen-lockfile diff --git a/.github/workflows/verify_e2e-tugboat.yml b/.github/workflows/verify_e2e-tugboat.yml index 1054ccf579..04d9e686e2 100644 --- a/.github/workflows/verify_e2e-tugboat.yml +++ b/.github/workflows/verify_e2e-tugboat.yml @@ -10,12 +10,12 @@ jobs: # Set an initial commit status message to indicate that the tests are # running. - name: set pending status - uses: actions/github-script@v3 + uses: actions/github-script@v6 with: github-token: ${{secrets.GH_SERVICE_ACCOUNT_TOKEN}} debug: true script: | - return github.repos.createCommitStatus({ + return github.rest.repos.createCommitStatus({ owner: context.repo.owner, repo: context.repo.repo, sha: context.sha, @@ -34,12 +34,12 @@ jobs: # Set an initial commit status message to indicate that the tests are # running. - name: set pending status - uses: actions/github-script@v3 + uses: actions/github-script@v6 with: github-token: ${{secrets.GH_SERVICE_ACCOUNT_TOKEN}} debug: true script: | - return github.repos.createCommitStatus({ + return github.rest.repos.createCommitStatus({ owner: context.repo.owner, repo: context.repo.repo, sha: context.sha, @@ -49,8 +49,8 @@ jobs: target_url: "https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}" }); - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: '14' @@ -65,12 +65,12 @@ jobs: # https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/ - name: get deployment status id: get-status-env - uses: actions/github-script@v3 + uses: actions/github-script@v6 with: github-token: ${{secrets.GH_SERVICE_ACCOUNT_TOKEN}} result-encoding: string script: | - const result = await github.repos.getDeploymentStatus({ + const result = await github.rest.repos.getDeploymentStatus({ owner: context.repo.owner, repo: context.repo.repo, deployment_id: context.payload.deployment.id, @@ -95,18 +95,18 @@ jobs: - name: update artifact if: ${{ always() }} - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v3 with: name: cypress-videos path: ./cypress/cypress/videos - name: set status if: ${{ failure() }} - uses: actions/github-script@v3 + uses: actions/github-script@v6 with: github-token: ${{secrets.GH_SERVICE_ACCOUNT_TOKEN}} script: | - return github.repos.createCommitStatus({ + return github.rest.repos.createCommitStatus({ owner: context.repo.owner, repo: context.repo.repo, sha: context.sha, @@ -117,11 +117,11 @@ jobs: - name: set status if: ${{ success() }} - uses: actions/github-script@v3 + uses: actions/github-script@v6 with: github-token: ${{secrets.GH_SERVICE_ACCOUNT_TOKEN}} script: | - return github.repos.createCommitStatus({ + return github.rest.repos.createCommitStatus({ owner: context.repo.owner, repo: context.repo.repo, sha: context.sha, diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index becff56953..129c246a73 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -37,10 +37,10 @@ jobs: git config --global core.autocrlf false git config --global core.eol lf - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: Add msbuild to PATH diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml index 6126ae9bf2..8c6b25d2e4 100644 --- a/.github/workflows/verify_fossa.yml +++ b/.github/workflows/verify_fossa.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Fossa run: "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | bash" diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index 24a6ff5351..bd091b857e 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -19,10 +19,10 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index 60f58f4c66..a13aa3ae71 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -19,19 +19,19 @@ jobs: chromatic: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 # Required to retrieve git history # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: cache all node_modules id: cache-modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: '**/node_modules' key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} @@ -40,7 +40,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: echo "::set-output name=dir::$(yarn cache dir)" - name: cache global yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 if: steps.cache-modules.outputs.cache-hit != 'true' with: path: ${{ steps.yarn-cache.outputs.dir }} diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index 7156bec4f6..bb8aa9e5aa 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -24,11 +24,11 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -36,7 +36,7 @@ jobs: id: yarn-cache run: echo "::set-output name=dir::$(yarn cache dir)" - name: cache global yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ${{ steps.yarn-cache.outputs.dir }} key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} diff --git a/ADOPTERS.md b/ADOPTERS.md index bd9da8393d..3915aee949 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -123,3 +123,7 @@ _If you're using Backstage in your organization, please try to add your company | [leboncoin](https://www.leboncoin.fr/) | [Andy Ladjadj](https://github.com/aladjadj) | Centralize our multiple UI in a single portal. Simplify onbording, new features and harmonize how people search information. Core features (catalog,api,docs,scafolder) are good to start the adoption. status: internal beta. | | [Contentful](https://www.contentful.com) | [James Bourne](https://github.com/jamesmbourne) | Centralized documentation of service ownership, APIs, and documentation, and new service creation with a custom scaffolder - [full case study with Roadie](https://roadie.io/case-studies/maintaining-velocity-through-hypergrowth-contentful/). | | [Back Market](https://www.backmarket.com) | [Sami Farhat](https://github.com/skfarhat) | Internal Developer Portal featuring catalog, tech-radar, ownership management, component creation (scaffolder) and centralized infrastructure management -- probably more to come. | +| [Avalia Systems](https://avalia.io) | [Olivier Liechti](https://github.com/wasadigi), [Fabio Velloso](https://github.com/fabiovelloso) | Innersource, software analytics, knowledge base for 360 software assessments, collaborative applications, hub for tracking and sharing IP assets. | +| [Albert Heijn](https://ah.technology) | [Joost Hofman](https://github.com/joosthofman), [Reindrich Geerman](https://github.com/reinst) | Single point of entry for all our engineers (Developer portal), Tech radar, catalog, templates (paved roads) and tech documentation. | +| [Wise, formerly TransferWise](https://wise.com) | [Andrew Beveridge](https://github.com/beveradb) | It's early days for us, we're trying to start small with catalog, tech docs and unified search. Future ambitious vision includes scaffolder for one-click component addition, building out integrations with CI/CD tooling, kubernetes clusters, monitoring/alerting tooling etc. and aiming for a frictionless "golden path" for engineers! 🚀 | + diff --git a/app-config.yaml b/app-config.yaml index 1156b9b340..eb51c59847 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -203,8 +203,6 @@ catalog: - Component - API - Resource - - Group - - User - Template - System - Domain @@ -243,7 +241,7 @@ catalog: # Add a location here to ingest it, for example from a URL: # # - type: url - # target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-components.yaml + # target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all.yaml # # For local development you can use a file location instead: # @@ -253,33 +251,23 @@ catalog: # File locations are relative to the current working directory of the # backend, for example packages/backend/. - # Backstage example components + # Backstage example entities - type: file - target: ../catalog-model/examples/all-components.yaml + target: ../catalog-model/examples/all.yaml + # Backstage example groups and users + - type: file + target: ../catalog-model/examples/acme-corp.yaml + rules: + - allow: [User, Group] # Example component for github-actions and TechDocs - type: file target: ../../plugins/github-actions/examples/sample.yaml # Example component for TechDocs - type: file target: ../../plugins/techdocs-backend/examples/documented-component/catalog-info.yaml - # Backstage example APIs - - type: file - target: ../catalog-model/examples/all-apis.yaml - # Backstage example resources - - type: file - target: ../catalog-model/examples/all-resources.yaml - # Backstage example systems - - type: file - target: ../catalog-model/examples/all-systems.yaml - # Backstage example domains - - type: file - target: ../catalog-model/examples/all-domains.yaml # Backstage example templates - type: file target: ../../plugins/scaffolder-backend/sample-templates/all-templates.yaml - # Backstage example groups and users - - type: file - target: ../catalog-model/examples/acme-corp.yaml # Backstage end-to-end tests of TechDocs - type: file target: ../../cypress/e2e-fixture.catalog.info.yaml diff --git a/contrib/chart/backstage/Chart.lock b/contrib/chart/backstage/Chart.lock index d18a48a655..2a304bd917 100644 --- a/contrib/chart/backstage/Chart.lock +++ b/contrib/chart/backstage/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 9.8.12 -digest: sha256:549b9a0cdf7b2e0ad949ebad853a467bf320928970a946fb0ef7e13e9bdb7a10 -generated: "2022-04-21T07:02:48.301491565Z" + version: 11.1.28 +digest: sha256:91deeef78a140252c1ec9fbdf011e5584fc26b67f5a5dc9b6c90be2eee838499 +generated: "2022-05-06T14:02:33.227808666Z" diff --git a/contrib/chart/backstage/Chart.yaml b/contrib/chart/backstage/Chart.yaml index 9770ef665c..43c1615d2f 100644 --- a/contrib/chart/backstage/Chart.yaml +++ b/contrib/chart/backstage/Chart.yaml @@ -18,7 +18,7 @@ sources: dependencies: - name: postgresql condition: postgresql.enabled - version: 9.8.12 + version: 11.1.28 repository: https://charts.bitnami.com/bitnami maintainers: diff --git a/docs/assets/techdocs/addon-locations.png b/docs/assets/techdocs/addon-locations.png index e535fe61aa..0541f35af5 100644 Binary files a/docs/assets/techdocs/addon-locations.png and b/docs/assets/techdocs/addon-locations.png differ diff --git a/docs/features/kubernetes/configuration.md b/docs/features/kubernetes/configuration.md index 5b60316fd0..246e4dcd43 100644 --- a/docs/features/kubernetes/configuration.md +++ b/docs/features/kubernetes/configuration.md @@ -85,13 +85,14 @@ array. Users will see this value in the Software Catalog Kubernetes plugin. This determines how the Kubernetes client authenticates with the Kubernetes cluster. Valid values are: -| Value | Description | -| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `serviceAccount` | This will use a Kubernetes [service account](https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/) to access the Kubernetes API. When this is used the `serviceAccountToken` field should also be set. | -| `google` | This will use a user's Google auth token from the [Google auth plugin](https://backstage.io/docs/auth/) to access the Kubernetes API. | -| `aws` | This will use AWS credentials to access resources in EKS clusters | -| `googleServiceAccount` | This will use the Google Cloud service account credentials to access resources in clusters | -| `azure` | This will use [Azure Identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) to access resources in clusters | +| Value | Description | +| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `serviceAccount` | This will use a Kubernetes [service account](https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/) to access the Kubernetes API. When this is used the `serviceAccountToken` field should also be set. | +| `google` | This will use a user's Google auth token from the [Google auth plugin](https://backstage.io/docs/auth/) to access the Kubernetes API. | +| `aws` | This will use AWS credentials to access resources in EKS clusters | +| `googleServiceAccount` | This will use the Google Cloud service account credentials to access resources in clusters | +| `azure` | This will use [Azure Identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) to access resources in clusters | +| `oidc` | This will use [Oidc Tokens](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens) to authenticate to the Kubernetes API. When this is used the `oidcTokenProvider` field should also be set. | ##### `clusters.\*.skipTLSVerify` @@ -115,6 +116,33 @@ kubectl -n get secret $(kubectl -n get sa ); default: @@ -78,6 +79,7 @@ export const searchPage = ( ); } @@ -266,6 +268,7 @@ an example: ); // ... diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md index c5f53c905f..64787ec3c1 100644 --- a/docs/features/search/how-to-guides.md +++ b/docs/features/search/how-to-guides.md @@ -67,11 +67,24 @@ getting started guide. import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend'; ``` -2. Register the `DefaultTechDocsCollatorFactory` with the IndexBuilder. +2. If there isn't an existing schedule you'd like to run the collator on, be + sure to create it first. Something like... + +```typescript +import { Duration } from 'luxon'; + +const every10MinutesSchedule = env.scheduler.createScheduledTaskRunner({ + frequency: Duration.fromObject({ seconds: 600 }), + timeout: Duration.fromObject({ seconds: 900 }), + initialDelay: Duration.fromObject({ seconds: 3 }), +}); +``` + +3. Register the `DefaultTechDocsCollatorFactory` with the IndexBuilder. ```typescript indexBuilder.addCollator({ - defaultRefreshIntervalSeconds: 600, + schedule: every10MinutesSchedule, factory: DefaultTechDocsCollatorFactory.fromConfig(env.config, { discovery: env.discovery, logger: env.logger, @@ -398,6 +411,29 @@ export class YourSearchEngine implements SearchEngine { } ``` +## How to customize search results highlighting styling + +The default highlighting styling for matched terms in search results is your +browsers default styles for the `` HTML tag. If you want to customize +how highlighted terms look you can follow Backstage's guide on how to +[Customize the look-and-feel of your App](https://backstage.io/docs/getting-started/app-custom-theme) +to create an override with your preferred styling. + +For example, the following will result in highlighted terms to be bold & underlined: + +```jsx +const highlightOverride = { + BackstageHighlightedSearchResultText: { + highlight: { + color: 'inherit', + backgroundColor: 'inherit', + fontWeight: 'bold', + textDecoration: 'underline', + }, + }, +}; +``` + [obj-mode]: https://nodejs.org/docs/latest-v14.x/api/stream.html#stream_object_mode [read-stream]: https://nodejs.org/docs/latest-v14.x/api/stream.html#stream_readable_streams [async-gen]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of#iterating_over_async_generators diff --git a/docs/features/techdocs/README.md b/docs/features/techdocs/README.md index c64d0b785d..5ac275b8b4 100644 --- a/docs/features/techdocs/README.md +++ b/docs/features/techdocs/README.md @@ -82,13 +82,17 @@ With the Backstage 1.2 release, we plan to introduce the [TechDocs Addon Framewo In addition to the framework itself, we'll be open sourcing a `` addon, helping you to create a feedback loop that drives up documentation quality and fosters a documentation culture at your organization. -### **Future work 🔮** +### **Next** -Some of the following items are coming soon and some are potential ideas. +- What can we do in TechDocs to drive up documentation quality? +### **Someday/Maybe** + +- Contribute to and deploy from a marketplace of TechDocs Addons +- Addon: MDX (allows you to use JSX in your Markdown content) +- Can we go static site generator agnostic? - Better integration with - [Scaffolder V2](https://github.com/backstage/backstage/issues/2771) (e.g. easy to choose and plug documentation template with Software Templates) -- Static site generator agnostic, including possible support for MDX (allowing you to use JSX in your Markdown content) + [Scaffolder V2](https://github.com/backstage/backstage/issues/2771) (e.g. easy to choose and apply documentation template with Software Templates) - Possible to configure several aspects about TechDocs (e.g. URL, homepage, theme) diff --git a/docs/features/techdocs/addons.md b/docs/features/techdocs/addons.md index 0fba3b92e3..e8af56d3fc 100644 --- a/docs/features/techdocs/addons.md +++ b/docs/features/techdocs/addons.md @@ -35,6 +35,8 @@ representative of physical spaces in the TechDocs UI: line as the title. - `Subheader`: For Addons that sit below the header but above all content. This is a great location for tooling/configuration of TechDocs display. +- `Settings`: These addons are items added to the settings menu list and are designed to make + the reader experience customizable, for example accessibility options. - `PrimarySidebar`: Left of the content, above of the navigation. - `SecondarySidebar`: Right of the content, above the table of contents. - `Content`: A special location intended for Addons which augment the @@ -109,9 +111,10 @@ page header, TechDocs Addons whose location is `Header` will not be rendered. Addons can, in principle, be provided by any plugin! To make it easier to discover available Addons, we've compiled a list of them here: -| Addon | Package/Plugin | Description | -| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.reportissue) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. | +| Addon | Package/Plugin | Description | +| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.reportissue) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. | +| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.textsize) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. | Got an Addon to contribute? Feel free to add a row above! diff --git a/docs/features/techdocs/cli.md b/docs/features/techdocs/cli.md index 9a7dccd5a6..52c389975e 100644 --- a/docs/features/techdocs/cli.md +++ b/docs/features/techdocs/cli.md @@ -120,7 +120,7 @@ Generate TechDocs documentation site using MkDocs. Options: --source-dir Source directory containing mkdocs.yml and docs/ directory. (default: ".") --output-dir Output directory containing generated TechDocs site. (default: "./site/") - --docker-image The mkdocs docker container to use (default: "spotify/techdocs:v1.0.2") + --docker-image The mkdocs docker container to use (default: "spotify/techdocs:v1.0.3") --no-pull Do not pull the latest docker image --no-docker Do not use Docker, use MkDocs executable and plugins in current user environment. --techdocs-ref The repository hosting documentation source files e.g. diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index 8ecd7c4a38..106bf56f79 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -6,80 +6,101 @@ description: Roadmap of Backstage ## The Backstage Roadmap -Backstage is currently under rapid development. This page details the project’s +Backstage is currently under rapid development. This page details the project's public roadmap, the result of ongoing collaboration between the core maintainers and the broader Backstage community. -The Backstage roadmap lays out both [“what’s next”](#whats-next) and -[“future work”](#future-work). With "next" we mean features planned for release -within the ongoing quarter from January through March 2022. With "future" we -mean features in the radar, but not yet scheduled. +The Backstage roadmap lays out both [“what's next”](#whats-next) and ["future +work"](#future-work). With "next" we mean features planned for release within +the ongoing quarter from January through March 2022. With "future" we mean +features on the radar, but not yet scheduled. -| [What's next](#whats-next) | [Future work](#future-work) | -| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Backstage 1.0 (and following versions)](#backstage-10-and-following-versions)
[Backstage Security Audit](#backstage-security-audit)
[Moving to Incubation in CNCF](#moving-to-incubation-in-cncf) | Backend Services
Security Plan (and Strategy)
TechDocs Addon framework
Composable Homepage 1.0
GraphQL
Telemetry
Improved UX design | +| [What's next](#whats-next) | [Future work](#future-work) | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| [Ease of onboarding](#ease-of-onboarding)
[Search 1.0](#search-1.0)
[TechDocs Addon framework](#techdocs-addon-framework)
[Backend Services (initial)](#backend-services-initial)
[Backstage Security Audit](#backstage-security-audit)
[SIGs for contributors](#sigs-for-contributors) | Security Plan (and Strategy)
Composable Homepage 1.0
GraphQL
Telemetry
Improved UX design | The long-term roadmap (12 - 36 months) is not detailed in the public roadmap. Third-party contributions are also not currently included in the roadmap. Let us -know about any ongoing developments and we’re happy to include them here as well. +know about any ongoing developments and we're happy to include them here as +well. -## What’s next +## What's next The feature set below is planned for the ongoing quarter, and grouped by theme. -The list order doesn’t necessarily reflect priority, and the development/release +The list order doesn't necessarily reflect priority, and the development/release cycle will vary based on maintainer schedules. -### Backstage 1.0 (and following versions) +### Ease of onboarding -During the first quarter of 2022, we plan to finalize and release version 1.0 of -the Backstage platform (which includes Core, -[Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview), -[Scaffolder](https://backstage.io/docs/features/software-templates/software-templates-index) -and [TechDocs](https://backstage.io/docs/features/techdocs/techdocs-overview)). -Included as part of this milestone: +A faster (with less development) and easier setup of a proof-of-concept +deployment, as part of the onboarding experience, has been a common and loud +suggestion from new adopters as well as analysts looking at Backstage. -- Deciding on the cadence of minor/weekly/daily releases to provide clarity on - the frequency and expectations for future versions of the platform and its - defining modules. -- Establish the support model to set the expectations from the adopters in their - respective use cases. +With this initiative we plan to start facing this important topic with the most +commonly used and challenging tasks. More in particular we plan to reduce the +effort required to go from zero to production in installing and customizing +Backstage, as well as reducing the effort required to populate the Software +Catalog. + +More iterations will be required in the following quarters, but this will be a +good improvement in the onboarding experience, especially for the benefit of new +adopters. + +### Search 1.0 + +Fix the few remaining issues to get Backstage Search platform up to 1.0 +([here](https://github.com/backstage/backstage/milestone/27) and +[here](https://github.com/backstage/backstage/milestone/28)). + +### TechDocs Addon framework + +Addons are TechDocs features that are added on top of the base docs-like-code +experience. An example would be a feature that showed comments on the page. We +plan to add an Addon framework and open source a selection of the Addons that we +use internally at Spotify. Further Addons can then be added by the Community. + +### Backend Services (initial) + +To better scale and maintain the Backstage instances, a backend services system +is planned to be introduced as part of the software architecture. This layer of +backend services will help in decoupling the various modules (e.g. Catalog and +Scaffolder) from the frontend experience. + +In this quarter we plan to start designing the new architecture, together with +the first experimentation and development of the software components. ### Backstage Security Audit +This is the continuation of the initiative started in the previous quarter. This +quarter will see the publication of the report describing the outcome of the +audit, together the first fixes and the development of some of the changes +required to address the vulnerabilities. + This initiative is the first of a broader Security Strategy for Backstage. The purpose of the Security Audit is to involve third-party companies in auditing -the platform and highlighting potential vulnerabilities. The benefit for the -adopters is clear: We want Backstage to be as secure as possible, and we want to -make it reliable through a specific initiative. This initiative in particular is -done together, and with the support of, the -[Cloud Native Computing Foundation (CNCF)](https://www.cncf.io/). +the platform. The benefit for the adopters is clear: we want Backstage to be as +secure as possible, and we want to make it reliable through a specific +initiative. -### Moving to Incubation in CNCF +This initiative is done together with, and with the support of, the [Cloud +Native Computing Foundation (CNCF)](https://www.cncf.io/). -The progress of the request can be seen -[here](https://github.com/cncf/toc/pull/717). +### SIGs for contributors + +The request to better coordinate the increasing number of contributions coming +from the various adopters' developers is loud and clear. We think that the +community is mature enough to start launching the SIGs (Special Interest Groups) +following the successful model of Kubernetes. ## Future work -The following feature list doesn’t represent a commitment to develop, and the -list order doesn’t reflect any priority or importance, but these features are on -the maintainers’ radar, with clear interest expressed by the community. +The following feature list doesn't represent a commitment to develop, and the +list order doesn't reflect any priority or importance, but these features are on +the maintainers' radar, with clear interest expressed by the community. -- **Backend Services:** To better scale and maintain the Backstage instances, a - backend layer of services is planned to be introduced as part of the software - architecture. This layer of backend services will help in decoupling the - various modules (e.g. Catalog and Scaffolder) from the frontend experience. - **Security Plan (and Strategy):** The purpose of the Security Strategy is to move another step along the path to maturing the platform, setting the expectations of any adopters from a security standpoint. -- **Search 1.0:** Fix the few remaining issues to get Backstage Search platform - up to 1.0 ([here](https://github.com/backstage/backstage/milestone/27) and - [here](https://github.com/backstage/backstage/milestone/28)). -- **TechDocs Addon framework and Addons:** Addons are TechDocs features that are - added on top of the base docs like code experience. An example would be a - feature that showed comments on the page. We plan to add an Addon framework - and open source a selection of the Addons that we use internally at Spotify. - Further Addons can then be added by the Community. - **Composable Homepage 1.0:** Driving this to 1.0 by adding some composable components. - **[GraphQL](https://graphql.org/) support:** Introduce the ability to query @@ -107,51 +128,5 @@ guidelines to get started. If you have specific questions about the roadmap, please create an [issue](https://github.com/backstage/backstage/issues/new/choose), ping us on -[Discord](https://discord.gg/qxsEfa8Vq8), or -[book time](http://calendly.com/spotify-backstage) with the Spotify team. - -## Completed milestones - -Read more about the completed (and released) features for reference. - -- [[Search] ElasticSearch integration](https://backstage.io/docs/features/search/search-engines#elasticsearch) -- [[Search] TechDocs search capabilities](https://backstage.io/docs/features/search/how-to-guides#how-to-index-techdocs-documents) -- [TechDocs Beta](https://backstage.spotify.com/blog/product-updates/techdocs-beta-has-landed) -- [[Home] Composable homepage](https://github.com/backstage/backstage/milestone/34) -- [[Search] Out-of-the-Box Implementation (Alpha)](https://github.com/backstage/backstage/milestone/26) -- [Deploy a product demo at `demo.backstage.io`](https://demo.backstage.io) -- [Kubernetes plugin - v1](https://github.com/backstage/backstage/tree/master/plugins/kubernetes) -- [Helm charts](https://github.com/backstage/backstage/tree/master/contrib/chart/backstage) -- [Backstage Design System 💅](https://backstage.io/blog/2020/09/30/backstage-design-system) -- [Cost Insights plugin 💸](https://engineering.atspotify.com/2020/09/29/managing-clouds-from-the-ground-up-cost-engineering-at-spotify/) -- [Donate Backstage to the CNCF 🎉](https://backstage.io/blog/2020/09/23/backstage-cncf-sandbox) -- [TechDocs v1](https://backstage.io/blog/2020/09/08/announcing-tech-docs) -- [Plugin marketplace](https://backstage.io/plugins) -- [Improved and move documentation to backstage.io](https://backstage.io/docs/overview/what-is-backstage) -- [Backstage Software Catalog (alpha)](https://backstage.io/blog/2020/06/22/backstage-service-catalog-alpha) -- [Backstage Software Templates (alpha)](https://backstage.io/blog/2020/08/05/announcing-backstage-software-templates) -- [Make it possible to add custom auth providers](https://backstage.io/blog/2020/07/01/how-to-enable-authentication-in-backstage-using-passport) -- [TechDocs v0](https://github.com/backstage/backstage/milestone/15) -- CI plugins: CircleCI, Jenkins, GitHub Actions and TravisCI -- [Service API documentation](https://github.com/backstage/backstage/pull/1737) -- Backstage Software Catalog can read from: GitHub, GitLab, - [Bitbucket](https://github.com/backstage/backstage/pull/1938) -- Support auth providers: Google, Okta, GitHub, GitLab, - [auth0](https://github.com/backstage/backstage/pull/1611), - [AWS](https://github.com/backstage/backstage/pull/1990) - -- [Donate Backstage to the CNCF 🎉](https://backstage.io/blog/2020/09/23/backstage-cncf-sandbox) -- [TechDocs v1](https://backstage.io/blog/2020/09/08/announcing-tech-docs) -- [Plugin marketplace](https://backstage.io/plugins) -- [Improved and move documentation to backstage.io](https://backstage.io/docs/overview/what-is-backstage) -- [Backstage Software Catalog (alpha)](https://backstage.io/blog/2020/06/22/backstage-service-catalog-alpha) -- [Backstage Software Templates (beta)](https://backstage.io/blog/2021/07/26/software-templates-are-now-in-beta) -- [Make it possible to add custom auth providers](https://backstage.io/blog/2020/07/01/how-to-enable-authentication-in-backstage-using-passport) -- [TechDocs v0](https://github.com/backstage/backstage/milestone/15) -- CI plugins: CircleCI, Jenkins, GitHub Actions and TravisCI -- [Service API documentation](https://github.com/backstage/backstage/pull/1737) -- Backstage Software Catalog can read from: GitHub, GitLab, - [Bitbucket](https://github.com/backstage/backstage/pull/1938) -- Support auth providers: Google, Okta, GitHub, GitLab, - [auth0](https://github.com/backstage/backstage/pull/1611), - [AWS](https://github.com/backstage/backstage/pull/1990) +[Discord](https://discord.gg/qxsEfa8Vq8), or [book +time](http://calendly.com/spotify-backstage) with the Spotify team. diff --git a/docs/releases/v1.2.0-next.2-changelog.md b/docs/releases/v1.2.0-next.2-changelog.md new file mode 100644 index 0000000000..6ca238ccb5 --- /dev/null +++ b/docs/releases/v1.2.0-next.2-changelog.md @@ -0,0 +1,1594 @@ +# Release v1.2.0-next.2 + +## @backstage/plugin-codescene@0.1.0-next.0 + +### Minor Changes + +- 9bc6e9493f: Add CodeScene plugin + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-scaffolder-backend@1.2.0-next.1 + +### Minor Changes + +- f8baf7df44: Added the ability to reference the user in the `template.yaml` manifest + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/plugin-scaffolder-common@1.1.0-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/catalog-client@1.0.2-next.0 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.0-next.1 + +### Minor Changes + +- 3d001a3bcf: **BREAKING**: Added a new `allowedImageNames` option, which needs to list any image name for it to be allowed as `imageName` input. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-scaffolder-backend@1.2.0-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-scaffolder-common@1.1.0-next.0 + +### Minor Changes + +- f8baf7df44: Added the ability to reference the user in the `template.yaml` manifest + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.0.2-next.0 + +## @backstage/backend-common@0.13.3-next.2 + +### Patch Changes + +- e0a6360b80: Added a `stream()` method to complement the `buffer()` method on `ReadUrlResponse`. A `ReadUrlResponseFactory` utility class is now also available, providing a simple, consistent way to provide a valid `ReadUrlResponse`. + + This method, though optional for now, will be required on the responses of `UrlReader.readUrl()` implementations in a future release. + +- 4b811aafce: Implemented the `UrlReader.search()` method for Google Cloud Storage. Due to limitations in the underlying storage API, only prefix-based searches are supported right now (for example, `https://storage.cloud.google.com/your-bucket/some-path/*`). + +- Updated dependencies + - @backstage/cli-common@0.1.9-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/config-loader@1.1.1-next.1 + - @backstage/integration@1.2.0-next.1 + +## @backstage/backend-tasks@0.3.1-next.1 + +### Patch Changes + +- 73480846dd: `TaskScheduleDefinition` has been updated to also accept an options object containing duration information in the form of days, hours, seconds and so on. This allows for scheduling without importing `luxon`. + + ```diff + -import { Duration } from 'luxon'; + // omitted other code + + const schedule = env.scheduler.createScheduledTaskRunner({ + - frequency: Duration.fromObject({ minutes: 10 }), + - timeout: Duration.fromObject({ minutes: 15 }), + + frequency: { minutes: 10 }, + + timeout: { minutes: 15 }, + // omitted other code + }); + ``` + +- ebbec677e1: Correctly set next run time for tasks + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + +## @backstage/backend-test-utils@0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/cli@0.17.1-next.2 + +## @backstage/catalog-client@1.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.0.2-next.0 + +## @backstage/catalog-model@1.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + +## @backstage/cli@0.17.1-next.2 + +### Patch Changes + +- 632be18bbc: Updated `create-github-app` command to prompt for read or write permissions to simplify setup. +- Updated dependencies + - @backstage/cli-common@0.1.9-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/release-manifests@0.0.3-next.0 + - @backstage/config-loader@1.1.1-next.1 + +## @backstage/cli-common@0.1.9-next.0 + +### Patch Changes + +- 6e830352d4: Updated dependency `@types/node` to `^16.0.0`. + +## @backstage/codemods@0.1.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.9-next.0 + +## @backstage/config@1.0.1-next.0 + +### Patch Changes + +- 6e830352d4: Updated dependency `@types/node` to `^16.0.0`. + +## @backstage/config-loader@1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.9-next.0 + - @backstage/config@1.0.1-next.0 + +## @backstage/core-app-api@1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/core-components@0.9.4-next.1 + +### Patch Changes + +- 55f68c386a: Enabled select component to be enabled by keyboard +- ba97b80421: Updated dependency `@types/react-syntax-highlighter` to `^15.0.0`. +- 2bcb0a0e2b: Sidebar NAV now includes aria-label. Component AboutField now uses h2 variant instead of subtitle2 (font properties unchanged) +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/core-plugin-api@1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + +## @backstage/create-app@0.4.27-next.2 + +### Patch Changes + +- 73480846dd: Simplified the search collator scheduling by removing the need for the `luxon` dependency. + + For existing installations the scheduling can be simplified by removing the `luxon` dependency and using the human friendly duration object instead. + Please note that this only applies if luxon is not used elsewhere in your installation. + + `packages/backend/package.json` + + ```diff + "express": "^4.17.1", + "express-promise-router": "^4.1.0", + - "luxon": "^2.0.2", + ``` + + `packages/backend/src/plugins/search.ts` + + ```diff + import { Router } from 'express'; + -import { Duration } from 'luxon'; + + // omitted other code + + const schedule = env.scheduler.createScheduledTaskRunner({ + - frequency: Duration.fromObject({ minutes: 10 }), + - timeout: Duration.fromObject({ minutes: 15 }), + + frequency: { minutes: 10 }, + + timeout: { minutes: 15 }, + // A 3 second delay gives the backend server a chance to initialize before + // any collators are executed, which may attempt requests against the API. + - initialDelay: Duration.fromObject({ seconds: 3 }), + + initialDelay: { seconds: 3 }, + }); + ``` + +- 7cda923c16: Tweaked the `.dockerignore` file so that it's easier to add additional backend packages if desired. + + To apply this change to an existing app, make the following change to `.dockerignore`: + + ```diff + cypress + microsite + node_modules + -packages + -!packages/backend/dist + +packages/*/src + +packages/*/node_modules + plugins + ``` + +- f55414f895: Added sample catalog data to the template under a top-level `examples` directory. This includes some simple entities, org data, and a template. You can find the sample data at . + +- 3a74e203a8: Implement highlighting matching terms in search results. To enable this for an existing app, make the following changes: + + ```diff + // packages/app/src/components/search/SearchPage.tsx + ... + - {results.map(({ type, document }) => { + + {results.map(({ type, document, highlight }) => { + switch (type) { + case 'software-catalog': + return ( + + ); + case 'techdocs': + return ( + + ); + default: + return ( + + ); + } + })} + ... + ``` + +- Updated dependencies + - @backstage/cli-common@0.1.9-next.0 + +## @backstage/dev-utils@1.0.2-next.2 + +### Patch Changes + +- 6e830352d4: Updated dependency `@types/node` to `^16.0.0`. +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-app-api@1.0.2-next.1 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/test-utils@1.1.0-next.2 + +## @backstage/integration@1.2.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + +## @backstage/integration-react@1.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + +## @backstage/release-manifests@0.0.3-next.0 + +### Patch Changes + +- 6e830352d4: Updated dependency `@types/node` to `^16.0.0`. + +## @backstage/search-common@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-common@0.3.4-next.0 + +## @techdocs/cli@1.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/cli-common@0.1.9-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/plugin-techdocs-node@1.1.1-next.1 + +## @backstage/techdocs-common@0.11.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-node@1.1.1-next.1 + +## @backstage/test-utils@1.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/core-app-api@1.0.2-next.1 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-permission-react@0.4.1-next.1 + +## @backstage/plugin-adr-backend@0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/plugin-adr-common@0.1.0-next.1 + - @backstage/catalog-client@1.0.2-next.0 + +## @backstage/plugin-adr-common@0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-airbrake@0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/dev-utils@1.0.2-next.2 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/test-utils@1.1.0-next.2 + +## @backstage/plugin-airbrake-backend@0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + +## @backstage/plugin-allure@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-analytics-module-ga@0.1.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-api-docs@0.8.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog@1.2.0-next.2 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-app-backend@0.3.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/config-loader@1.1.1-next.1 + +## @backstage/plugin-auth-backend@0.13.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/catalog-client@1.0.2-next.0 + +## @backstage/plugin-auth-node@0.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + +## @backstage/plugin-azure-devops@0.1.21-next.2 + +### Patch Changes + +- ac14fcaf38: Added entity view for Azure Git Tags, based on existing Pull Requests view +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-azure-devops-common@0.2.3-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-azure-devops-backend@0.3.11-next.1 + +### Patch Changes + +- ac14fcaf38: Added entity view for Azure Git Tags, based on existing Pull Requests view +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-azure-devops-common@0.2.3-next.0 + +## @backstage/plugin-azure-devops-common@0.2.3-next.0 + +### Patch Changes + +- ac14fcaf38: Added entity view for Azure Git Tags, based on existing Pull Requests view + +## @backstage/plugin-badges@0.2.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-badges-backend@0.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/catalog-client@1.0.2-next.0 + +## @backstage/plugin-bazaar@0.1.20-next.2 + +### Patch Changes + +- 84c9e35a2f: Exported the SortView component from the Bazaar plugin for use directly +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog@1.2.0-next.2 + - @backstage/cli@0.17.1-next.2 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/catalog-client@1.0.2-next.0 + +## @backstage/plugin-bazaar-backend@0.1.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/backend-test-utils@0.1.24-next.1 + +## @backstage/plugin-bitrise@0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-catalog@1.2.0-next.2 + +### Patch Changes + +- 2bcb0a0e2b: Sidebar NAV now includes aria-label. Component AboutField now uses h2 variant instead of subtitle2 (font properties unchanged) +- 3a74e203a8: Updated search result components to support rendering content with highlighted matched terms +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-search-react@0.2.0-next.2 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/catalog-client@1.0.2-next.0 + - @backstage/plugin-catalog-common@1.0.2-next.0 + +## @backstage/plugin-catalog-backend@1.1.2-next.2 + +### Patch Changes + +- 16a40ac4c0: Fix wrong return type of the `isGroupEntity` function. +- 2909746147: Updated parseEntityTransformParams to handle keys with '.' in them. This will allow for querying of entities based off annotations such as 'backstage.io/orgin-location' or other entity field keys that have '.' in them. +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-scaffolder-common@1.1.0-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-permission-node@0.6.1-next.1 + - @backstage/catalog-client@1.0.2-next.0 + - @backstage/plugin-catalog-common@1.0.2-next.0 + +## @backstage/plugin-catalog-backend-module-aws@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-catalog-backend-module-azure@0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-catalog-backend-module-github@0.1.3-next.1 + +### Patch Changes + +- a7de43f648: `GitHubOrgEntityProvider.fromConfig` now supports a `schedule` option like other + entity providers, that makes it more convenient to leverage using the common + task scheduler. + + If you want to use this in your own project, it is used something like the following: + + ```ts + // In packages/backend/src/plugins/catalog.ts + builder.addEntityProvider( + GitHubOrgEntityProvider.fromConfig(env.config, { + id: 'production', + orgUrl: 'https://github.com/backstage', + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { cron: '*/30 * * * *' }, + timeout: { minutes: 10 }, + }), + logger: env.logger, + }), + ); + ``` + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-catalog-backend-module-ldap@0.4.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + +## @backstage/plugin-catalog-backend-module-msgraph@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + +## @backstage/plugin-catalog-common@1.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/search-common@0.3.4-next.0 + +## @backstage/plugin-catalog-graph@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/catalog-client@1.0.2-next.0 + +## @backstage/plugin-catalog-graphql@0.3.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + +## @backstage/plugin-catalog-import@0.8.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/catalog-client@1.0.2-next.0 + +## @backstage/plugin-catalog-react@1.1.0-next.2 + +### Patch Changes + +- 57f41fb8d6: Make Menu item on filters accessible through keyboard +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-permission-react@0.4.1-next.1 + - @backstage/catalog-client@1.0.2-next.0 + - @backstage/plugin-catalog-common@1.0.2-next.0 + +## @backstage/plugin-cicd-statistics@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-cicd-statistics@0.1.7-next.2 + +## @backstage/plugin-circleci@0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-cloudbuild@0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-code-climate@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-code-coverage@0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-code-coverage-backend@0.1.30-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/catalog-client@1.0.2-next.0 + +## @backstage/plugin-config-schema@0.1.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-cost-insights@0.11.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-explore@0.3.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-fossa@0.2.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-github-actions@0.5.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-github-deployments@0.1.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/integration-react@1.1.0-next.2 + +## @backstage/plugin-gocd@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-graphiql@0.2.37-next.1 + +### Patch Changes + +- e1f42a0e2c: Updated dependency `@types/codemirror` to `^5.0.0`. +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-graphql-backend@0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-graphql@0.3.9-next.0 + +## @backstage/plugin-home@0.4.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-stack-overflow@0.1.1-next.2 + +## @backstage/plugin-ilert@0.1.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-jenkins@0.7.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-jenkins-common@0.1.4-next.0 + +## @backstage/plugin-jenkins-backend@0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/catalog-client@1.0.2-next.0 + - @backstage/plugin-jenkins-common@0.1.4-next.0 + +## @backstage/plugin-jenkins-common@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-catalog-common@1.0.2-next.0 + +## @backstage/plugin-kafka@0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-kafka-backend@0.2.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + +## @backstage/plugin-kubernetes@0.6.5-next.2 + +### Patch Changes + +- 1ef98cfe48: add Azure Identity auth provider and AKS dashboard formatter +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-kubernetes-common@0.2.10-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-kubernetes-backend@0.5.1-next.1 + +### Patch Changes + +- 1ef98cfe48: add Azure Identity auth provider and AKS dashboard formatter +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-kubernetes-common@0.2.10-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + +## @backstage/plugin-kubernetes-common@0.2.10-next.0 + +### Patch Changes + +- 1ef98cfe48: add Azure Identity auth provider and AKS dashboard formatter +- Updated dependencies + - @backstage/catalog-model@1.0.2-next.0 + +## @backstage/plugin-lighthouse@0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-newrelic-dashboard@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-org@0.5.5-next.2 + +### Patch Changes + +- dfee1002d7: Fixed overflow bug of name and email on EntitiyMembersListCard component which can occur on specific 'screen width' + ’character length' combinations +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-pagerduty@0.3.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-periskop@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-periskop-backend@0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + +## @backstage/plugin-permission-backend@0.5.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-permission-node@0.6.1-next.1 + +## @backstage/plugin-permission-common@0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + +## @backstage/plugin-permission-node@0.6.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + +## @backstage/plugin-permission-react@0.4.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + +## @backstage/plugin-proxy-backend@0.2.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + +## @backstage/plugin-rollbar@0.4.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-rollbar-backend@0.1.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + +## @backstage/plugin-scaffolder@1.2.0-next.2 + +### Patch Changes + +- 70817dafc0: Updated dependency `use-immer` to `^0.7.0`. +- 1af133f779: Updated dependency `event-source-polyfill` to `1.0.26`. +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-scaffolder-common@1.1.0-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/plugin-permission-react@0.4.1-next.1 + - @backstage/catalog-client@1.0.2-next.0 + - @backstage/plugin-catalog-common@1.0.2-next.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-scaffolder-backend@1.2.0-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.2.0-next.1 + - @backstage/config@1.0.1-next.0 + +## @backstage/plugin-search@0.8.1-next.2 + +### Patch Changes + +- 3a74e203a8: Updated search result components to support rendering content with highlighted matched terms +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-react@0.2.0-next.2 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-search-backend@0.5.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-backend-node@0.6.1-next.1 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-permission-node@0.6.1-next.1 + +## @backstage/plugin-search-backend-module-elasticsearch@0.1.4-next.1 + +### Patch Changes + +- 71d3432710: Search Engines will now index documents in batches of 1000 instead of 100 (under the hood). This may result in your Backstage backend consuming slightly more memory during index runs, but should dramatically improve indexing performance for large document sets. +- 3a74e203a8: Support generating highlighted matched terms in search result data +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-backend-node@0.6.1-next.1 + - @backstage/plugin-search-common@0.3.4-next.0 + +## @backstage/plugin-search-backend-module-pg@0.3.3-next.1 + +### Patch Changes + +- 71d3432710: Search Engines will now index documents in batches of 1000 instead of 100 (under the hood). This may result in your Backstage backend consuming slightly more memory during index runs, but should dramatically improve indexing performance for large document sets. +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-search-backend-node@0.6.1-next.1 + - @backstage/plugin-search-common@0.3.4-next.0 + +## @backstage/plugin-search-backend-node@0.6.1-next.1 + +### Patch Changes + +- 71d3432710: Search Engines will now index documents in batches of 1000 instead of 100 (under the hood). This may result in your Backstage backend consuming slightly more memory during index runs, but should dramatically improve indexing performance for large document sets. +- 3a74e203a8: Support generating highlighted matched terms in search result data +- Updated dependencies + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/plugin-search-common@0.3.4-next.0 + +## @backstage/plugin-search-common@0.3.4-next.0 + +### Patch Changes + +- 3a74e203a8: Support generating highlighted matched terms in search result data +- Updated dependencies + - @backstage/plugin-permission-common@0.6.1-next.0 + +## @backstage/plugin-search-react@0.2.0-next.2 + +### Patch Changes + +- 3a74e203a8: Updated search result components to support rendering content with highlighted matched terms +- Updated dependencies + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-sentry@0.3.43-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-sonarqube@0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-splunk-on-call@0.3.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-stack-overflow@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-home@0.4.21-next.2 + +## @backstage/plugin-stack-overflow-backend@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + +## @backstage/plugin-tech-insights@0.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-tech-insights-backend@0.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/plugin-tech-insights-node@0.3.0-next.2 + - @backstage/catalog-client@1.0.2-next.0 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-tech-insights-node@0.3.0-next.2 + +## @backstage/plugin-tech-insights-node@0.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + +## @backstage/plugin-techdocs@1.1.1-next.2 + +### Patch Changes + +- 52419be116: Create a menu in the sub header of documentation pages, it is responsible for rendering TechDocs addons that allow users to customize their reading experience. +- 1af133f779: Updated dependency `event-source-polyfill` to `1.0.26`. +- 2dcb2c9678: Loading SVGs correctly with `bota` with extended characters +- 3a74e203a8: Updated search result components to support rendering content with highlighted matched terms +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-techdocs-react@0.1.1-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-react@0.2.0-next.2 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/integration-react@1.1.0-next.2 + +## @backstage/plugin-techdocs-addons-test-utils@0.1.0-next.1 + +### Patch Changes + +- f84e0e2818: Fixed a bug preventing testing of TechDocs Addons whose dom contained `` tags. +- 7c398c6473: The `TechDocsAddonTester` class may now be extended if custom test configuration is needed. +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-techdocs@1.1.1-next.2 + - @backstage/plugin-techdocs-react@0.1.1-next.2 + - @backstage/plugin-catalog@1.2.0-next.2 + - @backstage/plugin-search-react@0.2.0-next.2 + - @backstage/core-app-api@1.0.2-next.1 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/test-utils@1.1.0-next.2 + +## @backstage/plugin-techdocs-backend@1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-techdocs-node@1.1.1-next.1 + - @backstage/catalog-client@1.0.2-next.0 + - @backstage/plugin-catalog-common@1.0.2-next.0 + +## @backstage/plugin-techdocs-module-addons-contrib@0.1.0-next.2 + +### Patch Changes + +- 52419be116: Create a TechDocs `` addon that allows users to set a font size in the browser's local storage for the text of documentation pages. + + Here's an example on how to use it in a Backstage app: + + ```diff + import { + DefaultTechDocsHome, + TechDocsIndexPage, + TechDocsReaderPage, + } from '@backstage/plugin-techdocs'; + import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; + +import { TextSize } from '@backstage/plugin-techdocs-module-addons-contrib'; + + const AppRoutes = () => { + + // other plugin routes + }> + + + } + > + + + + + + ; + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-techdocs-react@0.1.1-next.2 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/integration-react@1.1.0-next.2 + +## @backstage/plugin-techdocs-node@1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + +## @backstage/plugin-techdocs-react@0.1.1-next.2 + +### Patch Changes + +- 52419be116: Create a new addon location called "Settings", it is designed for addons that allow users to customize the reading experience in documentation pages. + + Usage example: + + ```tsx + const TextSize = techdocsModuleAddonsContribPlugin.provide( + createTechDocsAddonExtension({ + name: 'TextSize', + location: TechDocsAddonLocations.Settings, + component: TextSizeAddon, + }), + ); + ``` + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-todo@0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + +## @backstage/plugin-todo-backend@0.1.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/catalog-client@1.0.2-next.0 + +## example-app@0.2.71-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-kubernetes@0.6.5-next.2 + - @backstage/plugin-org@0.5.5-next.2 + - @backstage/plugin-techdocs@1.1.1-next.2 + - @backstage/plugin-techdocs-react@0.1.1-next.2 + - @backstage/plugin-scaffolder@1.2.0-next.2 + - @backstage/plugin-graphiql@0.2.37-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog@1.2.0-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@0.1.0-next.2 + - @backstage/cli@0.17.1-next.2 + - @backstage/plugin-search@0.8.1-next.2 + - @backstage/plugin-search-react@0.2.0-next.2 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/plugin-azure-devops@0.1.21-next.2 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-app-api@1.0.2-next.1 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/plugin-catalog-import@0.8.8-next.2 + - @backstage/plugin-code-coverage@0.1.32-next.2 + - @backstage/plugin-cost-insights@0.11.27-next.1 + - @backstage/plugin-home@0.4.21-next.2 + - @backstage/plugin-lighthouse@0.3.5-next.2 + - @backstage/plugin-permission-react@0.4.1-next.1 + - @backstage/plugin-stack-overflow@0.1.1-next.2 + - @backstage/plugin-airbrake@0.3.5-next.2 + - @backstage/plugin-api-docs@0.8.5-next.2 + - @backstage/plugin-badges@0.2.29-next.2 + - @backstage/plugin-catalog-graph@0.2.17-next.2 + - @backstage/plugin-circleci@0.3.5-next.2 + - @backstage/plugin-cloudbuild@0.3.5-next.2 + - @backstage/plugin-explore@0.3.36-next.2 + - @backstage/plugin-github-actions@0.5.5-next.2 + - @backstage/plugin-gocd@0.1.11-next.2 + - @backstage/plugin-jenkins@0.7.4-next.2 + - @backstage/plugin-kafka@0.3.5-next.2 + - @backstage/plugin-newrelic-dashboard@0.1.13-next.2 + - @backstage/plugin-pagerduty@0.3.32-next.2 + - @backstage/plugin-rollbar@0.4.5-next.2 + - @backstage/plugin-sentry@0.3.43-next.2 + - @backstage/plugin-tech-insights@0.2.1-next.2 + - @backstage/plugin-todo@0.2.7-next.2 + - @backstage/plugin-catalog-common@1.0.2-next.0 + +## example-backend@0.2.71-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-kubernetes-backend@0.5.1-next.1 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.0-next.1 + - @backstage/plugin-scaffolder-backend@1.2.0-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-backend-node@0.6.1-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@0.1.4-next.1 + - @backstage/plugin-search-backend-module-pg@0.3.3-next.1 + - @backstage/plugin-azure-devops-backend@0.3.11-next.1 + - example-app@0.2.71-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/plugin-app-backend@0.3.32-next.1 + - @backstage/plugin-auth-backend@0.13.1-next.2 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-badges-backend@0.1.26-next.1 + - @backstage/plugin-code-coverage-backend@0.1.30-next.1 + - @backstage/plugin-graphql-backend@0.1.22-next.1 + - @backstage/plugin-jenkins-backend@0.1.22-next.1 + - @backstage/plugin-kafka-backend@0.2.25-next.1 + - @backstage/plugin-permission-backend@0.5.7-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-permission-node@0.6.1-next.1 + - @backstage/plugin-proxy-backend@0.2.26-next.1 + - @backstage/plugin-rollbar-backend@0.1.29-next.2 + - @backstage/plugin-search-backend@0.5.2-next.1 + - @backstage/plugin-tech-insights-backend@0.4.0-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.16-next.2 + - @backstage/plugin-tech-insights-node@0.3.0-next.2 + - @backstage/plugin-techdocs-backend@1.1.1-next.1 + - @backstage/plugin-todo-backend@0.1.29-next.1 + - @backstage/catalog-client@1.0.2-next.0 + +## techdocs-cli-embedded-app@0.2.70-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-techdocs@1.1.1-next.2 + - @backstage/plugin-techdocs-react@0.1.1-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog@1.2.0-next.2 + - @backstage/cli@0.17.1-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-app-api@1.0.2-next.1 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/test-utils@1.1.0-next.2 + +## @internal/plugin-todo-list-backend@1.0.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + +## @internal/plugin-todo-list-common@1.0.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.1-next.0 diff --git a/docs/releases/v1.2.0-next.3-changelog.md b/docs/releases/v1.2.0-next.3-changelog.md new file mode 100644 index 0000000000..4efce476d4 --- /dev/null +++ b/docs/releases/v1.2.0-next.3-changelog.md @@ -0,0 +1,73 @@ +# Release v1.2.0-next.3 + +## @backstage/core-components@0.9.4-next.2 + +### Patch Changes + +- 52c02ac02b: Don't set the background color on an Avatar component that has a picture. +- 3603014e0e: Add ARIA landmark(
), & label and a heading to OAuthRequestDialog. Removed nested interactive control (button). +- 2025d7c123: Properly highlight `SidebarSubmenuItem` dropdown items on hover, use ellipsis styling on long labels in `SidebarSubmenu`, allow `icon` and `to` properties to be optional on `SidebarSubmenuItem`, and fix `SidebarPage` padding to be responsive to pinned state + +## @backstage/plugin-home@0.4.21-next.3 + +### Patch Changes + +- 69093c5f91: Display entity titles in `StarredEntities` home page card (if defined) and don't show entities which no longer exist +- Updated dependencies + - @backstage/core-components@0.9.4-next.2 + +## @backstage/plugin-kubernetes@0.6.5-next.3 + +### Patch Changes + +- 447e060872: Add support for 'oidc' as authProvider for kubernetes authentication + and adds optional 'oidcTokenProvider' config value. This will allow + users to authenticate to kubernetes cluster using id tokens obtained + from the configured auth provider in their backstage instance. +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.2.10-next.1 + - @backstage/core-components@0.9.4-next.2 + +## @backstage/plugin-kubernetes-backend@0.5.1-next.2 + +### Patch Changes + +- 447e060872: Add support for 'oidc' as authProvider for kubernetes authentication + and adds optional 'oidcTokenProvider' config value. This will allow + users to authenticate to kubernetes cluster using id tokens obtained + from the configured auth provider in their backstage instance. +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.2.10-next.1 + +## @backstage/plugin-kubernetes-common@0.2.10-next.1 + +### Patch Changes + +- 447e060872: Add support for 'oidc' as authProvider for kubernetes authentication + and adds optional 'oidcTokenProvider' config value. This will allow + users to authenticate to kubernetes cluster using id tokens obtained + from the configured auth provider in their backstage instance. + +## @backstage/plugin-org@0.5.5-next.3 + +### Patch Changes + +- 2025d7c123: Include namespace in `MyGroupSidebarItem` if not default and remove root item routing if there are multiple groups +- Updated dependencies + - @backstage/core-components@0.9.4-next.2 + +## @backstage/plugin-scaffolder@1.2.0-next.3 + +### Patch Changes + +- cc8ddd0979: revert dependency `event-source-polyfill` to `1.0.25` +- Updated dependencies + - @backstage/core-components@0.9.4-next.2 + +## @backstage/plugin-techdocs@1.1.1-next.3 + +### Patch Changes + +- cc8ddd0979: revert dependency `event-source-polyfill` to `1.0.25` +- Updated dependencies + - @backstage/core-components@0.9.4-next.2 diff --git a/microsite/data/plugins/cloud-carbon-footprint.yaml b/microsite/data/plugins/cloud-carbon-footprint.yaml index 7e73ad6adb..5a50d02fe3 100644 --- a/microsite/data/plugins/cloud-carbon-footprint.yaml +++ b/microsite/data/plugins/cloud-carbon-footprint.yaml @@ -1,7 +1,7 @@ --- title: Cloud Carbon Footprint author: Thoughtworks -authorUrl: https://github.com/cloud-carbon-footprint +authorUrl: https://www.cloudcarbonfootprint.org/ category: Metrics description: View your cloud carbon footprint by estimating energy use (kilowatt-hours) and carbon emissions (metric tons CO2e) from public cloud usage. documentation: https://github.com/cloud-carbon-footprint/ccf-backstage-plugin/blob/trunk/README.md diff --git a/microsite/data/plugins/codescene.yaml b/microsite/data/plugins/codescene.yaml new file mode 100644 index 0000000000..4a7c224cf1 --- /dev/null +++ b/microsite/data/plugins/codescene.yaml @@ -0,0 +1,9 @@ +--- +title: CodeScene +author: CodeScene +authorUrl: https://codescene.com/ +category: Quality +description: CodeScene is a multi-purpose tool bridging code, business and people. See hidden risks and social patterns in your code. Prioritize and reduce technical debt. +documentation: https://github.com/backstage/backstage/tree/master/plugins/codescene +iconUrl: img/codescene_logo.svg +npmPackageName: '@backstage/plugin-codescene' diff --git a/microsite/static/img/codescene_logo.svg b/microsite/static/img/codescene_logo.svg new file mode 100644 index 0000000000..9e433b2c7b --- /dev/null +++ b/microsite/static/img/codescene_logo.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + diff --git a/package.json b/package.json index b586e0b8ba..c215ef69a4 100644 --- a/package.json +++ b/package.json @@ -45,11 +45,11 @@ ] }, "resolutions": { - "**/@graphql-codegen/cli/**/ws": "^7.4.6", + "**/@graphql-codegen/cli/**/ws": "^8.0.0", "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.2.0-next.1", + "version": "1.2.0-next.3", "dependencies": { "@manypkg/get-packages": "^1.1.3", "@microsoft/api-documenter": "^7.17.11", @@ -68,7 +68,7 @@ "concurrently": "^7.0.0", "eslint-plugin-notice": "^0.9.10", "fs-extra": "10.1.0", - "husky": "^7.0.4", + "husky": "^8.0.0", "lerna": "^4.0.0", "lint-staged": "^12.2.0", "minimist": "^1.2.5", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 8ea789e99a..7f29042ceb 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,56 @@ # example-app +## 0.2.71-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-kubernetes@0.6.5-next.2 + - @backstage/plugin-org@0.5.5-next.2 + - @backstage/plugin-techdocs@1.1.1-next.2 + - @backstage/plugin-techdocs-react@0.1.1-next.2 + - @backstage/plugin-scaffolder@1.2.0-next.2 + - @backstage/plugin-graphiql@0.2.37-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog@1.2.0-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@0.1.0-next.2 + - @backstage/cli@0.17.1-next.2 + - @backstage/plugin-search@0.8.1-next.2 + - @backstage/plugin-search-react@0.2.0-next.2 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/plugin-azure-devops@0.1.21-next.2 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-app-api@1.0.2-next.1 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/plugin-catalog-import@0.8.8-next.2 + - @backstage/plugin-code-coverage@0.1.32-next.2 + - @backstage/plugin-cost-insights@0.11.27-next.1 + - @backstage/plugin-home@0.4.21-next.2 + - @backstage/plugin-lighthouse@0.3.5-next.2 + - @backstage/plugin-permission-react@0.4.1-next.1 + - @backstage/plugin-stack-overflow@0.1.1-next.2 + - @backstage/plugin-airbrake@0.3.5-next.2 + - @backstage/plugin-api-docs@0.8.5-next.2 + - @backstage/plugin-badges@0.2.29-next.2 + - @backstage/plugin-catalog-graph@0.2.17-next.2 + - @backstage/plugin-circleci@0.3.5-next.2 + - @backstage/plugin-cloudbuild@0.3.5-next.2 + - @backstage/plugin-explore@0.3.36-next.2 + - @backstage/plugin-github-actions@0.5.5-next.2 + - @backstage/plugin-gocd@0.1.11-next.2 + - @backstage/plugin-jenkins@0.7.4-next.2 + - @backstage/plugin-kafka@0.3.5-next.2 + - @backstage/plugin-newrelic-dashboard@0.1.13-next.2 + - @backstage/plugin-pagerduty@0.3.32-next.2 + - @backstage/plugin-rollbar@0.4.5-next.2 + - @backstage/plugin-sentry@0.3.43-next.2 + - @backstage/plugin-tech-insights@0.2.1-next.2 + - @backstage/plugin-todo@0.2.7-next.2 + - @backstage/plugin-catalog-common@1.0.2-next.0 + ## 0.2.71-next.1 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 4c219916d8..8f42ee2654 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.71-next.1", + "version": "0.2.71-next.2", "private": true, "backstage": { "role": "frontend" @@ -8,58 +8,58 @@ "bundled": true, "dependencies": { "@backstage/app-defaults": "^1.0.2-next.0", - "@backstage/catalog-model": "^1.0.1", - "@backstage/cli": "^0.17.1-next.1", - "@backstage/config": "^1.0.0", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/integration-react": "^1.1.0-next.1", - "@backstage/plugin-airbrake": "^0.3.5-next.1", - "@backstage/plugin-api-docs": "^0.8.5-next.1", - "@backstage/plugin-azure-devops": "^0.1.21-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/core-components": "^0.9.4-next.1", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/integration-react": "^1.1.0-next.2", + "@backstage/plugin-airbrake": "^0.3.5-next.2", + "@backstage/plugin-api-docs": "^0.8.5-next.2", + "@backstage/plugin-azure-devops": "^0.1.21-next.2", "@backstage/plugin-apache-airflow": "^0.1.13-next.0", - "@backstage/plugin-badges": "^0.2.29-next.1", - "@backstage/plugin-catalog": "^1.2.0-next.1", - "@backstage/plugin-catalog-common": "^1.0.1", - "@backstage/plugin-catalog-graph": "^0.2.17-next.1", - "@backstage/plugin-catalog-import": "^0.8.8-next.1", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", - "@backstage/plugin-circleci": "^0.3.5-next.1", - "@backstage/plugin-cloudbuild": "^0.3.5-next.1", - "@backstage/plugin-code-coverage": "^0.1.32-next.1", - "@backstage/plugin-cost-insights": "^0.11.27-next.0", - "@backstage/plugin-explore": "^0.3.36-next.1", + "@backstage/plugin-badges": "^0.2.29-next.2", + "@backstage/plugin-catalog": "^1.2.0-next.2", + "@backstage/plugin-catalog-common": "^1.0.2-next.0", + "@backstage/plugin-catalog-graph": "^0.2.17-next.2", + "@backstage/plugin-catalog-import": "^0.8.8-next.2", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", + "@backstage/plugin-circleci": "^0.3.5-next.2", + "@backstage/plugin-cloudbuild": "^0.3.5-next.2", + "@backstage/plugin-code-coverage": "^0.1.32-next.2", + "@backstage/plugin-cost-insights": "^0.11.27-next.1", + "@backstage/plugin-explore": "^0.3.36-next.2", "@backstage/plugin-gcalendar": "^0.3.1-next.1", "@backstage/plugin-gcp-projects": "^0.3.24-next.0", - "@backstage/plugin-github-actions": "^0.5.5-next.1", - "@backstage/plugin-gocd": "^0.1.11-next.1", - "@backstage/plugin-graphiql": "^0.2.37-next.0", - "@backstage/plugin-home": "^0.4.21-next.1", - "@backstage/plugin-jenkins": "^0.7.4-next.1", - "@backstage/plugin-kafka": "^0.3.5-next.1", - "@backstage/plugin-kubernetes": "^0.6.5-next.1", - "@backstage/plugin-lighthouse": "^0.3.5-next.1", + "@backstage/plugin-github-actions": "^0.5.5-next.2", + "@backstage/plugin-gocd": "^0.1.11-next.2", + "@backstage/plugin-graphiql": "^0.2.37-next.1", + "@backstage/plugin-home": "^0.4.21-next.2", + "@backstage/plugin-jenkins": "^0.7.4-next.2", + "@backstage/plugin-kafka": "^0.3.5-next.2", + "@backstage/plugin-kubernetes": "^0.6.5-next.2", + "@backstage/plugin-lighthouse": "^0.3.5-next.2", "@backstage/plugin-newrelic": "^0.3.23-next.0", - "@backstage/plugin-newrelic-dashboard": "^0.1.13-next.1", - "@backstage/plugin-org": "^0.5.5-next.1", - "@backstage/plugin-pagerduty": "0.3.32-next.1", - "@backstage/plugin-permission-react": "^0.4.1-next.0", - "@backstage/plugin-rollbar": "^0.4.5-next.1", - "@backstage/plugin-scaffolder": "^1.2.0-next.1", - "@backstage/plugin-search": "^0.8.1-next.1", - "@backstage/plugin-search-react": "^0.2.0-next.1", - "@backstage/plugin-search-common": "^0.3.3", - "@backstage/plugin-sentry": "^0.3.43-next.1", + "@backstage/plugin-newrelic-dashboard": "^0.1.13-next.2", + "@backstage/plugin-org": "^0.5.5-next.2", + "@backstage/plugin-pagerduty": "0.3.32-next.2", + "@backstage/plugin-permission-react": "^0.4.1-next.1", + "@backstage/plugin-rollbar": "^0.4.5-next.2", + "@backstage/plugin-scaffolder": "^1.2.0-next.2", + "@backstage/plugin-search": "^0.8.1-next.2", + "@backstage/plugin-search-react": "^0.2.0-next.2", + "@backstage/plugin-search-common": "^0.3.4-next.0", + "@backstage/plugin-sentry": "^0.3.43-next.2", "@backstage/plugin-shortcuts": "^0.2.6-next.0", - "@backstage/plugin-stack-overflow": "^0.1.1-next.1", + "@backstage/plugin-stack-overflow": "^0.1.1-next.2", "@backstage/plugin-tech-radar": "^0.5.12-next.0", - "@backstage/plugin-techdocs": "^1.1.1-next.1", - "@backstage/plugin-techdocs-react": "^0.1.1-next.1", - "@backstage/plugin-techdocs-module-addons-contrib": "^0.1.0-next.1", - "@backstage/plugin-todo": "^0.2.7-next.1", + "@backstage/plugin-techdocs": "^1.1.1-next.2", + "@backstage/plugin-techdocs-react": "^0.1.1-next.2", + "@backstage/plugin-techdocs-module-addons-contrib": "^0.1.0-next.2", + "@backstage/plugin-todo": "^0.2.7-next.2", "@backstage/plugin-user-settings": "^0.4.4-next.0", - "@backstage/plugin-tech-insights": "^0.2.1-next.1", + "@backstage/plugin-tech-insights": "^0.2.1-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -80,7 +80,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/test-utils": "^1.1.0-next.2", "@rjsf/core": "^3.2.1", "@testing-library/cypress": "^8.0.2", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 4cf2c02e55..089900fb77 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -70,7 +70,10 @@ import { techdocsPlugin, } from '@backstage/plugin-techdocs'; import { TechDocsAddons } from '@backstage/plugin-techdocs-react'; -import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib'; +import { + ReportIssue, + TextSize, +} from '@backstage/plugin-techdocs-module-addons-contrib'; import { UserSettingsPage, UserSettingsTab, @@ -183,6 +186,7 @@ const routes = ( {techDocsPage} + + + + + {pullRequestsContent} diff --git a/packages/app/src/components/search/SearchModal.tsx b/packages/app/src/components/search/SearchModal.tsx index f75017a4dd..3fdacf08b6 100644 --- a/packages/app/src/components/search/SearchModal.tsx +++ b/packages/app/src/components/search/SearchModal.tsx @@ -180,7 +180,7 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { {({ results }) => ( - {results.map(({ type, document }) => { + {results.map(({ type, document, highlight }) => { let resultItem; switch (type) { case 'software-catalog': @@ -188,6 +188,7 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { ); break; @@ -196,6 +197,7 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { ); break; @@ -204,6 +206,7 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { ); } diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx index fd9c80686c..d1b56bbaf0 100644 --- a/packages/app/src/components/search/SearchPage.tsx +++ b/packages/app/src/components/search/SearchPage.tsx @@ -132,13 +132,14 @@ const SearchPage = () => { {({ results }) => ( - {results.map(({ type, document }) => { + {results.map(({ type, document, highlight }) => { switch (type) { case 'software-catalog': return ( ); case 'techdocs': @@ -146,6 +147,7 @@ const SearchPage = () => { ); default: @@ -153,6 +155,7 @@ const SearchPage = () => { ); } diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index b67b7a3ce8..a00e094578 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/backend-common +## 0.13.3-next.2 + +### Patch Changes + +- e0a6360b80: Added a `stream()` method to complement the `buffer()` method on `ReadUrlResponse`. A `ReadUrlResponseFactory` utility class is now also available, providing a simple, consistent way to provide a valid `ReadUrlResponse`. + + This method, though optional for now, will be required on the responses of `UrlReader.readUrl()` implementations in a future release. + +- 4b811aafce: Implemented the `UrlReader.search()` method for Google Cloud Storage. Due to limitations in the underlying storage API, only prefix-based searches are supported right now (for example, `https://storage.cloud.google.com/your-bucket/some-path/*`). +- Updated dependencies + - @backstage/cli-common@0.1.9-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/config-loader@1.1.1-next.1 + - @backstage/integration@1.2.0-next.1 + ## 0.13.3-next.1 ### Patch Changes diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 961973b144..6059e68792 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -547,6 +547,24 @@ export type ReadUrlOptions = { // @public export type ReadUrlResponse = { buffer(): Promise; + stream?(): Readable; + etag?: string; +}; + +// @public +export class ReadUrlResponseFactory { + static fromNodeJSReadable( + oldStyleStream: NodeJS.ReadableStream, + options?: ReadUrlResponseFactoryFromStreamOptions, + ): Promise; + static fromReadable( + stream: Readable, + options?: ReadUrlResponseFactoryFromStreamOptions, + ): Promise; +} + +// @public +export type ReadUrlResponseFactoryFromStreamOptions = { etag?: string; }; @@ -599,18 +617,20 @@ export class ServerTokenManager implements TokenManager { // (undocumented) static fromConfig( config: Config, - options: { - logger: Logger; - }, + options: ServerTokenManagerOptions, ): ServerTokenManager; // (undocumented) getToken(): Promise<{ token: string; }>; - // (undocumented) static noop(): TokenManager; } +// @public +export interface ServerTokenManagerOptions { + logger: Logger; +} + // @public export type ServiceBuilder = { loadConfig(config: Config): ServiceBuilder; @@ -669,10 +689,8 @@ export interface StatusCheckHandlerOptions { // @public export interface TokenManager { - // (undocumented) - authenticate: (token: string) => Promise; - // (undocumented) - getToken: () => Promise<{ + authenticate(token: string): Promise; + getToken(): Promise<{ token: string; }>; } diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index a2913c7501..931ba4faec 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.13.3-next.1", + "version": "0.13.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -34,11 +34,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/cli-common": "^0.1.8", - "@backstage/config": "^1.0.0", - "@backstage/config-loader": "^1.1.1-next.0", + "@backstage/cli-common": "^0.1.9-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/config-loader": "^1.1.1-next.1", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", + "@backstage/integration": "^1.2.0-next.1", "@backstage/types": "^1.0.0", "@google-cloud/storage": "^5.8.0", "@manypkg/get-packages": "^1.1.3", @@ -50,6 +50,7 @@ "@types/webpack-env": "^1.15.2", "archiver": "^5.0.2", "aws-sdk": "^2.840.0", + "base64-stream": "^1.0.0", "compression": "^1.7.4", "concat-stream": "^2.0.0", "cors": "^2.8.5", @@ -90,9 +91,10 @@ } }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.24-next.0", - "@backstage/cli": "^0.17.1-next.1", + "@backstage/backend-test-utils": "^0.1.24-next.1", + "@backstage/cli": "^0.17.1-next.2", "@types/archiver": "^5.1.0", + "@types/base64-stream": "^1.0.2", "@types/compression": "^1.7.0", "@types/concat-stream": "^2.0.0", "@types/fs-extra": "^9.0.3", diff --git a/packages/backend-common/src/reading/AwsS3UrlReader.test.ts b/packages/backend-common/src/reading/AwsS3UrlReader.test.ts index 01fd27f45a..ea969b43a9 100644 --- a/packages/backend-common/src/reading/AwsS3UrlReader.test.ts +++ b/packages/backend-common/src/reading/AwsS3UrlReader.test.ts @@ -28,6 +28,7 @@ import AWSMock from 'aws-sdk-mock'; import aws from 'aws-sdk'; import path from 'path'; import { NotModifiedError } from '@backstage/errors'; +import getRawBody from 'raw-body'; const treeResponseFactory = DefaultReadTreeResponseFactory.create({ config: new ConfigReader({}), @@ -263,7 +264,7 @@ describe('AwsS3UrlReader', () => { describe('readUrl', () => { let awsS3UrlReader: AwsS3UrlReader; - beforeAll(() => { + beforeEach(() => { AWSMock.setSDKInstance(aws); AWSMock.mock( @@ -295,7 +296,7 @@ describe('AwsS3UrlReader', () => { ); }); - it('returns contents of an object in a bucket', async () => { + it('returns contents of an object in a bucket via buffer', async () => { const response = await awsS3UrlReader.readUrl( 'https://test-bucket.s3.us-east-2.amazonaws.com/awsS3-mock-object.yaml', ); @@ -303,6 +304,14 @@ describe('AwsS3UrlReader', () => { expect(buffer.toString().trim()).toBe('site_name: Test'); }); + it('returns contents of an object in a bucket via stream', async () => { + const response = await awsS3UrlReader.readUrl( + 'https://test-bucket.s3.us-east-2.amazonaws.com/awsS3-mock-object.yaml', + ); + const fromStream = await getRawBody(response.stream!()); + expect(fromStream.toString().trim()).toBe('site_name: Test'); + }); + it('rejects unknown targets', async () => { await expect( awsS3UrlReader.readUrl( diff --git a/packages/backend-common/src/reading/AwsS3UrlReader.ts b/packages/backend-common/src/reading/AwsS3UrlReader.ts index 4dd68bf32c..dbd2c66a62 100644 --- a/packages/backend-common/src/reading/AwsS3UrlReader.ts +++ b/packages/backend-common/src/reading/AwsS3UrlReader.ts @@ -26,7 +26,6 @@ import { SearchResponse, UrlReader, } from './types'; -import getRawBody from 'raw-body'; import { AwsS3Integration, ScmIntegrations, @@ -34,6 +33,7 @@ import { } from '@backstage/integration'; import { ForwardedError, NotModifiedError } from '@backstage/errors'; import { ListObjectsV2Output, ObjectList } from 'aws-sdk/clients/s3'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; /** * Path style URLs: https://s3.(region).amazonaws.com/(bucket)/(key) @@ -214,13 +214,11 @@ export class AwsS3UrlReader implements UrlReader { const request = this.deps.s3.getObject(params); options?.signal?.addEventListener('abort', () => request.abort()); - const buffer = await getRawBody(request.createReadStream()); const etag = (await request.promise()).ETag; - return { - buffer: async () => buffer, - etag: etag, - }; + return ReadUrlResponseFactory.fromReadable(request.createReadStream(), { + etag, + }); } catch (e) { if (e.statusCode === 304) { throw new NotModifiedError(); diff --git a/packages/backend-common/src/reading/AzureUrlReader.ts b/packages/backend-common/src/reading/AzureUrlReader.ts index d6ceaec258..140496c181 100644 --- a/packages/backend-common/src/reading/AzureUrlReader.ts +++ b/packages/backend-common/src/reading/AzureUrlReader.ts @@ -37,6 +37,7 @@ import { ReadUrlOptions, ReadUrlResponse, } from './types'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; /** * Implements a {@link UrlReader} for Azure repos. @@ -90,9 +91,7 @@ export class AzureUrlReader implements UrlReader { // for private repos when PAT is not valid, Azure API returns a http status code 203 with sign in page html if (response.ok && response.status !== 203) { - return { - buffer: async () => Buffer.from(await response.arrayBuffer()), - }; + return ReadUrlResponseFactory.fromNodeJSReadable(response.body); } const message = `${url} could not be read as ${builtUrl}, ${response.status} ${response.statusText}`; diff --git a/packages/backend-common/src/reading/BitbucketCloudUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketCloudUrlReader.test.ts index 38841d75ad..12ace2755b 100644 --- a/packages/backend-common/src/reading/BitbucketCloudUrlReader.test.ts +++ b/packages/backend-common/src/reading/BitbucketCloudUrlReader.test.ts @@ -29,6 +29,7 @@ import path from 'path'; import { NotModifiedError } from '@backstage/errors'; import { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader'; import { DefaultReadTreeResponseFactory } from './tree'; +import getRawBody from 'raw-body'; const treeResponseFactory = DefaultReadTreeResponseFactory.create({ config: new ConfigReader({}), @@ -65,7 +66,7 @@ describe('BitbucketCloudUrlReader', () => { setupRequestMockHandlers(worker); describe('readUrl', () => { - it('should be able to readUrl without ETag', async () => { + it('should be able to readUrl via buffer without ETag', async () => { worker.use( rest.get( 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', @@ -87,6 +88,28 @@ describe('BitbucketCloudUrlReader', () => { expect(buffer.toString()).toBe('foo'); }); + it('should be able to readUrl via stream without ETag', async () => { + worker.use( + rest.get( + 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', + (req, res, ctx) => { + expect(req.headers.get('If-None-Match')).toBeNull(); + return res( + ctx.status(200), + ctx.body('foo'), + ctx.set('ETag', 'etag-value'), + ); + }, + ), + ); + + const result = await reader.readUrl( + 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', + ); + const fromStream = await getRawBody(result.stream!()); + expect(fromStream.toString()).toBe('foo'); + }); + it('should be able to readUrl with matching ETag', async () => { worker.use( rest.get( diff --git a/packages/backend-common/src/reading/BitbucketCloudUrlReader.ts b/packages/backend-common/src/reading/BitbucketCloudUrlReader.ts index 6a9406e920..7bc4cd9c11 100644 --- a/packages/backend-common/src/reading/BitbucketCloudUrlReader.ts +++ b/packages/backend-common/src/reading/BitbucketCloudUrlReader.ts @@ -39,6 +39,7 @@ import { SearchResponse, UrlReader, } from './types'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; /** * Implements a {@link UrlReader} for files from Bitbucket Cloud. @@ -112,10 +113,9 @@ export class BitbucketCloudUrlReader implements UrlReader { } if (response.ok) { - return { - buffer: async () => Buffer.from(await response.arrayBuffer()), + return ReadUrlResponseFactory.fromNodeJSReadable(response.body, { etag: response.headers.get('ETag') ?? undefined, - }; + }); } const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`; diff --git a/packages/backend-common/src/reading/BitbucketServerUrlReader.ts b/packages/backend-common/src/reading/BitbucketServerUrlReader.ts index 320b8f2719..b4e1e62327 100644 --- a/packages/backend-common/src/reading/BitbucketServerUrlReader.ts +++ b/packages/backend-common/src/reading/BitbucketServerUrlReader.ts @@ -38,6 +38,7 @@ import { SearchResponse, UrlReader, } from './types'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; /** * Implements a {@link UrlReader} for files from Bitbucket Server APIs. @@ -103,10 +104,9 @@ export class BitbucketServerUrlReader implements UrlReader { } if (response.ok) { - return { - buffer: async () => Buffer.from(await response.arrayBuffer()), + return ReadUrlResponseFactory.fromNodeJSReadable(response.body, { etag: response.headers.get('ETag') ?? undefined, - }; + }); } const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`; diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts index 3a2360debb..922480f8e7 100644 --- a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts +++ b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts @@ -30,6 +30,7 @@ import { NotModifiedError } from '@backstage/errors'; import { BitbucketUrlReader } from './BitbucketUrlReader'; import { DefaultReadTreeResponseFactory } from './tree'; import { getVoidLogger } from '../logging'; +import getRawBody from 'raw-body'; const logger = getVoidLogger(); @@ -113,7 +114,7 @@ describe('BitbucketUrlReader', () => { setupRequestMockHandlers(worker); describe('readUrl', () => { - it('should be able to readUrl without ETag', async () => { + it('should be able to readUrl via buffer without ETag', async () => { worker.use( rest.get( 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', @@ -135,6 +136,28 @@ describe('BitbucketUrlReader', () => { expect(buffer.toString()).toBe('foo'); }); + it('should be able to readUrl via stream without ETag', async () => { + worker.use( + rest.get( + 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', + (req, res, ctx) => { + expect(req.headers.get('If-None-Match')).toBeNull(); + return res( + ctx.status(200), + ctx.body('foo'), + ctx.set('ETag', 'etag-value'), + ); + }, + ), + ); + + const result = await bitbucketProcessor.readUrl( + 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', + ); + const fromStream = await getRawBody(result.stream!()); + expect(fromStream.toString()).toBe('foo'); + }); + it('should be able to readUrl with matching ETag', async () => { worker.use( rest.get( diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.ts b/packages/backend-common/src/reading/BitbucketUrlReader.ts index 1687a66262..805697bf27 100644 --- a/packages/backend-common/src/reading/BitbucketUrlReader.ts +++ b/packages/backend-common/src/reading/BitbucketUrlReader.ts @@ -40,6 +40,7 @@ import { SearchResponse, UrlReader, } from './types'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; /** * Implements a {@link UrlReader} for files from Bitbucket v1 and v2 APIs, such @@ -123,10 +124,9 @@ export class BitbucketUrlReader implements UrlReader { } if (response.ok) { - return { - buffer: async () => Buffer.from(await response.arrayBuffer()), + return ReadUrlResponseFactory.fromNodeJSReadable(response.body, { etag: response.headers.get('ETag') ?? undefined, - }; + }); } const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`; diff --git a/packages/backend-common/src/reading/FetchUrlReader.ts b/packages/backend-common/src/reading/FetchUrlReader.ts index cb873ebdf8..b83f08c22f 100644 --- a/packages/backend-common/src/reading/FetchUrlReader.ts +++ b/packages/backend-common/src/reading/FetchUrlReader.ts @@ -25,6 +25,7 @@ import { UrlReader, } from './types'; import path from 'path'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; /** * A {@link UrlReader} that does a plain fetch of the URL. @@ -103,10 +104,9 @@ export class FetchUrlReader implements UrlReader { } if (response.ok) { - return { - buffer: async () => Buffer.from(await response.arrayBuffer()), + return ReadUrlResponseFactory.fromNodeJSReadable(response.body, { etag: response.headers.get('ETag') ?? undefined, - }; + }); } const message = `could not read ${url}, ${response.status} ${response.statusText}`; diff --git a/packages/backend-common/src/reading/GerritUrlReader.test.ts b/packages/backend-common/src/reading/GerritUrlReader.test.ts index fc27b3dd6a..4e0b97fc58 100644 --- a/packages/backend-common/src/reading/GerritUrlReader.test.ts +++ b/packages/backend-common/src/reading/GerritUrlReader.test.ts @@ -31,6 +31,7 @@ import { getVoidLogger } from '../logging'; import { UrlReaderPredicateTuple } from './types'; import { DefaultReadTreeResponseFactory } from './tree'; import { GerritUrlReader } from './GerritUrlReader'; +import getRawBody from 'raw-body'; const treeResponseFactory = DefaultReadTreeResponseFactory.create({ config: new ConfigReader({}), @@ -128,7 +129,7 @@ describe('GerritUrlReader', () => { describe('readUrl', () => { const responseBuffer = Buffer.from('Apache License'); - it('should be able to read file contents', async () => { + it('should be able to read file contents as buffer', async () => { worker.use( rest.get( 'https://gerrit.com/projects/web%2Fproject/branches/master/files/LICENSE/content', @@ -148,6 +149,26 @@ describe('GerritUrlReader', () => { expect(buffer.toString()).toBe(responseBuffer.toString()); }); + it('should be able to read file contents as stream', async () => { + worker.use( + rest.get( + 'https://gerrit.com/projects/web%2Fproject/branches/master/files/LICENSE/content', + (_, res, ctx) => { + return res( + ctx.status(200), + ctx.body(responseBuffer.toString('base64')), + ); + }, + ), + ); + + const result = await gerritProcessor.readUrl( + 'https://gerrit.com/web/project/+/refs/heads/master/LICENSE', + ); + const fromStream = await getRawBody(result.stream!()); + expect(fromStream.toString()).toBe(responseBuffer.toString()); + }); + it('should raise NotFoundError on 404.', async () => { worker.use( rest.get( diff --git a/packages/backend-common/src/reading/GerritUrlReader.ts b/packages/backend-common/src/reading/GerritUrlReader.ts index f3e8924192..59b33bb2cb 100644 --- a/packages/backend-common/src/reading/GerritUrlReader.ts +++ b/packages/backend-common/src/reading/GerritUrlReader.ts @@ -25,6 +25,7 @@ import { parseGerritJsonResponse, parseGerritGitilesUrl, } from '@backstage/integration'; +import { Base64Decode } from 'base64-stream'; import concatStream from 'concat-stream'; import fs from 'fs-extra'; import fetch, { Response } from 'node-fetch'; @@ -125,9 +126,18 @@ export class GerritUrlReader implements UrlReader { throw new Error(`Unable to read gerrit file ${url}, ${e}`); } if (response.ok) { - const responseBody = await response.text(); + let responseBody: string; return { - buffer: async () => Buffer.from(responseBody, 'base64'), + buffer: async () => { + if (responseBody === undefined) { + responseBody = await response.text(); + } + return Buffer.from(responseBody, 'base64'); + }, + stream: () => { + const readable = new Readable().wrap(response.body); + return readable.pipe(new Base64Decode()); + }, }; } if (response.status === 404) { diff --git a/packages/backend-common/src/reading/GithubUrlReader.ts b/packages/backend-common/src/reading/GithubUrlReader.ts index d86f491827..3806253a6f 100644 --- a/packages/backend-common/src/reading/GithubUrlReader.ts +++ b/packages/backend-common/src/reading/GithubUrlReader.ts @@ -39,6 +39,7 @@ import { ReadUrlOptions, ReadUrlResponse, } from './types'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; export type GhRepoResponse = RestEndpointMethodTypes['repos']['get']['response']['data']; @@ -127,10 +128,9 @@ export class GithubUrlReader implements UrlReader { } if (response.ok) { - return { - buffer: async () => Buffer.from(await response.arrayBuffer()), + return ReadUrlResponseFactory.fromNodeJSReadable(response.body, { etag: response.headers.get('ETag') ?? undefined, - }; + }); } let message = `${url} could not be read as ${ghUrl}, ${response.status} ${response.statusText}`; diff --git a/packages/backend-common/src/reading/GitlabUrlReader.ts b/packages/backend-common/src/reading/GitlabUrlReader.ts index d0e43fea59..2387dadf5b 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.ts @@ -38,6 +38,7 @@ import { ReadUrlOptions, } from './types'; import { trimEnd } from 'lodash'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; /** * Implements a {@link UrlReader} for files on GitLab. @@ -97,10 +98,9 @@ export class GitlabUrlReader implements UrlReader { } if (response.ok) { - return { - buffer: async () => Buffer.from(await response.arrayBuffer()), + return ReadUrlResponseFactory.fromNodeJSReadable(response.body, { etag: response.headers.get('ETag') ?? undefined, - }; + }); } const message = `${url} could not be read as ${builtUrl}, ${response.status} ${response.statusText}`; diff --git a/packages/backend-common/src/reading/GoogleGcsUrlReader.ts b/packages/backend-common/src/reading/GoogleGcsUrlReader.ts index 167e20ca2b..56b15a60e7 100644 --- a/packages/backend-common/src/reading/GoogleGcsUrlReader.ts +++ b/packages/backend-common/src/reading/GoogleGcsUrlReader.ts @@ -28,6 +28,8 @@ import { GoogleGcsIntegrationConfig, readGoogleGcsIntegrationConfig, } from '@backstage/integration'; +import { Readable } from 'stream'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; const GOOGLE_GCS_HOST = 'storage.cloud.google.com'; @@ -85,13 +87,14 @@ export class GoogleGcsUrlReader implements UrlReader { private readonly storage: Storage, ) {} + private readStreamFromUrl(url: string): Readable { + const { bucket, key } = parseURL(url); + return this.storage.bucket(bucket).file(key).createReadStream(); + } + async read(url: string): Promise { try { - const { bucket, key } = parseURL(url); - - return await getRawBody( - this.storage.bucket(bucket).file(key).createReadStream(), - ); + return await getRawBody(this.readStreamFromUrl(url)); } catch (error) { throw new Error(`unable to read gcs file from ${url}, ${error}`); } @@ -102,8 +105,8 @@ export class GoogleGcsUrlReader implements UrlReader { _options?: ReadUrlOptions, ): Promise { // TODO etag is not implemented yet. - const buffer = await this.read(url); - return { buffer: async () => buffer }; + const stream = this.readStreamFromUrl(url); + return ReadUrlResponseFactory.fromReadable(stream); } async readTree(): Promise { diff --git a/packages/backend-common/src/reading/ReadUrlResponseFactory.test.ts b/packages/backend-common/src/reading/ReadUrlResponseFactory.test.ts new file mode 100644 index 0000000000..c8a659e792 --- /dev/null +++ b/packages/backend-common/src/reading/ReadUrlResponseFactory.test.ts @@ -0,0 +1,125 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ConflictError } from '@backstage/errors'; +import getRawBody from 'raw-body'; +import { Readable, Stream } from 'stream'; +import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; + +describe('ReadUrlResponseFactory', () => { + describe("fromReadable's", () => { + const expectedText = 'expected text'; + let readable: Readable; + + beforeEach(() => { + readable = Readable.from(expectedText, { + objectMode: false, + }); + }); + + it('etag is passed through', async () => { + const expectedEtag = 'xyz'; + const response = await ReadUrlResponseFactory.fromReadable(readable, { + etag: expectedEtag, + }); + expect(response.etag).toEqual(expectedEtag); + }); + + it('buffer returns expected data', async () => { + const response = await ReadUrlResponseFactory.fromReadable(readable); + const buffer = await response.buffer(); + expect(buffer.toString()).toEqual(expectedText); + }); + + it('buffer can be called multiple times', async () => { + const response = await ReadUrlResponseFactory.fromReadable(readable); + const buffer1 = await response.buffer(); + const buffer2 = await response.buffer(); + expect(buffer1.toString()).toEqual(expectedText); + expect(buffer2.toString()).toEqual(expectedText); + }); + + it('buffer cannot be called after stream is called', async () => { + const response = await ReadUrlResponseFactory.fromReadable(readable); + response.stream!(); + expect(() => response.buffer()).toThrowError(ConflictError); + }); + + it('stream returns expected data', async () => { + const response = await ReadUrlResponseFactory.fromReadable(readable); + const stream = response.stream!(); + const bufferFromStream = await getRawBody(stream); + expect(bufferFromStream.toString()).toEqual(expectedText); + }); + + it('stream cannot be called after buffer is called', async () => { + const response = await ReadUrlResponseFactory.fromReadable(readable); + response.buffer(); + expect(() => response.stream!()).toThrowError(ConflictError); + }); + }); + + describe("fromNodeJSReadable's", () => { + const expectedText = 'expected text'; + const timeouts: NodeJS.Timeout[] = []; + let readable: NodeJS.ReadableStream; + + beforeEach(() => { + // @ts-ignore + readable = new Stream({ encoding: 'utf-8' }); + readable.readable = true; + + // Write data asynchronously, as soon as possible. + timeouts[0] = setTimeout(() => { + timeouts[1] = setTimeout(readable.emit.bind(readable, 'end'), 0); + readable.emit('data', expectedText); + }, 0); + }); + + afterEach(() => { + // Clear out timeouts so we don't emit data across tests. + timeouts.forEach(clearTimeout); + }); + + it('etag is passed through', async () => { + const expectedEtag = 'xyz'; + const response = await ReadUrlResponseFactory.fromNodeJSReadable( + readable, + { + etag: expectedEtag, + }, + ); + expect(response.etag).toEqual(expectedEtag); + }); + + it('buffer returns expected data', async () => { + const response = await ReadUrlResponseFactory.fromNodeJSReadable( + readable, + ); + const buffer = await response.buffer(); + expect(buffer.toString()).toEqual(expectedText); + }); + + it('stream returns expected data', async () => { + const response = await ReadUrlResponseFactory.fromNodeJSReadable( + readable, + ); + const stream = response.stream!(); + const bufferFromStream = await getRawBody(stream); + expect(bufferFromStream.toString()).toEqual(expectedText); + }); + }); +}); diff --git a/packages/backend-common/src/reading/ReadUrlResponseFactory.ts b/packages/backend-common/src/reading/ReadUrlResponseFactory.ts new file mode 100644 index 0000000000..91d1939c24 --- /dev/null +++ b/packages/backend-common/src/reading/ReadUrlResponseFactory.ts @@ -0,0 +1,77 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ConflictError } from '@backstage/errors'; +import getRawBody from 'raw-body'; +import { Readable } from 'stream'; +import { + ReadUrlResponse, + ReadUrlResponseFactoryFromStreamOptions, +} from './types'; + +/** + * Utility class for UrlReader implementations to create valid ReadUrlResponse + * instances from common response primitives. + * + * @public + */ +export class ReadUrlResponseFactory { + /** + * Resolves a ReadUrlResponse from a Readable stream. + */ + static async fromReadable( + stream: Readable, + options?: ReadUrlResponseFactoryFromStreamOptions, + ): Promise { + // Reference to eventual buffer enables callers to call buffer() multiple + // times without consequence. + let buffer: Promise; + + // Prevent "stream is not readable" errors from bubbling up. + const conflictError = new ConflictError( + 'Cannot use buffer() and stream() from the same ReadUrlResponse', + ); + let hasCalledStream = false; + let hasCalledBuffer = false; + + return { + buffer: () => { + hasCalledBuffer = true; + if (hasCalledStream) throw conflictError; + if (buffer) return buffer; + buffer = getRawBody(stream); + return buffer; + }, + stream: () => { + hasCalledStream = true; + if (hasCalledBuffer) throw conflictError; + return stream; + }, + etag: options?.etag, + }; + } + + /** + * Resolves a ReadUrlResponse from an old-style NodeJS.ReadableStream. + */ + static async fromNodeJSReadable( + oldStyleStream: NodeJS.ReadableStream, + options?: ReadUrlResponseFactoryFromStreamOptions, + ): Promise { + const readable = new Readable().wrap(oldStyleStream); + return ReadUrlResponseFactory.fromReadable(readable, options); + } +} diff --git a/packages/backend-common/src/reading/index.ts b/packages/backend-common/src/reading/index.ts index f1609179b5..9ee86ef3f2 100644 --- a/packages/backend-common/src/reading/index.ts +++ b/packages/backend-common/src/reading/index.ts @@ -23,6 +23,7 @@ export { GithubUrlReader } from './GithubUrlReader'; export { GitlabUrlReader } from './GitlabUrlReader'; export { AwsS3UrlReader } from './AwsS3UrlReader'; export { FetchUrlReader } from './FetchUrlReader'; +export { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; export type { FromReadableArrayOptions, ReaderFactory, @@ -34,6 +35,7 @@ export type { ReadTreeResponseFactoryOptions, ReadUrlOptions, ReadUrlResponse, + ReadUrlResponseFactoryFromStreamOptions, SearchOptions, SearchResponse, SearchResponseFile, diff --git a/packages/backend-common/src/reading/types.ts b/packages/backend-common/src/reading/types.ts index 9505778705..6eae4e6cac 100644 --- a/packages/backend-common/src/reading/types.ts +++ b/packages/backend-common/src/reading/types.ts @@ -124,6 +124,15 @@ export type ReadUrlResponse = { */ buffer(): Promise; + /** + * Returns the data that was read from the remote URL as a Readable stream. + * + * @remarks + * + * This method will be required in a future release. + */ + stream?(): Readable; + /** * Etag returned by content provider. * @@ -134,6 +143,15 @@ export type ReadUrlResponse = { etag?: string; }; +/** + * An options object for {@link ReadUrlResponseFactory} factory methods. + * + * @public + */ +export type ReadUrlResponseFactoryFromStreamOptions = { + etag?: string; +}; + /** * An options object for {@link UrlReader.readTree} operations. * diff --git a/packages/backend-common/src/tokens/ServerTokenManager.test.ts b/packages/backend-common/src/tokens/ServerTokenManager.test.ts index 0ff7bfb316..6a72b99908 100644 --- a/packages/backend-common/src/tokens/ServerTokenManager.test.ts +++ b/packages/backend-common/src/tokens/ServerTokenManager.test.ts @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { getVoidLogger } from '../logging/voidLogger'; + import { ConfigReader } from '@backstage/config'; -import { ServerTokenManager } from './ServerTokenManager'; -import { Logger } from 'winston'; import * as jose from 'jose'; +import { Logger } from 'winston'; +import { getVoidLogger } from '../logging/voidLogger'; +import { ServerTokenManager } from './ServerTokenManager'; import { TokenManager } from './types'; const emptyConfig = new ConfigReader({}); @@ -35,6 +36,7 @@ describe('ServerTokenManager', () => { afterEach(() => { process.env = env; + jest.useRealTimers(); }); describe('getToken', () => { @@ -166,6 +168,42 @@ describe('ServerTokenManager', () => { /invalid server token/i, ); }); + + it('should throw for expired tokens, and re-issue new ones', async () => { + jest.useFakeTimers(); + const warn = jest.spyOn(logger, 'warn'); + + const tokenManager = ServerTokenManager.fromConfig(configWithSecret, { + logger, + }); + + const { token: token1 } = await tokenManager.getToken(); + await expect(tokenManager.authenticate(token1)).resolves.not.toThrow(); + expect(warn.mock.calls.length).toBe(0); + + // Right before the reissue timeout, it still returns the same token + jest.advanceTimersByTime(9 * 60 * 1000); + const { token: token1Again } = await tokenManager.getToken(); + expect(token1).toEqual(token1Again); + await expect(tokenManager.authenticate(token1)).resolves.not.toThrow(); + expect(warn.mock.calls.length).toBe(0); + + // Right after the reissue timeout, the old ones are still valid but returning a new token + jest.advanceTimersByTime(2 * 60 * 1000); + const { token: token2 } = await tokenManager.getToken(); + expect(token1).not.toEqual(token2); + await expect(tokenManager.authenticate(token1)).resolves.not.toThrow(); + await expect(tokenManager.authenticate(token2)).resolves.not.toThrow(); + expect(warn.mock.calls.length).toBe(0); + + // After expiry of the first one, it gets warnings but the newest one is still valid + jest.advanceTimersByTime(52 * 60 * 1000); + await expect(tokenManager.authenticate(token1)).resolves.not.toThrow(); + await expect(tokenManager.authenticate(token2)).resolves.not.toThrow(); + expect(warn.mock.calls[0][0]).toMatchInlineSnapshot( + '"#### DEPRECATION WARNING: #### Server-to-server token had an expired exp claim, support for this has been deprecated and will result in errors in a future release"', + ); + }); }); describe('fromConfig', () => { @@ -242,7 +280,7 @@ describe('ServerTokenManager', () => { }); }); - describe('ServerTokenManager.noop', () => { + describe('noop', () => { let noopTokenManager: TokenManager; beforeEach(() => { diff --git a/packages/backend-common/src/tokens/ServerTokenManager.ts b/packages/backend-common/src/tokens/ServerTokenManager.ts index 484b99ca4d..329c2f164c 100644 --- a/packages/backend-common/src/tokens/ServerTokenManager.ts +++ b/packages/backend-common/src/tokens/ServerTokenManager.ts @@ -14,12 +14,22 @@ * limitations under the License. */ -import { base64url, generateSecret, SignJWT, jwtVerify, exportJWK } from 'jose'; import { Config } from '@backstage/config'; -import { AuthenticationError } from '@backstage/errors'; -import { TokenManager } from './types'; +import { AuthenticationError, NotAllowedError } from '@backstage/errors'; +import { base64url, exportJWK, generateSecret, jwtVerify, SignJWT } from 'jose'; +import { DateTime, Duration } from 'luxon'; import { Logger } from 'winston'; +import { TokenManager } from './types'; +const TOKEN_ALG = 'HS256'; +const TOKEN_SUB = 'backstage-server'; +const TOKEN_EXPIRY_AFTER = Duration.fromObject({ hours: 1 }); +const TOKEN_REISSUE_AFTER = Duration.fromObject({ minutes: 10 }); + +/** + * A token manager that issues static dummy tokens and never fails + * authentication. This can be useful for testing. + */ class NoopTokenManager implements TokenManager { public readonly isInsecureServerTokenManager: boolean = true; @@ -30,6 +40,18 @@ class NoopTokenManager implements TokenManager { async authenticate() {} } +/** + * Options for {@link ServerTokenManager}. + * + * @public + */ +export interface ServerTokenManagerOptions { + /** + * The logger to use. + */ + logger: Logger; +} + /** * Creates and validates tokens for use during backend-to-backend * authentication. @@ -37,44 +59,51 @@ class NoopTokenManager implements TokenManager { * @public */ export class ServerTokenManager implements TokenManager { - private verificationKeys: Uint8Array[]; + private readonly options: ServerTokenManagerOptions; + private readonly verificationKeys: Uint8Array[]; private signingKey: Uint8Array; - private privateKeyPromise?: Promise; - private logger: Logger; + private privateKeyPromise: Promise | undefined; + private currentTokenPromise: Promise<{ token: string }> | undefined; + private warnedForMissingExpClaim = false; + private warnedForExpiredExpClaim = false; + /** + * Creates a token manager that issues static dummy tokens and never fails + * authentication. This can be useful for testing. + */ static noop(): TokenManager { return new NoopTokenManager(); } - static fromConfig(config: Config, options: { logger: Logger }) { - const { logger } = options; - + static fromConfig(config: Config, options: ServerTokenManagerOptions) { const keys = config.getOptionalConfigArray('backend.auth.keys'); if (keys?.length) { return new ServerTokenManager( keys.map(key => key.getString('secret')), - logger, + options, ); } + if (process.env.NODE_ENV !== 'development') { throw new Error( 'You must configure at least one key in backend.auth.keys for production.', ); } + // For development, if a secret has not been configured, we auto generate a secret instead of throwing. - logger.warn( + options.logger.warn( 'Generated a secret for backend-to-backend authentication: DEVELOPMENT USE ONLY.', ); - return new ServerTokenManager([], logger); + return new ServerTokenManager([], options); } - private constructor(secrets: string[], logger: Logger) { + private constructor(secrets: string[], options: ServerTokenManagerOptions) { if (!secrets.length && process.env.NODE_ENV !== 'development') { throw new Error( 'No secrets provided when constructing ServerTokenManager', ); } - this.logger = logger; + this.options = options; this.verificationKeys = secrets.map(s => base64url.decode(s)); this.signingKey = this.verificationKeys[0]; } @@ -86,11 +115,13 @@ export class ServerTokenManager implements TokenManager { 'Key generation is not supported outside of the dev environment', ); } + if (this.privateKeyPromise) { return this.privateKeyPromise; } + const promise = (async () => { - const secret = await generateSecret('HS256'); + const secret = await generateSecret(TOKEN_ALG); const jwk = await exportJWK(secret); this.verificationKeys.push(base64url.decode(jwk.k ?? '')); this.signingKey = this.verificationKeys[0]; @@ -98,13 +129,15 @@ export class ServerTokenManager implements TokenManager { })(); try { - // If we fail to generate a new key, we need to clear the state so that - // the next caller will try to generate another key. + this.privateKeyPromise = promise; await promise; } catch (error) { - this.logger.error(`Failed to generate new key, ${error}`); + // If we fail to generate a new key, we need to clear the state so that + // the next caller will try to generate another key. + this.options.logger.error(`Failed to generate new key, ${error}`); delete this.privateKeyPromise; } + return promise; } @@ -112,26 +145,83 @@ export class ServerTokenManager implements TokenManager { if (!this.verificationKeys.length) { await this.generateKeys(); } - const sub = 'backstage-server'; - const jwt = await new SignJWT({ alg: 'HS256' }) - .setProtectedHeader({ alg: 'HS256', sub: sub }) - .setSubject('backstage-server') - .sign(this.signingKey); - return { token: jwt }; + + if (this.currentTokenPromise) { + return this.currentTokenPromise; + } + + const result = Promise.resolve().then(async () => { + const jwt = await new SignJWT({}) + .setProtectedHeader({ alg: TOKEN_ALG }) + .setSubject(TOKEN_SUB) + .setExpirationTime( + DateTime.now().plus(TOKEN_EXPIRY_AFTER).toUnixInteger(), + ) + .sign(this.signingKey); + return { token: jwt }; + }); + + this.currentTokenPromise = result; + + result + .then(() => { + setTimeout(() => { + this.currentTokenPromise = undefined; + }, TOKEN_REISSUE_AFTER.toMillis()); + }) + .catch(() => { + this.currentTokenPromise = undefined; + }); + + return result; } async authenticate(token: string): Promise { let verifyError = undefined; + for (const key of this.verificationKeys) { try { - await jwtVerify(token, key); - // If the verify succeeded, return + const { + protectedHeader: { alg }, + payload: { sub, exp }, + } = await jwtVerify(token, key, { + // TODO(freben): Holding on to tokens and reusing them is deprecated; remove this tolerance in a future release + clockTolerance: 3e9, + }); + + if (alg !== TOKEN_ALG) { + throw new NotAllowedError(`Illegal alg "${alg}"`); + } + + if (sub !== TOKEN_SUB) { + throw new NotAllowedError(`Illegal sub "${sub}"`); + } + + // TODO(freben): Passing in tokens without an exp is deprecated; change this warning to an error in a future release + if (typeof exp !== 'number') { + if (!this.warnedForMissingExpClaim) { + this.warnedForMissingExpClaim = true; + this.options.logger.warn( + `#### DEPRECATION WARNING: #### Server-to-server token had no exp claim, support for this has been deprecated and will result in errors in a future release`, + ); + } + } + // TODO(freben): Holding on to tokens and reusing them is deprecated; remove this tolerance in a future release + else if (exp * 1000 < Date.now()) { + if (!this.warnedForExpiredExpClaim) { + this.warnedForExpiredExpClaim = true; + this.options.logger.warn( + `#### DEPRECATION WARNING: #### Server-to-server token had an expired exp claim, support for this has been deprecated and will result in errors in a future release`, + ); + } + } return; } catch (e) { // Catch the verify exception and continue verifyError = e; } } + throw new AuthenticationError(`Invalid server token: ${verifyError}`); } } diff --git a/packages/backend-common/src/tokens/index.ts b/packages/backend-common/src/tokens/index.ts index 43ff12e597..fe1b56df80 100644 --- a/packages/backend-common/src/tokens/index.ts +++ b/packages/backend-common/src/tokens/index.ts @@ -15,4 +15,5 @@ */ export { ServerTokenManager } from './ServerTokenManager'; +export type { ServerTokenManagerOptions } from './ServerTokenManager'; export type { TokenManager } from './types'; diff --git a/packages/backend-common/src/tokens/types.ts b/packages/backend-common/src/tokens/types.ts index 1fea018db9..2fa771b7e2 100644 --- a/packages/backend-common/src/tokens/types.ts +++ b/packages/backend-common/src/tokens/types.ts @@ -20,6 +20,20 @@ * @public */ export interface TokenManager { - getToken: () => Promise<{ token: string }>; - authenticate: (token: string) => Promise; + /** + * Fetches a valid token. + * + * @remarks + * + * Tokens are valid for roughly one hour; the actual deadline is set in the + * payload `exp` claim. Never hold on to tokens for reuse; always ask for a + * new one for each outgoing request. This ensures that you always get a + * valid, fresh one. + */ + getToken(): Promise<{ token: string }>; + + /** + * Validates a given token. + */ + authenticate(token: string): Promise; } diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index a8c66d866d..73e18d5c6c 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/backend-tasks +## 0.3.1-next.1 + +### Patch Changes + +- 73480846dd: `TaskScheduleDefinition` has been updated to also accept an options object containing duration information in the form of days, hours, seconds and so on. This allows for scheduling without importing `luxon`. + + ```diff + -import { Duration } from 'luxon'; + // omitted other code + + const schedule = env.scheduler.createScheduledTaskRunner({ + - frequency: Duration.fromObject({ minutes: 10 }), + - timeout: Duration.fromObject({ minutes: 15 }), + + frequency: { minutes: 10 }, + + timeout: { minutes: 15 }, + // omitted other code + }); + ``` + +- ebbec677e1: Correctly set next run time for tasks +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + ## 0.3.1-next.0 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 20eab4e58e..c9e1371447 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.3.1-next.0", + "version": "0.3.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -33,8 +33,8 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", "@backstage/types": "^1.0.0", "@types/luxon": "^2.0.4", @@ -48,8 +48,8 @@ "zod": "^3.9.5" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.24-next.0", - "@backstage/cli": "^0.17.1-next.0", + "@backstage/backend-test-utils": "^0.1.24-next.1", + "@backstage/cli": "^0.17.1-next.2", "@types/cron": "^1.7.3", "wait-for-expect": "^3.0.2" }, diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 4a6a5a0c25..d224abb4e4 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-test-utils +## 0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/cli@0.17.1-next.2 + ## 0.1.24-next.0 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index eb6f7e0aba..0c7dc08e8b 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-test-utils", "description": "Test helpers library for Backstage backends", - "version": "0.1.24-next.0", + "version": "0.1.24-next.1", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -34,9 +34,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/cli": "^0.17.1-next.0", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/config": "^1.0.1-next.0", "better-sqlite3": "^7.5.0", "knex": "^1.0.2", "msw": "^0.35.0", @@ -46,7 +46,7 @@ "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0" + "@backstage/cli": "^0.17.1-next.2" }, "files": [ "dist" diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index d77bb00d72..649d2fc525 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,45 @@ # example-backend +## 0.2.71-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-kubernetes-backend@0.5.1-next.1 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.0-next.1 + - @backstage/plugin-scaffolder-backend@1.2.0-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-backend-node@0.6.1-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@0.1.4-next.1 + - @backstage/plugin-search-backend-module-pg@0.3.3-next.1 + - @backstage/plugin-azure-devops-backend@0.3.11-next.1 + - example-app@0.2.71-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/plugin-app-backend@0.3.32-next.1 + - @backstage/plugin-auth-backend@0.13.1-next.2 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-badges-backend@0.1.26-next.1 + - @backstage/plugin-code-coverage-backend@0.1.30-next.1 + - @backstage/plugin-graphql-backend@0.1.22-next.1 + - @backstage/plugin-jenkins-backend@0.1.22-next.1 + - @backstage/plugin-kafka-backend@0.2.25-next.1 + - @backstage/plugin-permission-backend@0.5.7-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-permission-node@0.6.1-next.1 + - @backstage/plugin-proxy-backend@0.2.26-next.1 + - @backstage/plugin-rollbar-backend@0.1.29-next.2 + - @backstage/plugin-search-backend@0.5.2-next.1 + - @backstage/plugin-tech-insights-backend@0.4.0-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.16-next.2 + - @backstage/plugin-tech-insights-node@0.3.0-next.2 + - @backstage/plugin-techdocs-backend@1.1.1-next.1 + - @backstage/plugin-todo-backend@0.1.29-next.1 + - @backstage/catalog-client@1.0.2-next.0 + ## 0.2.71-next.1 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 1757693252..9b1664cbe9 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.71-next.1", + "version": "0.2.71-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -26,39 +26,39 @@ "build-image": "docker build ../.. -f Dockerfile --tag example-backend" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.1", - "@backstage/backend-tasks": "^0.3.1-next.0", - "@backstage/catalog-client": "^1.0.1", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/plugin-app-backend": "^0.3.32-next.0", - "@backstage/plugin-auth-backend": "^0.13.1-next.1", - "@backstage/plugin-auth-node": "^0.2.1-next.0", - "@backstage/plugin-azure-devops-backend": "^0.3.11-next.0", - "@backstage/plugin-badges-backend": "^0.1.26-next.0", - "@backstage/plugin-catalog-backend": "^1.1.2-next.1", - "@backstage/plugin-code-coverage-backend": "^0.1.30-next.0", - "@backstage/plugin-graphql-backend": "^0.1.22-next.0", - "@backstage/plugin-jenkins-backend": "^0.1.22-next.0", - "@backstage/plugin-kubernetes-backend": "^0.5.1-next.0", - "@backstage/plugin-kafka-backend": "^0.2.25-next.0", - "@backstage/plugin-permission-backend": "^0.5.7-next.0", - "@backstage/plugin-permission-common": "^0.6.0", - "@backstage/plugin-permission-node": "^0.6.1-next.0", - "@backstage/plugin-proxy-backend": "^0.2.26-next.0", - "@backstage/plugin-rollbar-backend": "^0.1.29-next.1", - "@backstage/plugin-scaffolder-backend": "^1.2.0-next.0", - "@backstage/plugin-scaffolder-backend-module-rails": "^0.3.7-next.0", - "@backstage/plugin-search-backend": "^0.5.2-next.0", - "@backstage/plugin-search-backend-node": "^0.6.1-next.0", - "@backstage/plugin-search-backend-module-elasticsearch": "^0.1.4-next.0", - "@backstage/plugin-search-backend-module-pg": "^0.3.3-next.0", - "@backstage/plugin-techdocs-backend": "^1.1.1-next.0", - "@backstage/plugin-tech-insights-backend": "^0.4.0-next.1", - "@backstage/plugin-tech-insights-node": "^0.3.0-next.1", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.16-next.1", - "@backstage/plugin-todo-backend": "^0.1.29-next.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/backend-tasks": "^0.3.1-next.1", + "@backstage/catalog-client": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/plugin-app-backend": "^0.3.32-next.1", + "@backstage/plugin-auth-backend": "^0.13.1-next.2", + "@backstage/plugin-auth-node": "^0.2.1-next.1", + "@backstage/plugin-azure-devops-backend": "^0.3.11-next.1", + "@backstage/plugin-badges-backend": "^0.1.26-next.1", + "@backstage/plugin-catalog-backend": "^1.1.2-next.2", + "@backstage/plugin-code-coverage-backend": "^0.1.30-next.1", + "@backstage/plugin-graphql-backend": "^0.1.22-next.1", + "@backstage/plugin-jenkins-backend": "^0.1.22-next.1", + "@backstage/plugin-kubernetes-backend": "^0.5.1-next.1", + "@backstage/plugin-kafka-backend": "^0.2.25-next.1", + "@backstage/plugin-permission-backend": "^0.5.7-next.1", + "@backstage/plugin-permission-common": "^0.6.1-next.0", + "@backstage/plugin-permission-node": "^0.6.1-next.1", + "@backstage/plugin-proxy-backend": "^0.2.26-next.1", + "@backstage/plugin-rollbar-backend": "^0.1.29-next.2", + "@backstage/plugin-scaffolder-backend": "^1.2.0-next.1", + "@backstage/plugin-scaffolder-backend-module-rails": "^0.4.0-next.1", + "@backstage/plugin-search-backend": "^0.5.2-next.1", + "@backstage/plugin-search-backend-node": "^0.6.1-next.1", + "@backstage/plugin-search-backend-module-elasticsearch": "^0.1.4-next.1", + "@backstage/plugin-search-backend-module-pg": "^0.3.3-next.1", + "@backstage/plugin-techdocs-backend": "^1.1.1-next.1", + "@backstage/plugin-tech-insights-backend": "^0.4.0-next.2", + "@backstage/plugin-tech-insights-node": "^0.3.0-next.2", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.16-next.2", + "@backstage/plugin-todo-backend": "^0.1.29-next.1", "@gitbeaker/node": "^35.1.0", "@octokit/rest": "^18.5.3", "better-sqlite3": "^7.5.0", @@ -75,7 +75,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", + "@backstage/cli": "^0.17.1-next.2", "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 968afe294b..4c02f5fb28 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/catalog-client +## 1.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.0.2-next.0 + ## 1.0.1 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index a5af4e21c1..725f318d80 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "1.0.1", + "version": "1.0.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,12 +33,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", + "@backstage/catalog-model": "^1.0.2-next.0", "@backstage/errors": "^1.0.0", "cross-fetch": "^3.1.5" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/jest": "^26.0.7", "msw": "^0.35.0" }, diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 6dd90da2be..8cc061c193 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/catalog-model +## 1.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + ## 1.0.1 ### Patch Changes diff --git a/packages/catalog-model/examples/all.yaml b/packages/catalog-model/examples/all.yaml new file mode 100644 index 0000000000..c8e073345c --- /dev/null +++ b/packages/catalog-model/examples/all.yaml @@ -0,0 +1,12 @@ +apiVersion: backstage.io/v1alpha1 +kind: Location +metadata: + name: example-all + description: A collection of all Backstage example entities, except users, groups, and templates +spec: + targets: + - ./all-apis.yaml + - ./all-components.yaml + - ./all-domains.yaml + - ./all-resources.yaml + - ./all-systems.yaml diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 4154e1b8df..6d3506c5bf 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "1.0.1", + "version": "1.0.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,7 +34,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", "@backstage/types": "^1.0.0", "ajv": "^8.10.0", @@ -43,7 +43,7 @@ "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/jest": "^26.0.7", "@types/json-schema": "^7.0.5", "@types/lodash": "^4.14.151", diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md index c890e44b29..718f766286 100644 --- a/packages/cli-common/CHANGELOG.md +++ b/packages/cli-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/cli-common +## 0.1.9-next.0 + +### Patch Changes + +- 6e830352d4: Updated dependency `@types/node` to `^16.0.0`. + ## 0.1.8 ### Patch Changes diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index 3b05e93603..afeccfef8d 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-common", "description": "Common functionality used by cli, backend, and create-app", - "version": "0.1.8", + "version": "0.1.9-next.0", "private": false, "main": "src/index.ts", "types": "src/index.ts", @@ -34,7 +34,7 @@ }, "devDependencies": { "@types/jest": "^26.0.7", - "@types/node": "^14.14.32" + "@types/node": "^16.0.0" }, "files": [ "dist" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index da3e112df8..77db125206 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/cli +## 0.17.1-next.2 + +### Patch Changes + +- 632be18bbc: Updated `create-github-app` command to prompt for read or write permissions to simplify setup. +- Updated dependencies + - @backstage/cli-common@0.1.9-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/release-manifests@0.0.3-next.0 + - @backstage/config-loader@1.1.1-next.1 + ## 0.17.1-next.1 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 5440982d73..fe97e6127b 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.17.1-next.1", + "version": "0.17.1-next.2", "private": false, "publishConfig": { "access": "public" @@ -31,11 +31,11 @@ "backstage-cli": "bin/backstage-cli" }, "dependencies": { - "@backstage/cli-common": "^0.1.8", - "@backstage/config": "^1.0.0", - "@backstage/config-loader": "^1.1.1-next.0", + "@backstage/cli-common": "^0.1.9-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/config-loader": "^1.1.1-next.1", "@backstage/errors": "^1.0.0", - "@backstage/release-manifests": "^0.0.2", + "@backstage/release-manifests": "^0.0.3-next.0", "@backstage/types": "^1.0.0", "@hot-loader/react-dom-v16": "npm:@hot-loader/react-dom@^16.0.2", "@hot-loader/react-dom-v17": "npm:@hot-loader/react-dom@^17.0.2", @@ -125,13 +125,13 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-common": "^0.13.3-next.1", - "@backstage/config": "^1.0.0", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/core-components": "^0.9.4-next.1", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 9b3aec5d0e..a913c906f9 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/codemods +## 0.1.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.9-next.0 + ## 0.1.38-next.0 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index f1700564eb..2edf0ce953 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.38-next.0", + "version": "0.1.38-next.1", "private": false, "publishConfig": { "access": "public", @@ -34,7 +34,7 @@ "backstage-codemods": "bin/backstage-codemods" }, "dependencies": { - "@backstage/cli-common": "^0.1.8", + "@backstage/cli-common": "^0.1.9-next.0", "chalk": "^4.0.0", "jscodeshift": "^0.13.0", "jscodeshift-add-imports": "^1.0.10" diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 894be08dc0..e2f89babb2 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/config-loader +## 1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.9-next.0 + - @backstage/config@1.0.1-next.0 + ## 1.1.1-next.0 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index aa40320ac2..ca439d07ce 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "1.1.1-next.0", + "version": "1.1.1-next.1", "private": false, "publishConfig": { "access": "public", @@ -34,8 +34,8 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/cli-common": "^0.1.8", - "@backstage/config": "^1.0.0", + "@backstage/cli-common": "^0.1.9-next.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", "@backstage/types": "^1.0.0", "@types/json-schema": "^7.0.6", diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index ce8d1a05f4..396249fd86 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/config +## 1.0.1-next.0 + +### Patch Changes + +- 6e830352d4: Updated dependency `@types/node` to `^16.0.0`. + ## 1.0.0 ### Major Changes diff --git a/packages/config/package.json b/packages/config/package.json index bca6968b01..189963c333 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config", "description": "Config API used by Backstage core, backend, and CLI", - "version": "1.0.0", + "version": "1.0.1-next.0", "private": false, "publishConfig": { "access": "public", @@ -37,9 +37,9 @@ "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/test-utils": "^1.1.0-next.2", "@types/jest": "^26.0.7", - "@types/node": "^14.14.32" + "@types/node": "^16.0.0" }, "files": [ "dist" diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index d9450a53c5..a658b9a4b0 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/core-app-api +## 1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 1.0.2-next.0 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index c4d9ea050f..a0e96684b4 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.0.2-next.0", + "version": "1.0.2-next.1", "private": false, "publishConfig": { "access": "public", @@ -33,8 +33,8 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^1.0.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", "@types/prop-types": "^15.7.3", @@ -49,8 +49,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/packages/core-app-api/src/apis/implementations/auth/saml/types.ts b/packages/core-app-api/src/apis/implementations/auth/saml/types.ts index 55b278b429..e5e32e3457 100644 --- a/packages/core-app-api/src/apis/implementations/auth/saml/types.ts +++ b/packages/core-app-api/src/apis/implementations/auth/saml/types.ts @@ -34,7 +34,6 @@ export const samlSessionSchema: z.ZodSchema = z.object({ picture: z.string().optional(), }), backstageIdentity: z.object({ - id: z.string(), token: z.string(), identity: z.object({ type: z.literal('user'), diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 147f4b4f52..05efac4a62 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/core-components +## 0.9.4-next.2 + +### Patch Changes + +- 52c02ac02b: Don't set the background color on an Avatar component that has a picture. +- 3603014e0e: Add ARIA landmark(
), & label and a heading to OAuthRequestDialog. Removed nested interactive control (button). +- 2025d7c123: Properly highlight `SidebarSubmenuItem` dropdown items on hover, use ellipsis styling on long labels in `SidebarSubmenu`, allow `icon` and `to` properties to be optional on `SidebarSubmenuItem`, and fix `SidebarPage` padding to be responsive to pinned state + +## 0.9.4-next.1 + +### Patch Changes + +- 55f68c386a: Enabled select component to be enabled by keyboard +- ba97b80421: Updated dependency `@types/react-syntax-highlighter` to `^15.0.0`. +- 2bcb0a0e2b: Sidebar NAV now includes aria-label. Component AboutField now uses h2 variant instead of subtitle2 (font properties unchanged) +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.9.4-next.0 ### Patch Changes diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index a195d62496..727a50926c 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -1084,8 +1084,8 @@ export type SidebarSubmenuItemDropdownItem = { // @public export type SidebarSubmenuItemProps = { title: string; - to: string; - icon: IconComponent; + to?: string; + icon?: IconComponent; dropdownItems?: SidebarSubmenuItemDropdownItem[]; }; diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 35ba6db9c5..e2f05aff2d 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.9.4-next.0", + "version": "0.9.4-next.2", "private": false, "publishConfig": { "access": "public", @@ -33,8 +33,8 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^1.0.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", "@backstage/theme": "^0.2.15", "@material-table/core": "^3.1.0", @@ -55,7 +55,7 @@ "pluralize": "^8.0.0", "prop-types": "^15.7.2", "qs": "^6.9.4", - "rc-progress": "3.2.4", + "rc-progress": "3.3.2", "react-helmet": "6.1.0", "react-hook-form": "^7.12.2", "react-markdown": "^8.0.0", @@ -78,9 +78,9 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/cli": "^0.17.1-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -95,7 +95,7 @@ "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "@types/react-helmet": "^6.1.0", - "@types/react-syntax-highlighter": "^13.5.2", + "@types/react-syntax-highlighter": "^15.0.0", "@types/react-virtualized-auto-sizer": "^1.0.1", "@types/react-window": "^1.8.5", "@types/zen-observable": "^0.8.0", diff --git a/packages/core-components/src/components/Avatar/Avatar.test.tsx b/packages/core-components/src/components/Avatar/Avatar.test.tsx index 1c08d57679..d7bbf712fe 100644 --- a/packages/core-components/src/components/Avatar/Avatar.test.tsx +++ b/packages/core-components/src/components/Avatar/Avatar.test.tsx @@ -17,6 +17,7 @@ import { render } from '@testing-library/react'; import React from 'react'; import { Avatar } from './Avatar'; +import { stringToColor } from './utils'; describe('', () => { it('renders without exploding', async () => { @@ -24,4 +25,24 @@ describe('', () => { expect(getByText('JD')).toBeInTheDocument(); }); + + it('generates a background color', async () => { + const bgcolor = stringToColor('John Doe'); + const { getByText } = render(); + expect(getByText('JD')).toHaveStyle(`background-color: ${bgcolor}`); + }); + + it('does not generate a background color when a picture is given', async () => { + const bgcolor = stringToColor('John Doe'); + const { getByAltText } = render( + , + ); + + expect(getByAltText('John Doe')).not.toHaveStyle( + `background-color: ${bgcolor}`, + ); + }); }); diff --git a/packages/core-components/src/components/Avatar/Avatar.tsx b/packages/core-components/src/components/Avatar/Avatar.tsx index 304ee574d2..af8dabf554 100644 --- a/packages/core-components/src/components/Avatar/Avatar.tsx +++ b/packages/core-components/src/components/Avatar/Avatar.tsx @@ -67,15 +67,23 @@ export interface AvatarProps { export function Avatar(props: AvatarProps) { const { displayName, picture, customStyles } = props; const classes = useStyles(); + let styles = { ...customStyles }; + // We only calculate the background color if there's not an avatar + // picture. If there is a picture, it might have a transparent + // background and we don't know whether the calculated background + // color will clash. + if (!picture) { + styles = { + backgroundColor: stringToColor(displayName || ''), + ...customStyles, + }; + } return ( {displayName && extractInitials(displayName)} diff --git a/packages/core-components/src/components/Chip/Chip.stories.tsx b/packages/core-components/src/components/Chip/Chip.stories.tsx index f5cdfd3f16..5e00779209 100644 --- a/packages/core-components/src/components/Chip/Chip.stories.tsx +++ b/packages/core-components/src/components/Chip/Chip.stories.tsx @@ -15,29 +15,51 @@ */ import React from 'react'; -import Chip from '@material-ui/core/Chip'; +import AddIcon from '@material-ui/icons/Add'; +import WarningIcon from '@material-ui/icons/Warning'; +import EditIcon from '@material-ui/icons/Edit'; +import Chip, { ChipProps } from '@material-ui/core/Chip'; + +const icons = { + AddIcon: , + WarningIcon: , + EditIcon: , + None: null, +}; + +const defaultArgs = { + label: 'Label', + size: 'medium', + variant: 'default', + icon: 'None', +}; export default { title: 'Data Display/Chip', component: Chip, + argTypes: { + size: { + options: ['small', 'medium'], + control: { type: 'select' }, + }, + variant: { + options: ['default', 'outlined'], + control: { type: 'select' }, + }, + icon: { + options: Object.keys(icons), + mapping: icons, + control: { + type: 'select', + }, + }, + }, }; -export const Default = () => ; +export const Default = (args: ChipProps) => ; +Default.args = defaultArgs; -export const LargeDeletable = () => ( - ({})} /> +export const Deleteable = (args: ChipProps) => ( + ({})} /> ); - -export const LargeNotDeletable = () => ( - -); - -export const SmallDeletable = () => ( - ({})} /> -); - -export const SmallNotDeletable = () => ( - -); - -export const Outline = () => ; +Deleteable.args = defaultArgs; diff --git a/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx b/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx index 449d4a987b..ac341071bf 100644 --- a/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx +++ b/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { DismissableBanner } from './DismissableBanner'; +import { DismissableBanner, Props } from './DismissableBanner'; import Typography from '@material-ui/core/Typography'; import { WebStorage } from '@backstage/core-app-api'; import { @@ -29,6 +29,12 @@ import { Link } from '../Link'; export default { title: 'Feedback/DismissableBanner', component: DismissableBanner, + argTypes: { + variant: { + options: ['info', 'error', 'warning'], + control: { type: 'select' }, + }, + }, }; let errorApi: ErrorApi; @@ -39,47 +45,27 @@ const createWebStorage = (): StorageApi => { }; const apis = [[storageApiRef, createWebStorage()] as const]; +const defaultArgs = { + message: 'This is a dismissable banner', + variant: 'info', + fixed: false, +}; -export const Default = () => ( +export const Default = (args: Props) => (
- +
); -export const Error = () => ( -
- - - -
-); +Default.args = defaultArgs; -export const EmojisIncluded = () => ( -
- - - -
-); - -export const WithLink = () => ( +export const WithLink = (args: Props) => (
This is a dismissable banner with a link:{' '} @@ -88,34 +74,10 @@ export const WithLink = () => ( } - variant="info" id="linked_dismissable" />
); -export const Fixed = () => ( -
- - - -
-); - -export const Warning = () => ( -
- - - -
-); +WithLink.args = defaultArgs; diff --git a/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx b/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx index 9ff7616c45..99113fcdb1 100644 --- a/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx +++ b/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx @@ -87,7 +87,7 @@ const useStyles = makeStyles( { name: 'BackstageDismissableBanner' }, ); -type Props = { +export type Props = { variant: 'info' | 'error' | 'warning'; message: ReactNode; id: string; diff --git a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx index 0c6bd62bcb..c7707c07d5 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx @@ -59,7 +59,7 @@ const LoginRequestListItem = ({ request, busy, setBusy }: RowProps) => { const IconComponent = request.provider.icon; return ( - + diff --git a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx index b11821803a..02b1afe4a1 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx @@ -25,6 +25,7 @@ import React, { useMemo, useState } from 'react'; import useObservable from 'react-use/lib/useObservable'; import LoginRequestListItem from './LoginRequestListItem'; import { useApi, oauthRequestApiRef } from '@backstage/core-plugin-api'; +import Typography from '@material-ui/core/Typography'; export type OAuthRequestDialogClassKey = | 'dialog' @@ -40,6 +41,9 @@ const useStyles = makeStyles( title: { minWidth: 0, }, + titleHeading: { + fontSize: theme.typography.h6.fontSize, + }, contentList: { padding: 0, }, @@ -69,23 +73,31 @@ export function OAuthRequestDialog(_props: {}) { fullWidth maxWidth="xs" classes={{ paper: classes.dialog }} + aria-labelledby="oauth-req-dialog-title" > - - Login Required - +
+ + + Login Required + + - - - {requests.map(request => ( - - ))} - - + + + {requests.map(request => ( + + ))} + + +
diff --git a/packages/core-components/src/components/Select/Select.tsx b/packages/core-components/src/components/Select/Select.tsx index 022df0a7ad..31097d8aab 100644 --- a/packages/core-components/src/components/Select/Select.tsx +++ b/packages/core-components/src/components/Select/Select.tsx @@ -19,6 +19,7 @@ import Chip from '@material-ui/core/Chip'; import ClickAwayListener from '@material-ui/core/ClickAwayListener'; import FormControl from '@material-ui/core/FormControl'; import InputBase from '@material-ui/core/InputBase'; +import InputLabel from '@material-ui/core/InputLabel'; import MenuItem from '@material-ui/core/MenuItem'; import Select from '@material-ui/core/Select'; import { @@ -87,6 +88,16 @@ const useStyles = makeStyles( color: theme.palette.text.primary, }, }, + formLabel: { + transform: 'initial', + fontWeight: 'bold', + fontSize: 14, + fontFamily: theme.typography.fontFamily, + color: theme.palette.text.primary, + '&.Mui-focused': { + color: theme.palette.text.primary, + }, + }, chips: { display: 'flex', flexWrap: 'wrap', @@ -184,9 +195,9 @@ export function SelectComponent(props: SelectProps) { return (
- {label} + {label} setSearchText(e.target.value)} + /> + + {cards} + + ); +}; diff --git a/plugins/codescene/src/components/ProjectsComponent/index.ts b/plugins/codescene/src/components/ProjectsComponent/index.ts new file mode 100644 index 0000000000..f89c0de697 --- /dev/null +++ b/plugins/codescene/src/components/ProjectsComponent/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { ProjectsComponent } from './ProjectsComponent'; diff --git a/plugins/codescene/src/index.ts b/plugins/codescene/src/index.ts new file mode 100644 index 0000000000..355ff4eb31 --- /dev/null +++ b/plugins/codescene/src/index.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { + codescenePlugin, + CodeScenePage, + CodeSceneProjectDetailsPage, +} from './plugin'; +import CodeSceneIconComponent from './assets/codescene.icon.svg'; +import { IconComponent } from '@backstage/core-plugin-api'; + +/** + * @public + */ +export const CodeSceneIcon: IconComponent = + CodeSceneIconComponent as IconComponent; diff --git a/plugins/codescene/src/plugin.test.ts b/plugins/codescene/src/plugin.test.ts new file mode 100644 index 0000000000..1ffdb95b06 --- /dev/null +++ b/plugins/codescene/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { codescenePlugin } from './plugin'; + +describe('codescene', () => { + it('should export plugin', () => { + expect(codescenePlugin).toBeDefined(); + }); +}); diff --git a/plugins/codescene/src/plugin.ts b/plugins/codescene/src/plugin.ts new file mode 100644 index 0000000000..b4e297345d --- /dev/null +++ b/plugins/codescene/src/plugin.ts @@ -0,0 +1,69 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + createPlugin, + createRoutableExtension, + createApiFactory, + discoveryApiRef, +} from '@backstage/core-plugin-api'; +import { codesceneApiRef, CodeSceneClient } from './api/api'; +import { rootRouteRef, projectDetailsRouteRef } from './routes'; + +/** + * @public + */ +export const codescenePlugin = createPlugin({ + id: 'codescene', + apis: [ + createApiFactory({ + api: codesceneApiRef, + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new CodeSceneClient({ discoveryApi }), + }), + ], + routes: { + root: rootRouteRef, + projectPage: projectDetailsRouteRef, + }, +}); + +/** + * @public + */ +export const CodeScenePage = codescenePlugin.provide( + createRoutableExtension({ + name: 'CodeScenePage', + component: () => + import('./components/CodeScenePageComponent').then( + m => m.CodeScenePageComponent, + ), + mountPoint: rootRouteRef, + }), +); + +/** + * @public + */ +export const CodeSceneProjectDetailsPage = codescenePlugin.provide( + createRoutableExtension({ + name: 'CodeSceneProjectDetailsPage', + component: () => + import('./components/CodeSceneProjectDetailsPage').then( + m => m.CodeSceneProjectDetailsPage, + ), + mountPoint: projectDetailsRouteRef, + }), +); diff --git a/plugins/codescene/src/routes.ts b/plugins/codescene/src/routes.ts new file mode 100644 index 0000000000..2fd9a5ee38 --- /dev/null +++ b/plugins/codescene/src/routes.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createRouteRef } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'codescene', +}); + +export const projectDetailsRouteRef = createRouteRef({ + id: 'codescene-project-page', + params: ['projectId'], +}); diff --git a/plugins/codescene/src/setupTests.ts b/plugins/codescene/src/setupTests.ts new file mode 100644 index 0000000000..9bb3e72355 --- /dev/null +++ b/plugins/codescene/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index a12bc24c8b..42649d9ca9 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-config-schema +## 0.1.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.1.28-next.0 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index d66abe1f58..0a4e160dc8 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.28-next.0", + "version": "0.1.28-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,9 +24,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", "@backstage/theme": "^0.2.15", "@backstage/types": "^1.0.0", @@ -41,10 +41,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index baf6da53ed..7a8fb7ef5d 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-cost-insights +## 0.11.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.11.27-next.0 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index ef1b9e2c63..b9dd30d439 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.11.27-next.0", + "version": "0.11.27-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,10 +34,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -60,10 +60,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md new file mode 100644 index 0000000000..b7a1410e5f --- /dev/null +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -0,0 +1,10 @@ +# @internal/plugin-todo-list-backend + +## 1.0.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 471a496fd8..5f82fb2113 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.0", + "version": "1.0.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,10 +20,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.1-next.0", + "@backstage/plugin-auth-node": "^0.2.1-next.1", "@types/express": "^4.17.6", "cross-fetch": "^3.1.5", "express": "^4.17.1", @@ -33,7 +33,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", "msw": "^0.35.0", diff --git a/plugins/example-todo-list-common/CHANGELOG.md b/plugins/example-todo-list-common/CHANGELOG.md new file mode 100644 index 0000000000..5d7d4e5a65 --- /dev/null +++ b/plugins/example-todo-list-common/CHANGELOG.md @@ -0,0 +1,8 @@ +# @internal/plugin-todo-list-common + +## 1.0.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.1-next.0 diff --git a/plugins/example-todo-list-common/package.json b/plugins/example-todo-list-common/package.json index 48619d7de5..7d2443a3ce 100644 --- a/plugins/example-todo-list-common/package.json +++ b/plugins/example-todo-list-common/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-common", - "version": "1.0.0", + "version": "1.0.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,13 +23,13 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/plugin-permission-common": "^0.6.0" + "@backstage/plugin-permission-common": "^0.6.1-next.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@types/node": "^16.11.26", "msw": "^0.35.0", "cross-fetch": "^3.1.5" diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 93c0ef7c17..46a3789e62 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -21,8 +21,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -33,10 +33,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index c21c6f838d..edc1389481 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-explore +## 0.3.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.3.36-next.1 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index d1dc142ef0..dcd190861e 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.3.36-next.1", + "version": "0.3.36-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,10 +34,10 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/plugin-explore-react": "^0.0.17-next.0", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", @@ -53,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 0e02fc7556..93dab0b183 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -25,8 +25,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/plugin-catalog-react": "^1.1.0-next.1", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", @@ -39,10 +39,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index 1d3beb2aba..2701e9cb07 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-fossa +## 0.2.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.2.37-next.1 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 6b31188a1d..09e41c2e7f 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.37-next.1", + "version": "0.2.37-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,11 +35,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -53,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index a51066b7da..aff29d7e07 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -34,8 +34,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,10 +47,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 1e2ccc7213..a3537c71c1 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -24,8 +24,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/integration": "^1.2.0-next.0", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", @@ -43,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index c1542585e5..dc61a82446 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-github-actions +## 0.5.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + ## 0.5.5-next.1 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 69aca919ba..c4b2d7438f 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.5.5-next.1", + "version": "0.5.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,11 +36,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -55,10 +55,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 855f57e6eb..b7e889bedf 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-deployments +## 0.1.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/integration-react@1.1.0-next.2 + ## 0.1.36-next.1 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index fa38477979..3dee550bf7 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.36-next.1", + "version": "0.1.36-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,13 +24,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/integration-react": "^1.1.0-next.1", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/integration-react": "^1.1.0-next.2", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -43,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 16f079aaab..2fedb7d6df 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -35,8 +35,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,10 +48,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index 82749a211e..f96c9ca4b7 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-gocd +## 0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.1.11-next.1 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 16894fd78d..6d7f273447 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.11-next.1", + "version": "0.1.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index 2dafc7ef99..de6ed6cd7d 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphiql +## 0.2.37-next.1 + +### Patch Changes + +- e1f42a0e2c: Updated dependency `@types/codemirror` to `^5.0.0`. +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.2.37-next.0 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 9abdf8fbd7..e19a3e40d1 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.37-next.0", + "version": "0.2.37-next.1", "private": false, "publishConfig": { "access": "public", @@ -34,8 +34,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,14 +48,14 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", - "@types/codemirror": "^0.0.109", + "@types/codemirror": "^5.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index a55bf5897d..ce5d19c142 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphql-backend +## 0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-graphql@0.3.9-next.0 + ## 0.1.22-next.0 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index 3abf17b87a..ec2ec2090c 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.22-next.0", + "version": "0.1.22-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,9 +34,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/config": "^1.0.0", - "@backstage/plugin-catalog-graphql": "^0.3.8", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", + "@backstage/plugin-catalog-graphql": "^0.3.9-next.0", "@graphql-tools/schema": "^8.3.1", "@types/express": "^4.17.6", "apollo-server": "^3.0.0", @@ -51,7 +51,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/supertest": "^2.0.8", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index b4989a2af6..97db023fc1 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-home +## 0.4.21-next.3 + +### Patch Changes + +- 69093c5f91: Display entity titles in `StarredEntities` home page card (if defined) and don't show entities which no longer exist +- Updated dependencies + - @backstage/core-components@0.9.4-next.2 + +## 0.4.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-stack-overflow@0.1.1-next.2 + ## 0.4.21-next.1 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index a59aa2b744..68a683dc31 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.4.21-next.1", + "version": "0.4.21-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,13 +34,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", - "@backstage/plugin-stack-overflow": "^0.1.1-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", + "@backstage/plugin-stack-overflow": "^0.1.1-next.2", "@backstage/theme": "^0.2.15", - "@backstage/config": "^1.0.0", + "@backstage/config": "^1.0.1-next.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/home/src/homePageComponents/StarredEntities/Content.test.tsx b/plugins/home/src/homePageComponents/StarredEntities/Content.test.tsx index 9087ed3605..2b9fae8221 100644 --- a/plugins/home/src/homePageComponents/StarredEntities/Content.test.tsx +++ b/plugins/home/src/homePageComponents/StarredEntities/Content.test.tsx @@ -15,6 +15,7 @@ */ import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { + catalogApiRef, starredEntitiesApiRef, MockStarredEntitiesApi, entityRouteRef, @@ -22,14 +23,44 @@ import { import React from 'react'; import { Content } from './Content'; +const entities = [ + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity-2', + title: 'Mock Starred Entity 2!', + }, + }, +]; + describe('StarredEntitiesContent', () => { - it('should render list of tools', async () => { + it('should render list of starred entities', async () => { const mockedApi = new MockStarredEntitiesApi(); mockedApi.toggleStarred('component:default/mock-starred-entity'); mockedApi.toggleStarred('component:default/mock-starred-entity-2'); + mockedApi.toggleStarred('component:default/mock-starred-entity-3'); - const { getByText } = await renderInTestApp( - + const mockCatalogApi = { + getEntities: jest + .fn() + .mockImplementation(async () => ({ items: entities })), + }; + + const { getByText, queryByText } = await renderInTestApp( + , { @@ -40,12 +71,13 @@ describe('StarredEntitiesContent', () => { ); expect(getByText('mock-starred-entity')).toBeInTheDocument(); - expect(getByText('mock-starred-entity-2')).toBeInTheDocument(); + expect(getByText('Mock Starred Entity 2!')).toBeInTheDocument(); + expect(queryByText('mock-starred-entity-3')).not.toBeInTheDocument(); expect(getByText('mock-starred-entity').closest('a')).toHaveAttribute( 'href', '/catalog/default/component/mock-starred-entity', ); - expect(getByText('mock-starred-entity-2').closest('a')).toHaveAttribute( + expect(getByText('Mock Starred Entity 2!').closest('a')).toHaveAttribute( 'href', '/catalog/default/component/mock-starred-entity-2', ); diff --git a/plugins/home/src/homePageComponents/StarredEntities/Content.tsx b/plugins/home/src/homePageComponents/StarredEntities/Content.tsx index e82d915e3b..31fa00378e 100644 --- a/plugins/home/src/homePageComponents/StarredEntities/Content.tsx +++ b/plugins/home/src/homePageComponents/StarredEntities/Content.tsx @@ -15,12 +15,14 @@ */ import { + catalogApiRef, useStarredEntities, + entityRouteParams, entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { parseEntityRef } from '@backstage/catalog-model'; -import { useRouteRef } from '@backstage/core-plugin-api'; -import { Link } from '@backstage/core-components'; +import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; +import { useApi, useRouteRef } from '@backstage/core-plugin-api'; +import { Link, Progress, ResponseErrorPanel } from '@backstage/core-components'; import { List, ListItem, @@ -32,6 +34,7 @@ import { } from '@material-ui/core'; import StarIcon from '@material-ui/icons/Star'; import React from 'react'; +import useAsync from 'react-use/lib/useAsync'; /** * A component to display a list of starred entities for the user. @@ -39,9 +42,37 @@ import React from 'react'; * @public */ export const Content = () => { + const catalogApi = useApi(catalogApiRef); const catalogEntityRoute = useRouteRef(entityRouteRef); const { starredEntities, toggleStarredEntity } = useStarredEntities(); + // Grab starred entities from catalog to ensure they still exist and also retrieve display titles + const entities = useAsync(async () => { + if (!starredEntities.size) { + return []; + } + + const filter = [...starredEntities] + .map(ent => parseEntityRef(ent)) + .map(ref => ({ + kind: ref.kind, + 'metadata.namespace': ref.namespace, + 'metadata.name': ref.name, + })); + + return ( + await catalogApi.getEntities({ + filter, + fields: [ + 'kind', + 'metadata.namespace', + 'metadata.name', + 'metadata.title', + ], + }) + ).items; + }, [catalogApi, starredEntities]); + if (starredEntities.size === 0) return ( @@ -49,26 +80,40 @@ export const Content = () => { ); - return ( + if (entities.loading) { + return ; + } + + return entities.error ? ( + + ) : ( - {Array.from(starredEntities).map(entity => ( - - - - - - - toggleStarredEntity(entity)} - > - - - - - - ))} + {entities.value + ?.sort((a, b) => + (a.metadata.title ?? a.metadata.name).localeCompare( + b.metadata.title ?? b.metadata.name, + ), + ) + .map(entity => ( + + + + + + + toggleStarredEntity(entity)} + > + + + + + + ))} ); }; diff --git a/plugins/home/src/homePageComponents/StarredEntities/StarredEntities.stories.tsx b/plugins/home/src/homePageComponents/StarredEntities/StarredEntities.stories.tsx index 1b01820482..a5e05e56c1 100644 --- a/plugins/home/src/homePageComponents/StarredEntities/StarredEntities.stories.tsx +++ b/plugins/home/src/homePageComponents/StarredEntities/StarredEntities.stories.tsx @@ -17,6 +17,7 @@ import { HomePageStarredEntities } from '../../plugin'; import { wrapInTestApp, TestApiProvider } from '@backstage/test-utils'; import { + catalogApiRef, starredEntitiesApiRef, MockStarredEntitiesApi, entityRouteRef, @@ -30,12 +31,56 @@ starredEntitiesApi.toggleStarred('component:default/example-starred-entity-2'); starredEntitiesApi.toggleStarred('component:default/example-starred-entity-3'); starredEntitiesApi.toggleStarred('component:default/example-starred-entity-4'); +const entities = [ + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity', + title: 'Mock Starred Entity!', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity-2', + title: 'Mock Starred Entity 2!', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity-3', + title: 'Mock Starred Entity 3!', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity-4', + title: 'Mock Starred Entity 4!', + }, + }, +]; + +const mockCatalogApi = { + getEntities: async () => ({ items: entities }), +}; + export default { title: 'Plugins/Home/Components/StarredEntities', decorators: [ (Story: ComponentType<{}>) => wrapInTestApp( - + , { diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index c2d5675ff5..d89b8132c2 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-ilert +## 0.1.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.1.31-next.1 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 149b135463..b40b2b9e0e 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.1.31-next.1", + "version": "0.1.31-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,11 +24,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@date-io/luxon": "1.x", "@material-ui/core": "^4.12.2", @@ -43,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index 10afcd6c33..e3d456650a 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-jenkins-backend +## 0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/catalog-client@1.0.2-next.0 + - @backstage/plugin-jenkins-common@0.1.4-next.0 + ## 0.1.22-next.0 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 861c7fddd6..ee1dc4fada 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins-backend", "description": "A Backstage backend plugin that integrates towards Jenkins", - "version": "0.1.22-next.0", + "version": "0.1.22-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,14 +25,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/catalog-client": "^1.0.1", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/catalog-client": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.1-next.0", - "@backstage/plugin-jenkins-common": "^0.1.3", - "@backstage/plugin-permission-common": "^0.6.0", + "@backstage/plugin-auth-node": "^0.2.1-next.1", + "@backstage/plugin-jenkins-common": "^0.1.4-next.0", + "@backstage/plugin-permission-common": "^0.6.1-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -41,7 +41,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/jenkins": "^0.23.1", "@types/supertest": "^2.0.8", "msw": "^0.35.0", diff --git a/plugins/jenkins-common/CHANGELOG.md b/plugins/jenkins-common/CHANGELOG.md index a5883d28f8..b47fb8b3a7 100644 --- a/plugins/jenkins-common/CHANGELOG.md +++ b/plugins/jenkins-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-jenkins-common +## 0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-catalog-common@1.0.2-next.0 + ## 0.1.3 ### Patch Changes diff --git a/plugins/jenkins-common/package.json b/plugins/jenkins-common/package.json index a8c04efef0..5e71854cf4 100644 --- a/plugins/jenkins-common/package.json +++ b/plugins/jenkins-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins-common", - "version": "0.1.3", + "version": "0.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,11 +22,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/plugin-catalog-common": "^1.0.1", - "@backstage/plugin-permission-common": "^0.6.0" + "@backstage/plugin-catalog-common": "^1.0.2-next.0", + "@backstage/plugin-permission-common": "^0.6.1-next.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0" + "@backstage/cli": "^0.17.1-next.2" }, "files": [ "dist" diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index f84dbdabcc..2f2b38f434 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-jenkins +## 0.7.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-jenkins-common@0.1.4-next.0 + ## 0.7.4-next.1 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 9b9be06bf8..f77afe86e5 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins", "description": "A Backstage plugin that integrates towards Jenkins", - "version": "0.7.4-next.1", + "version": "0.7.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,12 +35,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", - "@backstage/plugin-jenkins-common": "^0.1.3", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", + "@backstage/plugin-jenkins-common": "^0.1.4-next.0", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -54,10 +54,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index 61124c0c96..bafb8181b9 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-kafka-backend +## 0.2.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + ## 0.2.25-next.0 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index b3f3e0c880..68b8f24f59 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka-backend", "description": "A Backstage backend plugin that integrates towards Kafka", - "version": "0.2.25-next.0", + "version": "0.2.25-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,9 +35,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -47,7 +47,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/jest-when": "^3.5.0", "@types/lodash": "^4.14.151", "jest-when": "^3.1.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index 393b162761..ca0fe5925a 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-kafka +## 0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.3.5-next.1 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 73db72cbb3..e1c452496b 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.5-next.1", + "version": "0.3.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,10 +24,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -39,10 +39,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index d344d8c63d..cad2a5bcc3 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-kubernetes-backend +## 0.5.1-next.2 + +### Patch Changes + +- 447e060872: Add support for 'oidc' as authProvider for kubernetes authentication + and adds optional 'oidcTokenProvider' config value. This will allow + users to authenticate to kubernetes cluster using id tokens obtained + from the configured auth provider in their backstage instance. +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.2.10-next.1 + +## 0.5.1-next.1 + +### Patch Changes + +- 1ef98cfe48: add Azure Identity auth provider and AKS dashboard formatter +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-kubernetes-common@0.2.10-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + ## 0.5.1-next.0 ### Patch Changes diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 03682807e2..1a24e6e1cc 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -41,6 +41,7 @@ export interface ClusterDetails { dashboardParameters?: JsonObject; dashboardUrl?: string; name: string; + oidcTokenProvider?: string | undefined; // (undocumented) serviceAccountToken?: string | undefined; skipMetricsLookup?: boolean; diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 4d4cd8dfd0..8e2f143e7f 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.5.1-next.0", + "version": "0.5.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,11 +36,11 @@ }, "dependencies": { "@azure/identity": "^2.0.4", - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/plugin-kubernetes-common": "^0.2.9", + "@backstage/plugin-kubernetes-common": "^0.2.10-next.1", "@google-cloud/container": "^3.0.0", "@kubernetes/client-node": "^0.16.0", "@types/express": "^4.17.6", @@ -61,7 +61,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/aws4": "^1.5.1", "aws-sdk-mock": "^5.2.1", "supertest": "^6.1.3" diff --git a/plugins/kubernetes-backend/schema.d.ts b/plugins/kubernetes-backend/schema.d.ts index c2ac017713..fed243ef17 100644 --- a/plugins/kubernetes-backend/schema.d.ts +++ b/plugins/kubernetes-backend/schema.d.ts @@ -52,7 +52,14 @@ export interface Config { /** @visibility secret */ serviceAccountToken?: string; /** @visibility frontend */ - authProvider: 'aws' | 'google' | 'serviceAccount' | 'azure'; + authProvider: + | 'aws' + | 'google' + | 'serviceAccount' + | 'azure' + | 'oidc'; + /** @visibility frontend */ + oidcTokenProvider?: string; /** @visibility frontend */ skipTLSVerify?: boolean; }>; diff --git a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts index 5598740873..de5cac6d8d 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts @@ -64,6 +64,11 @@ export class ConfigClusterLocator implements KubernetesClustersSupplier { case 'azure': { return clusterDetails; } + case 'oidc': { + const oidcTokenProvider = c.getString('oidcTokenProvider'); + + return { oidcTokenProvider, ...clusterDetails }; + } case 'serviceAccount': { return clusterDetails; } diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.test.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.test.ts index 33592b1c41..b31443cdd1 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.test.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.test.ts @@ -19,6 +19,7 @@ import { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator import { KubernetesAuthTranslatorGenerator } from './KubernetesAuthTranslatorGenerator'; import { ServiceAccountKubernetesAuthTranslator } from './ServiceAccountKubernetesAuthTranslator'; import { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator'; +import { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator'; describe('getKubernetesAuthTranslatorInstance', () => { const sut = KubernetesAuthTranslatorGenerator; @@ -43,6 +44,12 @@ describe('getKubernetesAuthTranslatorInstance', () => { ).toBe(true); }); + it('can return an auth translator for oidc auth', () => { + const authTranslator: KubernetesAuthTranslator = + sut.getKubernetesAuthTranslatorInstance('oidc'); + expect(authTranslator instanceof OidcKubernetesAuthTranslator).toBe(true); + }); + it('throws an error when asked for an auth translator for an unsupported auth type', () => { expect(() => sut.getKubernetesAuthTranslatorInstance('linode')).toThrow( 'authProvider "linode" has no KubernetesAuthTranslator associated with it', diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts index e9a8a00ae9..4b17653359 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts @@ -20,6 +20,7 @@ import { ServiceAccountKubernetesAuthTranslator } from './ServiceAccountKubernet import { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator'; import { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider'; import { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator'; +import { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator'; export class KubernetesAuthTranslatorGenerator { static getKubernetesAuthTranslatorInstance( @@ -41,6 +42,9 @@ export class KubernetesAuthTranslatorGenerator { case 'googleServiceAccount': { return new GoogleServiceAccountAuthTranslator(); } + case 'oidc': { + return new OidcKubernetesAuthTranslator(); + } default: { throw new Error( `authProvider "${authProvider}" has no KubernetesAuthTranslator associated with it`, diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.test.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.test.ts new file mode 100644 index 0000000000..9f983aedc3 --- /dev/null +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.test.ts @@ -0,0 +1,67 @@ +/* + * 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 { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator'; +import { ClusterDetails } from '../types/types'; +import { Entity } from '@backstage/catalog-model'; + +describe('OidcKubernetesAuthTranslator tests', () => { + const at = new OidcKubernetesAuthTranslator(); + const entity: Entity = { + apiVersion: 'v1', + kind: 'service', + metadata: { name: 'test' }, + }; + const baseClusterDetails: ClusterDetails = { + name: 'test', + authProvider: 'oidc', + url: '', + }; + + it('returns cluster details with auth token', async () => { + const details = await at.decorateClusterDetailsWithAuth( + { + oidcTokenProvider: 'okta', + ...baseClusterDetails, + }, + { + auth: { + oidc: { okta: 'fakeToken' }, + }, + entity, + }, + ); + + expect(details.serviceAccountToken).toBe('fakeToken'); + }); + + it('returns error when oidcTokenProvider is not configured', async () => { + await expect( + at.decorateClusterDetailsWithAuth(baseClusterDetails, { entity }), + ).rejects.toThrow( + 'oidc authProvider requires a configured oidcTokenProvider', + ); + }); + + it('returns error when token is not included in request body', async () => { + await expect( + at.decorateClusterDetailsWithAuth( + { oidcTokenProvider: 'okta', ...baseClusterDetails }, + { entity }, + ), + ).rejects.toThrow('Auth token not found under oidc.okta in request body'); + }); +}); diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts new file mode 100644 index 0000000000..c53269abf3 --- /dev/null +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { KubernetesAuthTranslator } from './types'; +import { ClusterDetails } from '../types/types'; +import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; + +export class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator { + async decorateClusterDetailsWithAuth( + clusterDetails: ClusterDetails, + requestBody: KubernetesRequestBody, + ): Promise { + const clusterDetailsWithAuthToken: ClusterDetails = Object.assign( + {}, + clusterDetails, + ); + + const { oidcTokenProvider } = clusterDetails; + + if (!oidcTokenProvider || oidcTokenProvider === '') { + throw new Error( + `oidc authProvider requires a configured oidcTokenProvider`, + ); + } + + const authToken: string | undefined = + requestBody.auth?.oidc?.[oidcTokenProvider]; + + if (authToken) { + clusterDetailsWithAuthToken.serviceAccountToken = authToken; + } else { + throw new Error( + `Auth token not found under oidc.${oidcTokenProvider} in request body`, + ); + } + return clusterDetailsWithAuthToken; + } +} diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index a3dfc8b005..18c3fdc931 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -246,6 +246,7 @@ export class KubernetesBuilder { name: cd.name, dashboardUrl: cd.dashboardUrl, authProvider: cd.authProvider, + oidcTokenProvider: cd.oidcTokenProvider, })), }); }); diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index 706582f439..e8665c57eb 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -105,6 +105,10 @@ export interface ClusterDetails { url: string; authProvider: string; serviceAccountToken?: string | undefined; + /** + * oidc provider used to get id tokens to authenticate against kubernetes + */ + oidcTokenProvider?: string | undefined; skipTLSVerify?: boolean; /** * Whether to skip the lookup to the metrics server to retrieve pod resource usage. diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index 790cc9d3a7..cdc209f88f 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-kubernetes-common +## 0.2.10-next.1 + +### Patch Changes + +- 447e060872: Add support for 'oidc' as authProvider for kubernetes authentication + and adds optional 'oidcTokenProvider' config value. This will allow + users to authenticate to kubernetes cluster using id tokens obtained + from the configured auth provider in their backstage instance. + +## 0.2.10-next.0 + +### Patch Changes + +- 1ef98cfe48: add Azure Identity auth provider and AKS dashboard formatter +- Updated dependencies + - @backstage/catalog-model@1.0.2-next.0 + ## 0.2.9 ### Patch Changes diff --git a/plugins/kubernetes-common/api-report.md b/plugins/kubernetes-common/api-report.md index 639c3f63c2..e6f96fa253 100644 --- a/plugins/kubernetes-common/api-report.md +++ b/plugins/kubernetes-common/api-report.md @@ -195,6 +195,9 @@ export interface KubernetesRequestBody { // (undocumented) auth?: { google?: string; + oidc?: { + [key: string]: string; + }; }; // (undocumented) entity: Entity; diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index e9158e640a..d250e82780 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.2.9", + "version": "0.2.10-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,11 +38,11 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", + "@backstage/catalog-model": "^1.0.2-next.0", "@kubernetes/client-node": "^0.16.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0" + "@backstage/cli": "^0.17.1-next.2" }, "jest": { "roots": [ diff --git a/plugins/kubernetes-common/src/types.ts b/plugins/kubernetes-common/src/types.ts index cb388bad0a..9b7c89bbd0 100644 --- a/plugins/kubernetes-common/src/types.ts +++ b/plugins/kubernetes-common/src/types.ts @@ -31,6 +31,9 @@ import { Entity } from '@backstage/catalog-model'; export interface KubernetesRequestBody { auth?: { google?: string; + oidc?: { + [key: string]: string; + }; }; entity: Entity; } diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 628036cf01..dda45a0409 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-kubernetes +## 0.6.5-next.3 + +### Patch Changes + +- 447e060872: Add support for 'oidc' as authProvider for kubernetes authentication + and adds optional 'oidcTokenProvider' config value. This will allow + users to authenticate to kubernetes cluster using id tokens obtained + from the configured auth provider in their backstage instance. +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.2.10-next.1 + - @backstage/core-components@0.9.4-next.2 + +## 0.6.5-next.2 + +### Patch Changes + +- 1ef98cfe48: add Azure Identity auth provider and AKS dashboard formatter +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-kubernetes-common@0.2.10-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.6.5-next.1 ### Patch Changes diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md index e8a3da83a9..99bee06165 100644 --- a/plugins/kubernetes/api-report.md +++ b/plugins/kubernetes/api-report.md @@ -17,6 +17,7 @@ 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 { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { V1ConfigMap } from '@kubernetes/client-node'; @@ -225,6 +226,7 @@ export interface KubernetesApi { { name: string; authProvider: string; + oidcTokenProvider?: string | undefined; }[] >; // (undocumented) @@ -242,7 +244,12 @@ export const kubernetesApiRef: ApiRef; // // @public (undocumented) export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { - constructor(options: { googleAuthApi: OAuthApi }); + constructor(options: { + googleAuthApi: OAuthApi; + oidcProviders?: { + [key: string]: OpenIdConnectApi; + }; + }); // (undocumented) decorateRequestBodyForAuth( authProvider: string, diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 5309aefe49..61885408e8 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.6.5-next.1", + "version": "0.6.5-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,12 +34,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", - "@backstage/plugin-kubernetes-common": "^0.2.9", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", + "@backstage/plugin-kubernetes-common": "^0.2.10-next.1", "@backstage/theme": "^0.2.15", "@kubernetes/client-node": "^0.16.0", "@material-ui/core": "^4.12.2", @@ -57,10 +57,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/kubernetes/src/api/types.ts b/plugins/kubernetes/src/api/types.ts index 8b95dd820c..7c5943a6eb 100644 --- a/plugins/kubernetes/src/api/types.ts +++ b/plugins/kubernetes/src/api/types.ts @@ -28,5 +28,11 @@ export interface KubernetesApi { getObjectsByEntity( requestBody: KubernetesRequestBody, ): Promise; - getClusters(): Promise<{ name: string; authProvider: string }[]>; + getClusters(): Promise< + { + name: string; + authProvider: string; + oidcTokenProvider?: string | undefined; + }[] + >; } diff --git a/plugins/kubernetes/src/hooks/useKubernetesObjects.ts b/plugins/kubernetes/src/hooks/useKubernetesObjects.ts index d9aca875c7..8e2597c1d2 100644 --- a/plugins/kubernetes/src/hooks/useKubernetesObjects.ts +++ b/plugins/kubernetes/src/hooks/useKubernetesObjects.ts @@ -53,8 +53,16 @@ export const useKubernetesObjects = ( } const authProviders: string[] = [ - ...new Set(clusters.map(c => c.authProvider)), + ...new Set( + clusters.map( + c => + `${c.authProvider}${ + c.oidcTokenProvider ? `.${c.oidcTokenProvider}` : '' + }`, + ), + ), ]; + // For each auth type, invoke decorateRequestBodyForAuth on corresponding KubernetesAuthProvider let requestBody: KubernetesRequestBody = { entity, diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts b/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts new file mode 100644 index 0000000000..a83cbcfaa4 --- /dev/null +++ b/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts @@ -0,0 +1,79 @@ +/* + * 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 { OAuthApi, OpenIdConnectApi } from '@backstage/core-plugin-api'; +import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; +import { KubernetesAuthProviders } from './KubernetesAuthProviders'; + +class MockAuthApi implements OAuthApi, OpenIdConnectApi { + constructor(private readonly token: string) {} + + getAccessToken = jest.fn(async () => { + return this.token; + }); + + getIdToken = jest.fn(async () => { + return this.token; + }); +} + +const requestBody: KubernetesRequestBody = { + entity: { + apiVersion: 'v1', + kind: 'service', + metadata: { name: 'test' }, + }, +}; + +describe('KubernetesAuthProviders tests', () => { + const kap = new KubernetesAuthProviders({ + googleAuthApi: new MockAuthApi('googleToken'), + oidcProviders: { + okta: new MockAuthApi('oktaToken'), + }, + }); + + it('adds token to request body for google authProvider', async () => { + const details = await kap.decorateRequestBodyForAuth('google', requestBody); + + expect(details.auth?.google).toBe('googleToken'); + }); + + it('adds token to request body for oidc authProvider', async () => { + const details = await kap.decorateRequestBodyForAuth( + 'oidc.okta', + requestBody, + ); + + expect(details.auth?.oidc?.okta).toBe('oktaToken'); + }); + + it('returns error for unknown authProvider', async () => { + await expect( + kap.decorateRequestBodyForAuth('unknown', requestBody), + ).rejects.toThrow( + 'authProvider "unknown" has no KubernetesAuthProvider defined for it', + ); + }); + + it('returns error for missconfigured oidc authProvider', async () => { + await expect( + kap.decorateRequestBodyForAuth('oidc.random', requestBody), + ).rejects.toThrow( + 'KubernetesAuthProviders has no oidcProvider configured for oidc.random', + ); + }); +}); diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts b/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts index 00d5a17f72..bcd1b2911a 100644 --- a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts +++ b/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts @@ -19,9 +19,10 @@ import { KubernetesAuthProvider, KubernetesAuthProvidersApi } from './types'; import { GoogleKubernetesAuthProvider } from './GoogleKubernetesAuthProvider'; import { ServiceAccountKubernetesAuthProvider } from './ServiceAccountKubernetesAuthProvider'; import { AwsKubernetesAuthProvider } from './AwsKubernetesAuthProvider'; -import { OAuthApi } from '@backstage/core-plugin-api'; +import { OAuthApi, OpenIdConnectApi } from '@backstage/core-plugin-api'; import { GoogleServiceAccountAuthProvider } from './GoogleServiceAccountAuthProvider'; import { AzureKubernetesAuthProvider } from './AzureKubernetesAuthProvider'; +import { OidcKubernetesAuthProvider } from './OidcKubernetesAuthProvider'; export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { private readonly kubernetesAuthProviderMap: Map< @@ -29,7 +30,10 @@ export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { KubernetesAuthProvider >; - constructor(options: { googleAuthApi: OAuthApi }) { + constructor(options: { + googleAuthApi: OAuthApi; + oidcProviders?: { [key: string]: OpenIdConnectApi }; + }) { this.kubernetesAuthProviderMap = new Map(); this.kubernetesAuthProviderMap.set( 'google', @@ -48,6 +52,18 @@ export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { 'azure', new AzureKubernetesAuthProvider(), ); + + if (options.oidcProviders) { + Object.keys(options.oidcProviders).forEach(provider => { + this.kubernetesAuthProviderMap.set( + `oidc.${provider}`, + new OidcKubernetesAuthProvider( + provider, + options.oidcProviders![provider], + ), + ); + }); + } } async decorateRequestBodyForAuth( @@ -61,6 +77,12 @@ export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { requestBody, ); } + + if (authProvider.startsWith('oidc.')) { + throw new Error( + `KubernetesAuthProviders has no oidcProvider configured for ${authProvider}`, + ); + } throw new Error( `authProvider "${authProvider}" has no KubernetesAuthProvider defined for it`, ); diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts b/plugins/kubernetes/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts new file mode 100644 index 0000000000..f86df5e73e --- /dev/null +++ b/plugins/kubernetes/src/kubernetes-auth-provider/OidcKubernetesAuthProvider.ts @@ -0,0 +1,43 @@ +/* + * 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 { KubernetesAuthProvider } from './types'; +import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; +import { OpenIdConnectApi } from '@backstage/core-plugin-api'; + +export class OidcKubernetesAuthProvider implements KubernetesAuthProvider { + providerName: string; + authProvider: OpenIdConnectApi; + + constructor(providerName: string, authProvider: OpenIdConnectApi) { + this.providerName = providerName; + this.authProvider = authProvider; + } + + async decorateRequestBodyForAuth( + requestBody: KubernetesRequestBody, + ): Promise { + const authToken: string = await this.authProvider.getIdToken(); + const auth = { ...requestBody.auth }; + if (auth.oidc) { + auth.oidc[this.providerName] = authToken; + } else { + auth.oidc = { [this.providerName]: authToken }; + } + requestBody.auth = auth; + return requestBody; + } +} diff --git a/plugins/kubernetes/src/plugin.ts b/plugins/kubernetes/src/plugin.ts index a1f2f57621..b54850307e 100644 --- a/plugins/kubernetes/src/plugin.ts +++ b/plugins/kubernetes/src/plugin.ts @@ -24,6 +24,9 @@ import { discoveryApiRef, identityApiRef, googleAuthApiRef, + microsoftAuthApiRef, + oktaAuthApiRef, + oneloginAuthApiRef, createRoutableExtension, } from '@backstage/core-plugin-api'; @@ -45,9 +48,26 @@ export const kubernetesPlugin = createPlugin({ }), createApiFactory({ api: kubernetesAuthProvidersApiRef, - deps: { googleAuthApi: googleAuthApiRef }, - factory: ({ googleAuthApi }) => { - return new KubernetesAuthProviders({ googleAuthApi }); + deps: { + googleAuthApi: googleAuthApiRef, + microsoftAuthApi: microsoftAuthApiRef, + oktaAuthApi: oktaAuthApiRef, + oneloginAuthApi: oneloginAuthApiRef, + }, + factory: ({ + googleAuthApi, + microsoftAuthApi, + oktaAuthApi, + oneloginAuthApi, + }) => { + const oidcProviders = { + google: googleAuthApi, + microsoft: microsoftAuthApi, + okta: oktaAuthApi, + onelogin: oneloginAuthApi, + }; + + return new KubernetesAuthProviders({ googleAuthApi, oidcProviders }); }, }), ], diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index ce6a6b092d..82e7b72aa4 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-lighthouse +## 0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.3.5-next.1 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 7df7f321ad..59aca403ac 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.3.5-next.1", + "version": "0.3.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,11 +35,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -51,10 +51,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index f099f3a762..627b1ecb5d 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-newrelic-dashboard +## 0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.1.13-next.1 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index be2d59a8d0..a8ca2bd9e6 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.1.13-next.1", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,19 +23,19 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/dev-utils": "^1.0.2-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/dev-utils": "^1.0.2-next.2", "@testing-library/jest-dom": "^5.10.1", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5" diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 94970c0b41..d0d8e66787 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -35,8 +35,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,10 +47,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 81b9b6be6c..7a99844dea 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-org +## 0.5.5-next.3 + +### Patch Changes + +- 2025d7c123: Include namespace in `MyGroupSidebarItem` if not default and remove root item routing if there are multiple groups +- Updated dependencies + - @backstage/core-components@0.9.4-next.2 + +## 0.5.5-next.2 + +### Patch Changes + +- dfee1002d7: Fixed overflow bug of name and email on EntitiyMembersListCard component which can occur on specific 'screen width' + ’character length' combinations +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.5.5-next.1 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 612410dc7a..1eba133f18 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.5.5-next.1", + "version": "0.5.5-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,10 +29,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,11 +48,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/catalog-client": "^1.0.1", - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/catalog-client": "^1.0.2-next.0", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx index 14f02c189f..7e5b683bf1 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx @@ -59,6 +59,17 @@ const useStyles = makeStyles((theme: Theme) => flex: '1', minWidth: '0px', }, + email: { + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + display: 'inline-block', + maxWidth: '100%', + '&:hover': { + overflow: 'visible', + whiteSpace: 'normal', + }, + }, }), ); @@ -88,7 +99,13 @@ const MemberComponent = (props: { member: UserEntity }) => { top: '-2rem', }} /> - + { {profile?.email && ( - {profile.email} + + {profile.email} + )} {description && ( {description} diff --git a/plugins/org/src/components/MyGroupsSidebarItem/MyGroupsSidebarItem.tsx b/plugins/org/src/components/MyGroupsSidebarItem/MyGroupsSidebarItem.tsx index c2473670cf..5a3cc42628 100644 --- a/plugins/org/src/components/MyGroupsSidebarItem/MyGroupsSidebarItem.tsx +++ b/plugins/org/src/components/MyGroupsSidebarItem/MyGroupsSidebarItem.tsx @@ -15,6 +15,7 @@ */ import React from 'react'; +import { stringifyEntityRef } from '@backstage/catalog-model'; import { SidebarItem, SidebarSubmenu, @@ -31,6 +32,7 @@ import { catalogApiRef, CatalogApi, entityRouteRef, + humanizeEntityRef, } from '@backstage/plugin-catalog-react'; import { getCompoundEntityRef } from '@backstage/catalog-model'; @@ -80,15 +82,18 @@ export const MyGroupsSidebarItem = (props: { // Member of more than one group return ( - + {groups?.map(function groupsMap(group) { return ( ); })} diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index cb178cfa3d..06158d356b 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-pagerduty +## 0.3.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.3.32-next.1 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 522147ab4f..35e6ecefa9 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.3.32-next.1", + "version": "0.3.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,10 +34,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -52,10 +52,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index 0370c59212..fc39ac9107 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-periskop-backend +## 0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + ## 0.1.3-next.0 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index 335546a6aa..07e26f21bf 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.1.3-next.0", + "version": "0.1.3-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,8 +24,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@types/express": "*", "cross-fetch": "^3.0.6", "express": "^4.17.1", @@ -35,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/supertest": "^2.0.8", "msw": "^0.35.0", "supertest": "^6.1.6" diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index 60a49881c5..f0d3e996a8 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-periskop +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.1.3-next.1 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 177e53b4bf..804baccc84 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.3-next.1", + "version": "0.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,11 +25,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,10 +42,10 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index c73248ac4e..f6159ce2e5 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-backend +## 0.5.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-permission-node@0.6.1-next.1 + ## 0.5.7-next.0 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 404f287669..79ecee9d3c 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.7-next.0", + "version": "0.5.7-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,12 +22,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.1-next.0", - "@backstage/plugin-permission-common": "^0.6.0", - "@backstage/plugin-permission-node": "^0.6.1-next.0", + "@backstage/plugin-auth-node": "^0.2.1-next.1", + "@backstage/plugin-permission-common": "^0.6.1-next.0", + "@backstage/plugin-permission-node": "^0.6.1-next.1", "@types/express": "*", "dataloader": "^2.0.0", "express": "^4.17.1", @@ -39,7 +39,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", "supertest": "^6.1.6", diff --git a/plugins/permission-common/CHANGELOG.md b/plugins/permission-common/CHANGELOG.md index 99c996d2c0..6eedf4e060 100644 --- a/plugins/permission-common/CHANGELOG.md +++ b/plugins/permission-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-permission-common +## 0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + ## 0.6.0 ### Minor Changes diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index 43084f9ab9..195b3f4441 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-common", "description": "Isomorphic types and client for Backstage permissions and authorization", - "version": "0.6.0", + "version": "0.6.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -41,14 +41,14 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/config": "^1.0.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", "cross-fetch": "^3.1.5", "uuid": "^8.0.0", "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/jest": "^26.0.7", "msw": "^0.35.0" } diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 25973b1d52..cc3dceedaa 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-permission-node +## 0.6.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + ## 0.6.1-next.0 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index d9dfec1859..18b64aca8f 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.6.1-next.0", + "version": "0.6.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,18 +33,18 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.1-next.0", - "@backstage/plugin-permission-common": "^0.6.0", + "@backstage/plugin-auth-node": "^0.2.1-next.1", + "@backstage/plugin-permission-common": "^0.6.1-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/supertest": "^2.0.8", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index fdcdbb8f69..5cc01341b1 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-permission-react +## 0.4.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + ## 0.4.1-next.0 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index de9709835e..9aa1415661 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.4.1-next.0", + "version": "0.4.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^1.0.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-permission-common": "^0.6.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-permission-common": "^0.6.1-next.0", "cross-fetch": "^3.1.5", "react-router": "6.0.0-beta.0", "react-use": "^17.2.4", @@ -44,8 +44,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@types/jest": "^26.0.7" diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 27a8fc1df1..58badecc4f 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-proxy-backend +## 0.2.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + ## 0.2.26-next.0 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 47b466e0fc..cb1de16e46 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.2.26-next.0", + "version": "0.2.26-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -46,7 +46,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index bd4dfd9bef..142e12051e 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-rollbar-backend +## 0.1.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + ## 0.1.29-next.1 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 120a3ab3db..798f023159 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.29-next.1", + "version": "0.1.29-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,8 +34,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@types/express": "^4.17.6", "camelcase-keys": "^7.0.1", "compression": "^1.7.4", @@ -50,8 +50,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.24-next.0", - "@backstage/cli": "^0.17.1-next.1", + "@backstage/backend-test-utils": "^0.1.24-next.1", + "@backstage/cli": "^0.17.1-next.2", "@types/supertest": "^2.0.8", "msw": "^0.36.3", "supertest": "^6.1.3" diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index b10f6f7a46..9697729d16 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-rollbar +## 0.4.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.4.5-next.1 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 4d68bd1e35..2b6056b6e6 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.5-next.1", + "version": "0.4.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,10 +35,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -53,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index fdf79fd08f..dfd7157d40 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-scaffolder-backend@1.2.0-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/integration@1.2.0-next.1 + ## 0.2.7-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index b196b4da99..417ba83eb5 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.7-next.0", + "version": "0.2.7-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,11 +23,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", + "@backstage/backend-common": "^0.13.3-next.2", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/plugin-scaffolder-backend": "^1.2.0-next.0", - "@backstage/config": "^1.0.0", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/plugin-scaffolder-backend": "^1.2.0-next.1", + "@backstage/config": "^1.0.1-next.0", "@backstage/types": "^1.0.0", "command-exists": "^1.2.9", "fs-extra": "10.1.0", @@ -35,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", "@types/jest": "^26.0.7", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index 3057cd94dc..7b514833cd 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.0-next.1 + +### Minor Changes + +- 3d001a3bcf: **BREAKING**: Added a new `allowedImageNames` option, which needs to list any image name for it to be allowed as `imageName` input. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-scaffolder-backend@1.2.0-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/integration@1.2.0-next.1 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 226d4c0420..171ff66d49 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.3.7-next.0", + "version": "0.4.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,17 +24,17 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/plugin-scaffolder-backend": "^1.2.0-next.0", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/plugin-scaffolder-backend": "^1.2.0-next.1", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", + "@backstage/integration": "^1.2.0-next.1", "@backstage/types": "^1.0.0", "command-exists": "^1.2.9", "fs-extra": "^10.0.1" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "@types/command-exists": "^1.2.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index bc7c0f5b55..1790e0468d 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.2.0-next.1 + - @backstage/config@1.0.1-next.0 + ## 0.2.5-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 10371e89af..534eda3c1f 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.5-next.0", + "version": "0.2.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,14 +23,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.0", - "@backstage/plugin-scaffolder-backend": "^1.2.0-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/plugin-scaffolder-backend": "^1.2.0-next.1", "@backstage/types": "^1.0.0", "winston": "^3.2.1", "yeoman-environment": "^3.9.1" }, "devDependencies": { - "@backstage/backend-common": "^0.13.3-next.0", + "@backstage/backend-common": "^0.13.3-next.2", "@types/jest": "^26.0.7" }, "files": [ diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index bf4a9718f0..4d90344c16 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-scaffolder-backend +## 1.2.0-next.1 + +### Minor Changes + +- f8baf7df44: Added the ability to reference the user in the `template.yaml` manifest + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-catalog-backend@1.1.2-next.2 + - @backstage/plugin-scaffolder-common@1.1.0-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/catalog-client@1.0.2-next.0 + ## 1.2.0-next.0 ### Minor Changes diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 1bc8a27f54..7cf26aa473 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -342,6 +342,7 @@ export type CreateWorkerOptions = { // @public export interface CurrentClaimedTask { + createdBy?: string; secrets?: TaskSecrets; spec: TaskSpec; taskId: string; @@ -476,6 +477,7 @@ export type SerializedTask = { status: TaskStatus; createdAt: string; lastHeartbeatAt?: string; + createdBy?: string; secrets?: TaskSecrets; }; @@ -510,6 +512,7 @@ export interface TaskBroker { export type TaskBrokerDispatchOptions = { spec: TaskSpec; secrets?: TaskSecrets; + createdBy?: string; }; // @public @@ -525,6 +528,8 @@ export interface TaskContext { // (undocumented) complete(result: TaskCompletionState, metadata?: JsonObject): Promise; // (undocumented) + createdBy?: string; + // (undocumented) done: boolean; // (undocumented) emitLog(message: string, logMetadata?: JsonObject): Promise; @@ -550,6 +555,8 @@ export class TaskManager implements TaskContext { logger: Logger, ): TaskManager; // (undocumented) + get createdBy(): string | undefined; + // (undocumented) get done(): boolean; // (undocumented) emitLog(message: string, logMetadata?: JsonObject): Promise; @@ -609,6 +616,7 @@ export interface TaskStore { // @public export type TaskStoreCreateTaskOptions = { spec: TaskSpec; + createdBy?: string; secrets?: TaskSecrets; }; diff --git a/plugins/scaffolder-backend/migrations/20220129100000_created_by.js b/plugins/scaffolder-backend/migrations/20220129100000_created_by.js new file mode 100644 index 0000000000..3391a883c2 --- /dev/null +++ b/plugins/scaffolder-backend/migrations/20220129100000_created_by.js @@ -0,0 +1,38 @@ +/* + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('tasks', table => { + table + .text('created_by') + .nullable() + .comment('An entityRef of the user who created the task'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('tasks', table => { + table.dropColumn('created_by'); + }); +}; diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index d9492902d0..82c1320725 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.2.0-next.0", + "version": "1.2.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,14 +34,14 @@ "build:assets": "node scripts/build-nunjucks.js" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/catalog-client": "^1.0.1", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/catalog-client": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/plugin-catalog-backend": "^1.1.2-next.0", - "@backstage/plugin-scaffolder-common": "^1.0.1", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/plugin-catalog-backend": "^1.1.2-next.2", + "@backstage/plugin-scaffolder-common": "^1.1.0-next.0", "@backstage/types": "^1.0.0", "@gitbeaker/core": "^35.6.0", "@gitbeaker/node": "^35.1.0", @@ -74,8 +74,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.24-next.0", - "@backstage/cli": "^0.17.1-next.0", + "@backstage/backend-test-utils": "^0.1.24-next.1", + "@backstage/cli": "^0.17.1-next.2", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index 9fef68529f..d0a0fec0a6 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -43,6 +43,7 @@ export type RawDbTaskRow = { status: TaskStatus; last_heartbeat_at?: string; created_at: string; + created_by: string | null; secrets?: string | null; }; @@ -100,6 +101,7 @@ export class DatabaseTaskStore implements TaskStore { status: result.status, lastHeartbeatAt: result.last_heartbeat_at, createdAt: result.created_at, + createdBy: result.created_by ?? undefined, secrets, }; } catch (error) { @@ -115,6 +117,7 @@ export class DatabaseTaskStore implements TaskStore { id: taskId, spec: JSON.stringify(options.spec), secrets: options.secrets ? JSON.stringify(options.secrets) : undefined, + created_by: options.createdBy ?? null, status: 'open', }); return { taskId }; @@ -155,6 +158,7 @@ export class DatabaseTaskStore implements TaskStore { status: 'processing', lastHeartbeatAt: task.last_heartbeat_at, createdAt: task.created_at, + createdBy: task.created_by ?? undefined, secrets, }; } catch (error) { diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 0ef0846ddb..6b1701380b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -24,6 +24,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { TaskContext, TaskSecrets } from './types'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; +import { UserEntity } from '@backstage/catalog-model'; // The Stream module is lazy loaded, so make sure it's in the module cache before mocking fs void winston.transports.Stream; @@ -558,6 +559,36 @@ describe('DefaultWorkflowRunner', () => { }); }); + describe('user', () => { + it('allows access to the user entity at the templating level', async () => { + const task = createMockTaskWithSpec({ + apiVersion: 'scaffolder.backstage.io/v1beta3', + steps: [ + { + id: 'test', + name: 'name', + action: 'output-action', + input: {}, + }, + ], + user: { + entity: { metadata: { name: 'bob' } } as UserEntity, + ref: 'user:default/guest', + }, + output: { + foo: '${{ user.entity.metadata.name }} ${{ user.ref }}', + }, + parameters: { + repoUrl: 'github.com?repo=repo&owner=owner', + }, + }); + + const { output } = await runner.execute(task); + + expect(output.foo).toEqual('bob user:default/guest'); + }); + }); + describe('filters', () => { it('provides the parseRepoUrl filter', async () => { const task = createMockTaskWithSpec({ diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 0bd5a3c840..c9d0714392 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -37,6 +37,7 @@ import { TaskSpecV1beta3, TaskStep, } from '@backstage/plugin-scaffolder-common'; +import { UserEntity } from '@backstage/catalog-model'; type NunjucksWorkflowRunnerOptions = { workingDirectory: string; @@ -52,6 +53,10 @@ type TemplateContext = { [stepName: string]: { output: { [outputName: string]: JsonValue } }; }; secrets?: Record; + user?: { + entity?: UserEntity; + ref?: string; + }; }; const isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => { @@ -203,6 +208,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { const context: TemplateContext = { parameters: task.spec.parameters, steps: {}, + user: task.spec.user, }; for (const step of task.spec.steps) { diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index a92d6abdb8..17f07f702d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -59,6 +59,10 @@ export class TaskManager implements TaskContext { return this.task.secrets; } + get createdBy() { + return this.task.createdBy; + } + async getWorkspaceName() { return this.task.taskId; } @@ -127,6 +131,10 @@ export interface CurrentClaimedTask { * The secrets that are stored with the task. */ secrets?: TaskSecrets; + /** + * The creator of the task. + */ + createdBy?: string; } function defer() { @@ -156,6 +164,7 @@ export class StorageTaskBroker implements TaskBroker { taskId: pendingTask.id, spec: pendingTask.spec, secrets: pendingTask.secrets, + createdBy: pendingTask.createdBy, }, this.storage, this.logger, diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index 2af98b111b..a3a9ef84d1 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -47,6 +47,7 @@ export type SerializedTask = { status: TaskStatus; createdAt: string; lastHeartbeatAt?: string; + createdBy?: string; secrets?: TaskSecrets; }; @@ -97,6 +98,7 @@ export type TaskBrokerDispatchResult = { export type TaskBrokerDispatchOptions = { spec: TaskSpec; secrets?: TaskSecrets; + createdBy?: string; }; /** @@ -107,6 +109,7 @@ export type TaskBrokerDispatchOptions = { export interface TaskContext { spec: TaskSpec; secrets?: TaskSecrets; + createdBy?: string; done: boolean; emitLog(message: string, logMetadata?: JsonObject): Promise; complete(result: TaskCompletionState, metadata?: JsonObject): Promise; @@ -157,6 +160,7 @@ export type TaskStoreListEventsOptions = { */ export type TaskStoreCreateTaskOptions = { spec: TaskSpec; + createdBy?: string; secrets?: TaskSecrets; }; diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 6caed7b0cb..14c543249e 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -48,12 +48,11 @@ import request from 'supertest'; */ import { createRouter, DatabaseTaskStore, TaskBroker } from '../index'; import { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker'; -import { stringifyEntityRef } from '@backstage/catalog-model'; - -const createCatalogClient = (template: any) => - ({ - getEntityByRef: async () => template, - } as unknown as CatalogApi); +import { + parseEntityRef, + stringifyEntityRef, + UserEntity, +} from '@backstage/catalog-model'; function createDatabase(): PluginDatabaseManager { return DatabaseManager.fromConfig( @@ -76,7 +75,9 @@ const mockUrlReader = UrlReaders.default({ describe('createRouter', () => { let app: express.Express; let taskBroker: TaskBroker; - const template: TemplateEntityV1beta3 = { + const catalogClient = { getEntityByRef: jest.fn() } as unknown as CatalogApi; + + const mockTemplate: TemplateEntityV1beta3 = { apiVersion: 'scaffolder.backstage.io/v1beta3', kind: 'Template', metadata: { @@ -105,6 +106,22 @@ describe('createRouter', () => { }, }; + const mockUser: UserEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'guest', + annotations: { + 'google.com/email': 'bobby@tables.com', + }, + }, + spec: { + profile: { + displayName: 'Robert Tables of the North', + }, + }, + }; + beforeEach(async () => { const logger = getVoidLogger(); const databaseTaskStore = await DatabaseTaskStore.create({ @@ -120,11 +137,26 @@ describe('createRouter', () => { logger: getVoidLogger(), config: new ConfigReader({}), database: createDatabase(), - catalogClient: createCatalogClient(template), + catalogClient, reader: mockUrlReader, taskBroker, }); app = express().use(router); + + jest + .spyOn(catalogClient, 'getEntityByRef') + .mockImplementation(async ref => { + const { kind } = parseEntityRef(ref); + + if (kind === 'template') { + return mockTemplate; + } + + if (kind === 'user') { + return mockUser; + } + throw new Error(`no mock found for kind: ${kind}`); + }); }); afterEach(() => { @@ -158,9 +190,8 @@ describe('createRouter', () => { }); it('return the template id', async () => { - ( - taskBroker.dispatch as jest.Mocked['dispatch'] - ).mockResolvedValue({ + const broker = taskBroker.dispatch as jest.Mocked['dispatch']; + broker.mockResolvedValue({ taskId: 'a-random-id', }); @@ -179,6 +210,88 @@ describe('createRouter', () => { expect(response.body.id).toBe('a-random-id'); expect(response.status).toEqual(201); }); + + it('should call the broker with a correct spec', async () => { + const broker = taskBroker.dispatch as jest.Mocked['dispatch']; + const mockToken = + 'blob.eyJzdWIiOiJ1c2VyOmRlZmF1bHQvZ3Vlc3QiLCJuYW1lIjoiSm9obiBEb2UifQ.blob'; + + console.log( + JSON.stringify( + await request(app) + .post('/v2/tasks') + .set('Authorization', `Bearer ${mockToken}`) + .send({ + templateRef: stringifyEntityRef({ + kind: 'template', + name: 'create-react-app-template', + }), + values: { + required: 'required-value', + }, + }), + ), + ); + + expect(broker).toHaveBeenCalledWith( + expect.objectContaining({ + createdBy: 'user:default/guest', + secrets: { + backstageToken: mockToken, + }, + + spec: { + apiVersion: mockTemplate.apiVersion, + steps: mockTemplate.spec.steps.map((step, index) => ({ + ...step, + id: step.id ?? `step-${index + 1}`, + name: step.name ?? step.action, + })), + output: mockTemplate.spec.output ?? {}, + parameters: { + required: 'required-value', + }, + user: { + entity: mockUser, + ref: 'user:default/guest', + }, + templateInfo: { + entityRef: stringifyEntityRef({ + kind: 'Template', + namespace: 'Default', + name: mockTemplate.metadata?.name, + }), + baseUrl: 'https://dev.azure.com', + }, + }, + }), + ); + }); + + it('should not decorate a user when no backstage auth is passed', async () => { + const broker = taskBroker.dispatch as jest.Mocked['dispatch']; + + await request(app) + .post('/v2/tasks') + .send({ + templateRef: stringifyEntityRef({ + kind: 'template', + name: 'create-react-app-template', + }), + values: { + required: 'required-value', + }, + }); + + expect(broker).toHaveBeenCalledWith( + expect.objectContaining({ + createdBy: undefined, + spec: expect.objectContaining({ + user: { entity: undefined, ref: undefined }, + }), + }), + ); + }); }); describe('GET /v2/tasks/:taskId', () => { diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index e7413b3a87..5453dcd234 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -16,7 +16,11 @@ import { PluginDatabaseManager, UrlReader } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; -import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; +import { + parseEntityRef, + stringifyEntityRef, + UserEntity, +} from '@backstage/catalog-model'; import { Entity } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { InputError, NotFoundError } from '@backstage/errors'; @@ -130,10 +134,11 @@ export async function createRouter( '/v2/templates/:namespace/:kind/:name/parameter-schema', async (req, res) => { const { namespace, kind, name } = req.params; + const { token } = parseBearerToken(req.headers.authorization); const template = await findTemplate({ catalogApi: catalogClient, entityRef: { kind, namespace, name }, - token: getBearerToken(req.headers.authorization), + token, }); if (isSupportedTemplate(template)) { const parameters = [template.spec.parameters ?? []].flat(); @@ -168,12 +173,20 @@ export async function createRouter( const { kind, namespace, name } = parseEntityRef(templateRef, { defaultKind: 'template', }); + const { token, entityRef: userEntityRef } = parseBearerToken( + req.headers.authorization, + ); + + const userEntity = userEntityRef + ? await catalogClient.getEntityByRef(userEntityRef, { token }) + : undefined; + const values = req.body.values; - const token = getBearerToken(req.headers.authorization); + const template = await findTemplate({ catalogApi: catalogClient, entityRef: { kind, namespace, name }, - token: getBearerToken(req.headers.authorization), + token, }); if (!isSupportedTemplate(template)) { @@ -203,6 +216,10 @@ export async function createRouter( })), output: template.spec.output ?? {}, parameters: values, + user: { + entity: userEntity as UserEntity, + ref: userEntityRef, + }, templateInfo: { entityRef: stringifyEntityRef({ kind, @@ -215,6 +232,7 @@ export async function createRouter( const result = await taskBroker.dispatch({ spec: taskSpec, + createdBy: userEntityRef, secrets: { ...req.body.secrets, backstageToken: token, @@ -315,6 +333,21 @@ export async function createRouter( return app; } -function getBearerToken(header?: string): string | undefined { - return header?.match(/Bearer\s+(\S+)/i)?.[1]; +function parseBearerToken(header?: string): { + token?: string; + entityRef?: string; +} { + const token = header?.match(/Bearer\s+(\S+)/i)?.[1]; + + if (!token) return {}; + + const [_header, rawPayload, _signature] = token.split('.'); + const payload: { sub: string } = JSON.parse( + Buffer.from(rawPayload, 'base64').toString(), + ); + + return { + entityRef: payload.sub, + token, + }; } diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index a1b2d4511d..d4773d6d91 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-common +## 1.1.0-next.0 + +### Minor Changes + +- f8baf7df44: Added the ability to reference the user in the `template.yaml` manifest + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.0.2-next.0 + ## 1.0.1 ### Patch Changes diff --git a/plugins/scaffolder-common/api-report.md b/plugins/scaffolder-common/api-report.md index 532e72d3fd..a1c5c2bf23 100644 --- a/plugins/scaffolder-common/api-report.md +++ b/plugins/scaffolder-common/api-report.md @@ -7,6 +7,7 @@ import { Entity } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { KindValidator } from '@backstage/catalog-model'; +import { UserEntity } from '@backstage/catalog-model'; // @public export type TaskSpec = TaskSpecV1beta3; @@ -20,6 +21,10 @@ export interface TaskSpecV1beta3 { parameters: JsonObject; steps: TaskStep[]; templateInfo?: TemplateInfo; + user?: { + entity?: UserEntity; + ref?: string; + }; } // @public diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 1f3cad0f4a..2cf1def503 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-common", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", - "version": "1.0.1", + "version": "1.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -39,10 +39,10 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", + "@backstage/catalog-model": "^1.0.2-next.0", "@backstage/types": "^1.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0" + "@backstage/cli": "^0.17.1-next.2" } } diff --git a/plugins/scaffolder-common/src/TaskSpec.ts b/plugins/scaffolder-common/src/TaskSpec.ts index e745964ff7..4ba43092ae 100644 --- a/plugins/scaffolder-common/src/TaskSpec.ts +++ b/plugins/scaffolder-common/src/TaskSpec.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { UserEntity } from '@backstage/catalog-model'; import { JsonValue, JsonObject } from '@backstage/types'; /** @@ -91,6 +92,19 @@ export interface TaskSpecV1beta3 { * Some information about the template that is stored on the task spec. */ templateInfo?: TemplateInfo; + /** + * Some decoration of the author of the task that should be available in the context + */ + user?: { + /** + * The decorated entity from the Catalog + */ + entity?: UserEntity; + /** + * An entity ref for the author of the task + */ + ref?: string; + }; } /** diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index c2f287de82..88cee84d7e 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-scaffolder +## 1.2.0-next.3 + +### Patch Changes + +- cc8ddd0979: revert dependency `event-source-polyfill` to `1.0.25` +- Updated dependencies + - @backstage/core-components@0.9.4-next.2 + +## 1.2.0-next.2 + +### Patch Changes + +- 70817dafc0: Updated dependency `use-immer` to `^0.7.0`. +- 1af133f779: Updated dependency `event-source-polyfill` to `1.0.26`. +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-scaffolder-common@1.1.0-next.0 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/plugin-permission-react@0.4.1-next.1 + - @backstage/catalog-client@1.0.2-next.0 + - @backstage/plugin-catalog-common@1.0.2-next.0 + ## 1.2.0-next.1 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index fee14544b6..6795af4488 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.2.0-next.1", + "version": "1.2.0-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,18 +35,18 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.1", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-client": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/integration-react": "^1.1.0-next.1", - "@backstage/plugin-catalog-common": "^1.0.1", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", - "@backstage/plugin-permission-react": "^0.4.1-next.0", - "@backstage/plugin-scaffolder-common": "^1.0.1", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/integration-react": "^1.1.0-next.2", + "@backstage/plugin-catalog-common": "^1.0.2-next.0", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", + "@backstage/plugin-permission-react": "^0.4.1-next.1", + "@backstage/plugin-scaffolder-common": "^1.1.0-next.0", "@backstage/theme": "^0.2.15", "@backstage/types": "^1.0.0", "@codemirror/legacy-modes": "^0.20.0", @@ -70,7 +70,7 @@ "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", "react-use": "^17.2.4", - "use-immer": "^0.6.0", + "use-immer": "^0.7.0", "yaml": "^1.9.2", "zen-observable": "^0.8.15" }, @@ -79,11 +79,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/plugin-catalog": "^1.2.0-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/plugin-catalog": "^1.2.0-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -92,7 +92,7 @@ "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "event-source-polyfill": "1.0.26", + "event-source-polyfill": "1.0.25", "msw": "^0.35.0" }, "files": [ diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index a328c09098..38ecaa8486 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 0.1.4-next.1 + +### Patch Changes + +- 71d3432710: Search Engines will now index documents in batches of 1000 instead of 100 (under the hood). This may result in your Backstage backend consuming slightly more memory during index runs, but should dramatically improve indexing performance for large document sets. +- 3a74e203a8: Support generating highlighted matched terms in search result data +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-backend-node@0.6.1-next.1 + - @backstage/plugin-search-common@0.3.4-next.0 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md index 10231f3a83..7ef026745f 100644 --- a/plugins/search-backend-module-elasticsearch/api-report.md +++ b/plugins/search-backend-module-elasticsearch/api-report.md @@ -98,6 +98,27 @@ export interface ElasticSearchClientOptions { Transport?: ElasticSearchTransportConstructor; } +// @public (undocumented) +export type ElasticSearchHighlightConfig = { + fragmentDelimiter: string; + fragmentSize: number; + numFragments: number; + preTag: string; + postTag: string; +}; + +// @public (undocumented) +export type ElasticSearchHighlightOptions = { + fragmentDelimiter?: string; + fragmentSize?: number; + numFragments?: number; +}; + +// @public (undocumented) +export type ElasticSearchQueryTranslatorOptions = { + highlightOptions?: ElasticSearchHighlightConfig; +}; + // @public (undocumented) export class ElasticSearchSearchEngine implements SearchEngine { constructor( @@ -105,6 +126,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { aliasPostfix: string, indexPrefix: string, logger: Logger, + highlightOptions?: ElasticSearchHighlightOptions, ); // Warning: (ae-forgotten-export) The symbol "ElasticSearchOptions" needs to be exported by the entry point index.d.ts // @@ -127,7 +149,10 @@ export class ElasticSearchSearchEngine implements SearchEngine { // Warning: (ae-forgotten-export) The symbol "ConcreteElasticSearchQuery" needs to be exported by the entry point index.d.ts // // (undocumented) - protected translator(query: SearchQuery): ConcreteElasticSearchQuery; + protected translator( + query: SearchQuery, + options?: ElasticSearchQueryTranslatorOptions, + ): ConcreteElasticSearchQuery; } // Warning: (ae-missing-release-tag) "ElasticSearchSearchEngineIndexer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/search-backend-module-elasticsearch/config.d.ts b/plugins/search-backend-module-elasticsearch/config.d.ts index da403370cd..8f63e66365 100644 --- a/plugins/search-backend-module-elasticsearch/config.d.ts +++ b/plugins/search-backend-module-elasticsearch/config.d.ts @@ -21,6 +21,24 @@ export interface Config { * Options for ElasticSearch */ elasticsearch?: { + /** + * Options for configuring highlight settings + * See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/highlighting.html + */ + highlightOptions?: { + /** + * The size of the highlighted fragment in characters. Defaults to 1000. + */ + fragmentSize?: number; + /** + * Number of result fragments to extract. Fragments will be concatenated with `fragmentDelimiter`. Defaults to 1. + */ + numFragments?: number; + /** + * Delimiter string used to concatenate fragments. Defaults to " ... ". + */ + fragmentDelimiter?: string; + }; /** Miscellaneous options for the client */ clientOptions?: { ssl?: { diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index f53b20e377..cf009348aa 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": "0.1.4-next.0", + "version": "0.1.4-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,19 +23,20 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.0", - "@backstage/plugin-search-backend-node": "^0.6.1-next.0", - "@backstage/plugin-search-common": "^0.3.3", - "@elastic/elasticsearch": "7.13.0", "@acuris/aws-es-connection": "^2.2.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/plugin-search-backend-node": "^0.6.1-next.1", + "@backstage/plugin-search-common": "^0.3.4-next.0", + "@elastic/elasticsearch": "7.13.0", "aws-sdk": "^2.948.0", "elastic-builder": "^2.16.0", "lodash": "^4.17.21", + "uuid": "^8.3.2", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/cli": "^0.17.1-next.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/cli": "^0.17.1-next.2", "@elastic/elasticsearch-mock": "^1.0.0" }, "files": [ diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts index 467e1b4e77..134de5a9f6 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts @@ -26,6 +26,8 @@ import { } from './ElasticSearchSearchEngine'; import { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer'; +jest.mock('uuid', () => ({ v4: () => 'tag' })); + class ElasticSearchSearchEngineForTranslatorTests extends ElasticSearchSearchEngine { getTranslator() { return this.translator; @@ -105,10 +107,21 @@ describe('ElasticSearchSearchEngine', () => { filters: {}, }); - expect(translatorSpy).toHaveBeenCalledWith({ - term: 'testTerm', - filters: {}, - }); + expect(translatorSpy).toHaveBeenCalledWith( + { + term: 'testTerm', + filters: {}, + }, + { + highlightOptions: { + preTag: ``, + postTag: ``, + fragmentSize: 1000, + numFragments: 1, + fragmentDelimiter: ' ... ', + }, + }, + ); }); it('should return translated query with 1 filter', async () => { @@ -281,6 +294,59 @@ describe('ElasticSearchSearchEngine', () => { }); }); + it('should accept custom highlight options', async () => { + const translatorUnderTest = inspectableSearchEngine.getTranslator(); + + const actualTranslatedQuery = translatorUnderTest( + { + types: ['indexName'], + term: 'testTerm', + pageCursor: 'MQ==', + }, + { + highlightOptions: { + preTag: ``, + postTag: ``, + fragmentSize: 100, + numFragments: 3, + fragmentDelimiter: ' ... ', + }, + }, + ) as ConcreteElasticSearchQuery; + + expect(actualTranslatedQuery).toMatchObject({ + documentTypes: ['indexName'], + elasticSearchQuery: expect.any(Object), + }); + + const queryBody = actualTranslatedQuery.elasticSearchQuery; + + expect(queryBody).toEqual({ + query: { + bool: { + filter: [], + must: { + multi_match: { + query: 'testTerm', + fields: ['*'], + fuzziness: 'auto', + minimum_should_match: 1, + }, + }, + }, + }, + highlight: { + fields: { '*': {} }, + fragment_size: 100, + number_of_fragments: 3, + pre_tags: [''], + post_tags: [''], + }, + from: 25, + size: 25, + }); + }); + it('should throw if unsupported filter shapes passed in', async () => { const translatorUnderTest = inspectableSearchEngine.getTranslator(); const actualTranslatedQuery = () => @@ -465,6 +531,66 @@ describe('ElasticSearchSearchEngine', () => { }); }); + it('should handle parsing highlights in search query results', async () => { + mock.clear({ + method: 'POST', + path: '/*__search/_search', + }); + mock.add( + { + method: 'POST', + path: '/*__search/_search', + }, + () => { + return { + hits: { + total: { value: 30, relation: 'eq' }, + hits: Array(25) + .fill(null) + .map((_, i) => ({ + _index: 'mytype-index__', + _source: { + value: `${i}`, + }, + highlight: { + foo: [ + 'highlighted test result', + 'another fragment result', + ], + bar: ['more test results'], + }, + })), + }, + }; + }, + ); + + const mockedSearchResult = await testSearchEngine.query({ + term: 'testTerm', + filters: {}, + }); + + expect(mockedSearchResult).toMatchObject({ + results: expect.arrayContaining( + Array(25) + .fill(null) + .map((_, i) => ({ + type: 'mytype', + document: { value: `${i}` }, + highlight: { + preTag: '', + postTag: '', + fields: { + foo: 'highlighted test result ... another fragment result', + bar: 'more test results', + }, + }, + })), + ), + nextPageCursor: 'MQ==', + }); + }); + it('should handle index/search type filtering correctly', async () => { const elasticSearchQuerySpy = jest.spyOn(client, 'search'); await testSearchEngine.query({ @@ -488,6 +614,13 @@ describe('ElasticSearchSearchEngine', () => { filter: [], }, }, + highlight: { + fields: { '*': {} }, + fragment_size: 1000, + number_of_fragments: 1, + pre_tags: [''], + post_tags: [''], + }, from: 0, size: 25, }, @@ -515,6 +648,13 @@ describe('ElasticSearchSearchEngine', () => { filter: [], }, }, + highlight: { + fields: { '*': {} }, + fragment_size: 1000, + number_of_fragments: 1, + pre_tags: [''], + post_tags: [''], + }, from: 0, size: 25, }, @@ -543,6 +683,13 @@ describe('ElasticSearchSearchEngine', () => { filter: [], }, }, + highlight: { + fields: { '*': {} }, + fragment_size: 1000, + number_of_fragments: 1, + pre_tags: [''], + post_tags: [''], + }, from: 0, size: 25, }, @@ -618,7 +765,7 @@ describe('ElasticSearchSearchEngine', () => { }); describe('ElasticSearchSearchEngine.fromConfig', () => { - it('accesses the clientOptions config', async () => { + it('accesses the clientOptions and highlightOptions config', async () => { const esOptions = { clientOptions: { ssl: { @@ -635,6 +782,7 @@ describe('ElasticSearchSearchEngine', () => { const esConfig = new ConfigReader(esOptions); jest.spyOn(config, 'getConfig').mockImplementation(() => esConfig); const getOptionalConfig = jest.spyOn(esConfig, 'getOptionalConfig'); + const getOptional = jest.spyOn(config, 'getOptional'); await ElasticSearchSearchEngine.fromConfig({ logger: getVoidLogger(), @@ -642,9 +790,12 @@ describe('ElasticSearchSearchEngine', () => { }); expect(getOptionalConfig.mock.calls[0][0]).toEqual('clientOptions'); + expect(getOptional.mock.calls[0][0]).toEqual( + 'search.elasticsearch.highlightOptions', + ); }); - it('does not require the clientOptions config', async () => { + it('does not require the clientOptions or highlightOptions config', async () => { const config = new ConfigReader({ search: { elasticsearch: { diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index aec225a64b..5ec33a95e3 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -21,6 +21,7 @@ import { import { Config } from '@backstage/config'; import { IndexableDocument, + IndexableResult, IndexableResultSet, SearchEngine, SearchQuery, @@ -28,6 +29,7 @@ import { import { Client } from '@elastic/elasticsearch'; import esb from 'elastic-builder'; import { isEmpty, isNaN as nan, isNumber } from 'lodash'; +import { v4 as uuid } from 'uuid'; import { Logger } from 'winston'; import type { ElasticSearchClientOptions } from './ElasticSearchClientOptions'; import { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer'; @@ -40,8 +42,16 @@ export type ConcreteElasticSearchQuery = { pageSize: number; }; +/** + * @public + */ +export type ElasticSearchQueryTranslatorOptions = { + highlightOptions?: ElasticSearchHighlightConfig; +}; + type ElasticSearchQueryTranslator = ( query: SearchQuery, + options?: ElasticSearchQueryTranslatorOptions, ) => ConcreteElasticSearchQuery; type ElasticSearchOptions = { @@ -51,11 +61,34 @@ type ElasticSearchOptions = { indexPrefix?: string; }; +/** + * @public + */ +export type ElasticSearchHighlightOptions = { + fragmentDelimiter?: string; + fragmentSize?: number; + numFragments?: number; +}; + +/** + * @public + */ +export type ElasticSearchHighlightConfig = { + fragmentDelimiter: string; + fragmentSize: number; + numFragments: number; + preTag: string; + postTag: string; +}; + type ElasticSearchResult = { _index: string; _type: string; _score: number; _source: IndexableDocument; + highlight?: { + [field: string]: string[]; + }; }; function isBlank(str: string) { @@ -67,14 +100,25 @@ function isBlank(str: string) { */ export class ElasticSearchSearchEngine implements SearchEngine { private readonly elasticSearchClient: Client; + private readonly highlightOptions: ElasticSearchHighlightConfig; constructor( private readonly elasticSearchClientOptions: ElasticSearchClientOptions, private readonly aliasPostfix: string, private readonly indexPrefix: string, private readonly logger: Logger, + highlightOptions?: ElasticSearchHighlightOptions, ) { this.elasticSearchClient = this.newClient(options => new Client(options)); + const uuidTag = uuid(); + this.highlightOptions = { + preTag: `<${uuidTag}>`, + postTag: ``, + fragmentSize: 1000, + numFragments: 1, + fragmentDelimiter: ' ... ', + ...highlightOptions, + }; } static async fromConfig({ @@ -99,6 +143,9 @@ export class ElasticSearchSearchEngine implements SearchEngine { aliasPostfix, indexPrefix, logger, + config.getOptional( + 'search.elasticsearch.highlightOptions', + ), ); } @@ -111,7 +158,10 @@ export class ElasticSearchSearchEngine implements SearchEngine { return create(this.elasticSearchClientOptions); } - protected translator(query: SearchQuery): ConcreteElasticSearchQuery { + protected translator( + query: SearchQuery, + options?: ElasticSearchQueryTranslatorOptions, + ): ConcreteElasticSearchQuery { const { term, filters = {}, types, pageCursor } = query; const filter = Object.entries(filters) @@ -143,13 +193,25 @@ export class ElasticSearchSearchEngine implements SearchEngine { const pageSize = 25; const { page } = decodePageCursor(pageCursor); + let esbRequestBodySearch = esb + .requestBodySearch() + .query(esb.boolQuery().filter(filter).must([esbQuery])) + .from(page * pageSize) + .size(pageSize); + + if (options?.highlightOptions) { + esbRequestBodySearch = esbRequestBodySearch.highlight( + esb + .highlight('*') + .numberOfFragments(options.highlightOptions.numFragments as number) + .fragmentSize(options.highlightOptions.fragmentSize as number) + .preTags(options.highlightOptions.preTag) + .postTags(options.highlightOptions.postTag), + ); + } + return { - elasticSearchQuery: esb - .requestBodySearch() - .query(esb.boolQuery().filter(filter).must([esbQuery])) - .from(page * pageSize) - .size(pageSize) - .toJSON(), + elasticSearchQuery: esbRequestBodySearch.toJSON(), documentTypes: types, pageSize, }; @@ -193,8 +255,10 @@ export class ElasticSearchSearchEngine implements SearchEngine { } async query(query: SearchQuery): Promise { - const { elasticSearchQuery, documentTypes, pageSize } = - this.translator(query); + const { elasticSearchQuery, documentTypes, pageSize } = this.translator( + query, + { highlightOptions: this.highlightOptions }, + ); const queryIndices = documentTypes ? documentTypes.map(it => this.constructSearchAlias(it)) : this.constructSearchAlias('*'); @@ -214,10 +278,27 @@ export class ElasticSearchSearchEngine implements SearchEngine { : undefined; return { - results: result.body.hits.hits.map((d: ElasticSearchResult) => ({ - type: this.getTypeFromIndex(d._index), - document: d._source, - })), + results: result.body.hits.hits.map((d: ElasticSearchResult) => { + const resultItem: IndexableResult = { + type: this.getTypeFromIndex(d._index), + document: d._source, + }; + + if (d.highlight) { + resultItem.highlight = { + preTag: this.highlightOptions.preTag as string, + postTag: this.highlightOptions.postTag as string, + fields: Object.fromEntries( + Object.entries(d.highlight).map(([field, fragments]) => [ + field, + fragments.join(this.highlightOptions.fragmentDelimiter), + ]), + ), + }; + } + + return resultItem; + }), nextPageCursor, previousPageCursor, }; diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts index bf07b8a36d..2a738e1506 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts @@ -53,7 +53,7 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { private bulkResult: Promise; constructor(options: ElasticSearchSearchEngineIndexerOptions) { - super({ batchSize: 100 }); + super({ batchSize: 1000 }); this.logger = options.logger; this.startTimestamp = process.hrtime(); this.type = options.type; diff --git a/plugins/search-backend-module-elasticsearch/src/engines/index.ts b/plugins/search-backend-module-elasticsearch/src/engines/index.ts index 19c24b37ff..c5628776ef 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/index.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/index.ts @@ -18,6 +18,9 @@ export { ElasticSearchSearchEngine } from './ElasticSearchSearchEngine'; export type { ConcreteElasticSearchQuery, ElasticSearchClientOptions, + ElasticSearchHighlightConfig, + ElasticSearchHighlightOptions, + ElasticSearchQueryTranslatorOptions, } from './ElasticSearchSearchEngine'; export type { ElasticSearchSearchEngineIndexer, diff --git a/plugins/search-backend-module-elasticsearch/src/index.ts b/plugins/search-backend-module-elasticsearch/src/index.ts index 223141be6b..744e12f8c8 100644 --- a/plugins/search-backend-module-elasticsearch/src/index.ts +++ b/plugins/search-backend-module-elasticsearch/src/index.ts @@ -23,6 +23,9 @@ export { ElasticSearchSearchEngine } from './engines'; export type { ElasticSearchClientOptions, + ElasticSearchHighlightConfig, + ElasticSearchHighlightOptions, + ElasticSearchQueryTranslatorOptions, ElasticSearchSearchEngineIndexer, ElasticSearchSearchEngineIndexerOptions, } from './engines'; diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index c53a909f11..3a55eb6fc3 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search-backend-module-pg +## 0.3.3-next.1 + +### Patch Changes + +- 71d3432710: Search Engines will now index documents in batches of 1000 instead of 100 (under the hood). This may result in your Backstage backend consuming slightly more memory during index runs, but should dramatically improve indexing performance for large document sets. +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/plugin-search-backend-node@0.6.1-next.1 + - @backstage/plugin-search-common@0.3.4-next.0 + ## 0.3.3-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index b86aa62d2f..b033a145d8 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.3.3-next.0", + "version": "0.3.3-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,15 +23,15 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/plugin-search-backend-node": "^0.6.1-next.0", - "@backstage/plugin-search-common": "^0.3.3", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/plugin-search-backend-node": "^0.6.1-next.1", + "@backstage/plugin-search-common": "^0.3.4-next.0", "lodash": "^4.17.21", "knex": "^1.0.2" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.24-next.0", - "@backstage/cli": "^0.17.1-next.0" + "@backstage/backend-test-utils": "^0.1.24-next.1", + "@backstage/cli": "^0.17.1-next.2" }, "files": [ "dist", diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts index 8618bed4c8..cc89f28c80 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts @@ -136,7 +136,7 @@ describe('PgSearchEngine', () => { // Indexer instantiated with expected args. expect(PgSearchEngineIndexer).toHaveBeenCalledWith( expect.objectContaining({ - batchSize: 100, + batchSize: 1000, type: 'my-type', databaseStore: database, }), diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts index ea363d8ea1..445d1bb5c1 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts @@ -78,7 +78,7 @@ export class PgSearchEngine implements SearchEngine { async getIndexer(type: string) { return new PgSearchEngineIndexer({ - batchSize: 100, + batchSize: 1000, type, databaseStore: this.databaseStore, }); diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 23fb80dc3a..0be74d49d1 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search-backend-node +## 0.6.1-next.1 + +### Patch Changes + +- 71d3432710: Search Engines will now index documents in batches of 1000 instead of 100 (under the hood). This may result in your Backstage backend consuming slightly more memory during index runs, but should dramatically improve indexing performance for large document sets. +- 3a74e203a8: Support generating highlighted matched terms in search result data +- Updated dependencies + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/plugin-search-common@0.3.4-next.0 + ## 0.6.1-next.0 ### Patch Changes diff --git a/plugins/search-backend-node/api-report.md b/plugins/search-backend-node/api-report.md index 61b8a124f7..0f379b3fc1 100644 --- a/plugins/search-backend-node/api-report.md +++ b/plugins/search-backend-node/api-report.md @@ -82,6 +82,10 @@ export class LunrSearchEngine implements SearchEngine { // (undocumented) getIndexer(type: string): Promise; // (undocumented) + protected highlightPostTag: string; + // (undocumented) + protected highlightPreTag: string; + // (undocumented) protected logger: Logger; // (undocumented) protected lunrIndices: Record; diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 433edcfbd0..b55c77c05c 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": "0.6.1-next.0", + "version": "0.6.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,18 +23,19 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-tasks": "^0.3.1-next.0", + "@backstage/backend-tasks": "^0.3.1-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-search-common": "^0.3.3", + "@backstage/plugin-search-common": "^0.3.4-next.0", "@types/lunr": "^2.3.3", "lodash": "^4.17.21", "lunr": "^2.3.9", "node-abort-controller": "^3.0.1", + "uuid": "^8.3.2", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/cli": "^0.17.1-next.0" + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/cli": "^0.17.1-next.2" }, "files": [ "dist" diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts index b0bd2bca8f..84b1a35165 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts @@ -25,6 +25,7 @@ import { LunrSearchEngine, decodePageCursor, encodePageCursor, + parseHighlightFields, } from './LunrSearchEngine'; import { LunrSearchEngineIndexer } from './LunrSearchEngineIndexer'; import { TestPipeline } from '../test-utils'; @@ -33,6 +34,12 @@ import { TestPipeline } from '../test-utils'; * Just used to test the default translator shipped with LunrSearchEngine. */ class LunrSearchEngineForTests extends LunrSearchEngine { + getHighlightTags() { + return { + pre: this.highlightPreTag, + post: this.highlightPostTag, + }; + } getDocStore() { return this.docStore; } @@ -468,6 +475,58 @@ describe('LunrSearchEngine', () => { }); }); + it('should perform search query and return highlight metadata on match', async () => { + const inspectableSearchEngine = new LunrSearchEngineForTests({ + logger: getVoidLogger(), + }); + + const mockDocuments = [ + { + title: 'testTitle', + text: 'testText', + location: 'test/location', + }, + ]; + + // Mock indexing of 1 document + const indexer = await getActualIndexer( + inspectableSearchEngine, + 'test-index', + ); + await TestPipeline.withSubject(indexer) + .withDocuments(mockDocuments) + .execute(); + + // Perform search query + const mockedSearchResult = await inspectableSearchEngine.query({ + term: 'test', + filters: {}, + }); + + const highlightTags = inspectableSearchEngine.getHighlightTags(); + expect(mockedSearchResult).toMatchObject({ + results: [ + { + document: { + title: 'testTitle', + text: 'testText', + location: 'test/location', + }, + highlight: { + preTag: highlightTags.pre, + postTag: highlightTags.post, + fields: { + title: `${highlightTags.pre}testTitle${highlightTags.post}`, + text: `${highlightTags.pre}testText${highlightTags.post}`, + location: `${highlightTags.pre}test/location${highlightTags.post}`, + }, + }, + }, + ], + nextPageCursor: undefined, + }); + }); + it('should perform search query and return search results on partial match', async () => { const mockDocuments = [ { @@ -976,3 +1035,33 @@ describe('encodePageCursor', () => { expect(encodePageCursor({ page: 1 })).toEqual('MQ=='); }); }); + +describe('parseHighlightFields', () => { + it('should parse highlight metadata', () => { + expect( + parseHighlightFields({ + preTag: '<>', + postTag: '', + doc: { foo: 'abc def', bar: 'ghi jkl' }, + positionMetadata: { + test: { + foo: { + position: [[0, 3]], + }, + }, + anotherTest: { + foo: { + position: [[4, 3]], + }, + bar: { + position: [[4, 3]], + }, + }, + }, + }), + ).toEqual({ + foo: '<>abc <>def', + bar: 'ghi <>jkl', + }); + }); +}); diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts index 09e8729ba8..656cd3e1eb 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -22,6 +22,7 @@ import { SearchEngine, } from '@backstage/plugin-search-common'; import lunr from 'lunr'; +import { v4 as uuid } from 'uuid'; import { Logger } from 'winston'; import { LunrSearchEngineIndexer } from './LunrSearchEngineIndexer'; @@ -51,10 +52,15 @@ export class LunrSearchEngine implements SearchEngine { protected lunrIndices: Record = {}; protected docStore: Record; protected logger: Logger; + protected highlightPreTag: string; + protected highlightPostTag: string; constructor({ logger }: { logger: Logger }) { this.logger = logger; this.docStore = {}; + const uuidTag = uuid(); + this.highlightPreTag = `<${uuidTag}>`; + this.highlightPostTag = ``; } protected translator: QueryTranslator = ({ @@ -198,9 +204,20 @@ export class LunrSearchEngine implements SearchEngine { // Translate results into IndexableResultSet const realResultSet: IndexableResultSet = { - results: results.slice(offset, offset + pageSize).map(d => { - return { type: d.type, document: this.docStore[d.result.ref] }; - }), + results: results.slice(offset, offset + pageSize).map(d => ({ + type: d.type, + document: this.docStore[d.result.ref], + highlight: { + preTag: this.highlightPreTag, + postTag: this.highlightPostTag, + fields: parseHighlightFields({ + preTag: this.highlightPreTag, + postTag: this.highlightPostTag, + doc: this.docStore[d.result.ref], + positionMetadata: d.result.matchData.metadata as any, + }), + }, + })), nextPageCursor, previousPageCursor, }; @@ -222,3 +239,52 @@ export function decodePageCursor(pageCursor?: string): { page: number } { export function encodePageCursor({ page }: { page: number }): string { return Buffer.from(`${page}`, 'utf-8').toString('base64'); } + +type ParseHighlightFieldsProps = { + preTag: string; + postTag: string; + doc: any; + positionMetadata: { + [term: string]: { + [field: string]: { + position: number[][]; + }; + }; + }; +}; + +export function parseHighlightFields({ + preTag, + postTag, + doc, + positionMetadata, +}: ParseHighlightFieldsProps): { [field: string]: string } { + // Merge the field positions across all query terms + const highlightFieldPositions = Object.values(positionMetadata).reduce( + (fieldPositions, metadata) => { + Object.keys(metadata).map(fieldKey => { + fieldPositions[fieldKey] = fieldPositions[fieldKey] ?? []; + fieldPositions[fieldKey].push(...metadata[fieldKey].position); + }); + + return fieldPositions; + }, + {} as { [field: string]: number[][] }, + ); + + return Object.fromEntries( + Object.entries(highlightFieldPositions).map(([field, positions]) => { + positions.sort((a, b) => b[0] - a[0]); + + const highlightedField = positions.reduce((content, pos) => { + return ( + `${content.substring(0, pos[0])}${preTag}` + + `${content.substring(pos[0], pos[0] + pos[1])}` + + `${postTag}${content.substring(pos[0] + pos[1])}` + ); + }, doc[field]); + + return [field, highlightedField]; + }), + ); +} diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngineIndexer.ts b/plugins/search-backend-node/src/engines/LunrSearchEngineIndexer.ts index 49afafea64..4da27be94b 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngineIndexer.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngineIndexer.ts @@ -27,11 +27,12 @@ export class LunrSearchEngineIndexer extends BatchSearchEngineIndexer { private docStore: Record = {}; constructor() { - super({ batchSize: 100 }); + super({ batchSize: 1000 }); this.builder = new lunr.Builder(); this.builder.pipeline.add(lunr.trimmer, lunr.stopWordFilter, lunr.stemmer); this.builder.searchPipeline.add(lunr.stemmer); + this.builder.metadataWhitelist = ['position']; } // No async initialization required. diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 656b969541..d07d86d4aa 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search-backend +## 0.5.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-backend-node@0.6.1-next.1 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/plugin-auth-node@0.2.1-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-permission-node@0.6.1-next.1 + ## 0.5.2-next.0 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index b0e35aecd2..e259b7b00b 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": "0.5.2-next.0", + "version": "0.5.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,14 +23,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.1-next.0", - "@backstage/plugin-permission-common": "^0.6.0", - "@backstage/plugin-permission-node": "^0.6.1-next.0", - "@backstage/plugin-search-backend-node": "^0.6.1-next.0", - "@backstage/plugin-search-common": "^0.3.3", + "@backstage/plugin-auth-node": "^0.2.1-next.1", + "@backstage/plugin-permission-common": "^0.6.1-next.0", + "@backstage/plugin-permission-node": "^0.6.1-next.1", + "@backstage/plugin-search-backend-node": "^0.6.1-next.1", + "@backstage/plugin-search-common": "^0.3.4-next.0", "@backstage/types": "^1.0.0", "@types/express": "^4.17.6", "dataloader": "^2.0.0", @@ -43,7 +43,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/search-common/CHANGELOG.md b/plugins/search-common/CHANGELOG.md index f8caf9314b..9542374b28 100644 --- a/plugins/search-common/CHANGELOG.md +++ b/plugins/search-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-search-common +## 0.3.4-next.0 + +### Patch Changes + +- 3a74e203a8: Support generating highlighted matched terms in search result data +- Updated dependencies + - @backstage/plugin-permission-common@0.6.1-next.0 + ## 0.3.3 ### Patch Changes diff --git a/plugins/search-common/api-report.md b/plugins/search-common/api-report.md index bd5a56c5cc..495d77ed26 100644 --- a/plugins/search-common/api-report.md +++ b/plugins/search-common/api-report.md @@ -55,9 +55,21 @@ export interface Result { // (undocumented) document: TDocument; // (undocumented) + highlight?: ResultHighlight; + // (undocumented) type: string; } +// @beta +export interface ResultHighlight { + // (undocumented) + fields: { + [field: string]: string; + }; + postTag: string; + preTag: string; +} + // @beta (undocumented) export interface ResultSet { // (undocumented) diff --git a/plugins/search-common/package.json b/plugins/search-common/package.json index db0858f7fc..9f07b557bd 100644 --- a/plugins/search-common/package.json +++ b/plugins/search-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-common", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", - "version": "0.3.3", + "version": "0.3.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -40,10 +40,10 @@ }, "dependencies": { "@backstage/types": "^1.0.0", - "@backstage/plugin-permission-common": "^0.6.0" + "@backstage/plugin-permission-common": "^0.6.1-next.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0" + "@backstage/cli": "^0.17.1-next.2" }, "jest": { "roots": [ diff --git a/plugins/search-common/src/types.ts b/plugins/search-common/src/types.ts index 4eedabeb71..220ac977e5 100644 --- a/plugins/search-common/src/types.ts +++ b/plugins/search-common/src/types.ts @@ -28,12 +28,37 @@ export interface SearchQuery { pageCursor?: string; } +/** + * @beta + * Metadata for result relevant document fields with matched terms highlighted + * via wrapping in associated pre/post tags. The UI is expected to parse these + * field excerpts by replacing wrapping tags with applicable UI elements for rendering. + */ +export interface ResultHighlight { + /** + * Prefix tag for wrapping terms to be highlighted. + */ + preTag: string; + /** + * Postfix tag for wrapping terms to be highlighted. + */ + postTag: string; + fields: { + /** + * Matched document fields and associated excerpts containing highlighted + * terms wrapped in preTag and postTag to be parsed and rendered in the UI. + */ + [field: string]: string; + }; +} + /** * @beta */ export interface Result { type: string; document: TDocument; + highlight?: ResultHighlight; } /** diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index 9202d489ad..a7ee7fac2e 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-search-react +## 0.2.0-next.2 + +### Patch Changes + +- 3a74e203a8: Updated search result components to support rendering content with highlighted matched terms +- Updated dependencies + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.2.0-next.1 ### Minor Changes diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index e8d3afff82..9f61070854 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/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 { ApiRef } from '@backstage/core-plugin-api'; import { AsyncState } from 'react-use/lib/useAsync'; import { JsonObject } from '@backstage/types'; @@ -11,6 +13,20 @@ import { default as React_2 } from 'react'; import { SearchQuery } from '@backstage/plugin-search-common'; import { SearchResultSet } from '@backstage/plugin-search-common'; +// @public (undocumented) +export const HighlightedSearchResultText: ({ + text, + preTag, + postTag, +}: HighlightedSearchResultTextProps) => JSX.Element; + +// @public (undocumented) +export type HighlightedSearchResultTextProps = { + text: string; + preTag: string; + postTag: string; +}; + // @public export class MockSearchApi implements SearchApi { constructor(mockedResults?: SearchResultSet | undefined); diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 7579c3b9f8..17f3e1a12f 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "0.2.0-next.1", + "version": "0.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,19 +31,20 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/plugin-search-common": "^0.3.3", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/plugin-search-common": "^0.3.4-next.0", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/version-bridge": "^1.0.1", "react-use": "^17.3.2", - "@backstage/types": "^1.0.0" + "@backstage/types": "^1.0.0", + "@material-ui/core": "^4.12.2" }, "peerDependencies": { "@types/react": "^16.13.1 || ^17.0.0", "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", "@testing-library/jest-dom": "^5.10.1" diff --git a/plugins/search-react/src/components/HighlightedSearchResultText/HighlightedSearchResultText.test.tsx b/plugins/search-react/src/components/HighlightedSearchResultText/HighlightedSearchResultText.test.tsx new file mode 100644 index 0000000000..3a78a66541 --- /dev/null +++ b/plugins/search-react/src/components/HighlightedSearchResultText/HighlightedSearchResultText.test.tsx @@ -0,0 +1,39 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { screen } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { HighlightedSearchResultText } from './HighlightedSearchResultText'; + +describe('HighlightedSearchResultText', () => { + it('properly highlights result text', async () => { + await renderInTestApp( + , + ); + + expect( + screen.getByText('highlighted').tagName.toLocaleLowerCase('en-US'), + ).toEqual('mark'); + expect(screen.getByText('text').tagName.toLocaleLowerCase('en-US')).toEqual( + 'mark', + ); + }); +}); diff --git a/plugins/search-react/src/components/HighlightedSearchResultText/HighlightedSearchResultText.tsx b/plugins/search-react/src/components/HighlightedSearchResultText/HighlightedSearchResultText.tsx new file mode 100644 index 0000000000..a749f184fe --- /dev/null +++ b/plugins/search-react/src/components/HighlightedSearchResultText/HighlightedSearchResultText.tsx @@ -0,0 +1,62 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useMemo } from 'react'; +import { makeStyles } from '@material-ui/core'; + +const useStyles = makeStyles( + () => ({ + highlight: {}, + }), + { name: 'BackstageHighlightedSearchResultText' }, +); + +/** + * @public + */ +export type HighlightedSearchResultTextProps = { + text: string; + preTag: string; + postTag: string; +}; + +/** + * @public + */ +export const HighlightedSearchResultText = ({ + text, + preTag, + postTag, +}: HighlightedSearchResultTextProps) => { + const classes = useStyles(); + const terms = useMemo( + () => text.split(new RegExp(`(${preTag}.+?${postTag})`)), + [postTag, preTag, text], + ); + return ( + <> + {terms.map((t, idx) => + t.includes(preTag) ? ( + + {t.replace(new RegExp(`${preTag}|${postTag}`, 'g'), '')} + + ) : ( + t + ), + )} + + ); +}; diff --git a/plugins/search-react/src/components/HighlightedSearchResultText/index.ts b/plugins/search-react/src/components/HighlightedSearchResultText/index.ts new file mode 100644 index 0000000000..679a254827 --- /dev/null +++ b/plugins/search-react/src/components/HighlightedSearchResultText/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './HighlightedSearchResultText'; diff --git a/plugins/search-react/src/components/index.ts b/plugins/search-react/src/components/index.ts new file mode 100644 index 0000000000..679a254827 --- /dev/null +++ b/plugins/search-react/src/components/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './HighlightedSearchResultText'; diff --git a/plugins/search-react/src/index.ts b/plugins/search-react/src/index.ts index d24bd097de..9813661f3e 100644 --- a/plugins/search-react/src/index.ts +++ b/plugins/search-react/src/index.ts @@ -22,6 +22,7 @@ export { searchApiRef, MockSearchApi } from './api'; export type { SearchApi } from './api'; +export * from './components'; export { SearchContextProvider, useSearch, diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 397357326b..6d3c643c46 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-search +## 0.8.1-next.2 + +### Patch Changes + +- 3a74e203a8: Updated search result components to support rendering content with highlighted matched terms +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-react@0.2.0-next.2 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.8.1-next.1 ### Patch Changes diff --git a/plugins/search/api-report.md b/plugins/search/api-report.md index 31d357f10c..05dcdd89b3 100644 --- a/plugins/search/api-report.md +++ b/plugins/search/api-report.md @@ -10,6 +10,7 @@ import { IconComponent } from '@backstage/core-plugin-api'; import { InputBaseProps } from '@material-ui/core'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; +import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; import { SearchDocument } from '@backstage/plugin-search-common'; import { SearchResult as SearchResult_2 } from '@backstage/plugin-search-common'; @@ -19,6 +20,7 @@ import { SearchResult as SearchResult_2 } from '@backstage/plugin-search-common' // @public (undocumented) export const DefaultResultListItem: ({ result, + highlight, icon, secondaryAction, lineClamp, @@ -26,6 +28,7 @@ export const DefaultResultListItem: ({ icon?: ReactNode; secondaryAction?: ReactNode; result: SearchDocument; + highlight?: ResultHighlight | undefined; lineClamp?: number | undefined; }) => JSX.Element; diff --git a/plugins/search/package.json b/plugins/search/package.json index ee8c84fd58..109ed2a455 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": "0.8.1-next.1", + "version": "0.8.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,14 +33,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", - "@backstage/plugin-search-react": "^0.2.0-next.1", - "@backstage/plugin-search-common": "^0.3.3", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", + "@backstage/plugin-search-common": "^0.3.4-next.0", + "@backstage/plugin-search-react": "^0.2.0-next.2", "@backstage/theme": "^0.2.15", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", @@ -49,7 +49,6 @@ "qs": "^6.9.4", "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", - "react-text-truncate": "^0.18.0", "react-use": "^17.2.4" }, "peerDependencies": { @@ -57,10 +56,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.stories.tsx b/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.stories.tsx index 91143bb292..fb56d1ecdb 100644 --- a/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.stories.tsx +++ b/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.stories.tsx @@ -15,7 +15,10 @@ */ import { Button } from '@backstage/core-components'; +import { lightTheme } from '@backstage/theme'; import { Grid } from '@material-ui/core'; +import CssBaseline from '@material-ui/core/CssBaseline'; +import { ThemeProvider } from '@material-ui/core/styles'; import FindInPageIcon from '@material-ui/icons/FindInPage'; import GroupIcon from '@material-ui/icons/Group'; import React from 'react'; @@ -77,3 +80,47 @@ export const WithSecondaryAction = () => { /> ); }; +export const WithHighlightedResults = () => { + return ( + ', + postTag: '', + fields: { text: 'some text from the search result' }, + }} + /> + ); +}; + +export const WithCustomHighlightedResults = () => { + const customTheme = { + ...lightTheme, + overrides: { + ...lightTheme.overrides, + BackstageHighlightedSearchResultText: { + highlight: { + color: 'inherit', + backgroundColor: 'inherit', + fontWeight: 'bold', + textDecoration: 'underline', + }, + }, + }, + }; + + return ( + + + ', + postTag: '', + fields: { text: 'some text from the search result' }, + }} + /> + + + ); +}; diff --git a/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx b/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx index 68f00f9301..26d081b3b6 100644 --- a/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx +++ b/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx @@ -20,11 +20,6 @@ import { renderInTestApp } from '@backstage/test-utils'; import FindInPageIcon from '@material-ui/icons/FindInPage'; import { DefaultResultListItem } from './DefaultResultListItem'; -// Using canvas to render text.. -jest.mock('react-text-truncate', () => { - return ({ text }: { text: string }) => {text}; -}); - describe('DefaultResultListItem', () => { const result = { title: 'title', diff --git a/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.tsx b/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.tsx index 46045f91ee..5ce2d0744a 100644 --- a/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.tsx +++ b/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.tsx @@ -15,7 +15,11 @@ */ import React, { ReactNode } from 'react'; -import { SearchDocument } from '@backstage/plugin-search-common'; +import { + ResultHighlight, + SearchDocument, +} from '@backstage/plugin-search-common'; +import { HighlightedSearchResultText } from '@backstage/plugin-search-react'; import { ListItem, ListItemIcon, @@ -24,17 +28,18 @@ import { Divider, } from '@material-ui/core'; import { Link } from '@backstage/core-components'; -import TextTruncate from 'react-text-truncate'; type Props = { icon?: ReactNode; secondaryAction?: ReactNode; result: SearchDocument; + highlight?: ResultHighlight; lineClamp?: number; }; export const DefaultResultListItem = ({ result, + highlight, icon, secondaryAction, lineClamp = 5, @@ -45,14 +50,36 @@ export const DefaultResultListItem = ({ {icon && {icon}} + ) : ( + result.title + ) + } secondary={ - + + {highlight?.fields.text ? ( + + ) : ( + result.text + )} + } /> {secondaryAction && {secondaryAction}} diff --git a/plugins/search/src/components/SearchModal/SearchModal.tsx b/plugins/search/src/components/SearchModal/SearchModal.tsx index 55fd0cb977..b3df52d42e 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.tsx @@ -137,7 +137,7 @@ export const Modal = ({ toggleModal }: SearchModalProps) => { {({ results }) => ( - {results.map(({ document }) => ( + {results.map(({ document, highlight }) => (
{
))} diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index e07f0b44f1..ad52b9d10b 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-sentry +## 0.3.43-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.3.43-next.1 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 107425858e..2af804803b 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.3.43-next.1", + "version": "0.3.43-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,10 +35,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-table/core": "^3.1.0", "@material-ui/core": "^4.12.2", @@ -53,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 4613df7730..b72eb64a5b 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -24,8 +24,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/theme": "^0.2.15", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", @@ -42,10 +42,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 51ebbddc91..d76ad6bc83 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-sonarqube +## 0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.3.5-next.1 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 3bb7cb848f..e41f53d500 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.3.5-next.1", + "version": "0.3.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,27 +36,27 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@material-ui/styles": "^4.10.0", "cross-fetch": "^3.1.5", - "rc-progress": "3.2.4", + "rc-progress": "3.3.2", "react-use": "^17.2.4" }, "peerDependencies": { "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index f29d621a80..79b30a5761 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-splunk-on-call +## 0.3.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.3.29-next.1 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index c65d348567..c7ca761c1e 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.3.29-next.1", + "version": "0.3.29-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,10 +34,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -51,10 +51,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index de81256acb..2df87fa5ab 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-stack-overflow-backend +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 19bfe5d68d..571ea0b34e 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", - "version": "0.1.0", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,8 +33,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/plugin-search-common": "^0.3.3", - "@backstage/config": "^1.0.0", + "@backstage/plugin-search-common": "^0.3.4-next.0", + "@backstage/config": "^1.0.1-next.0", "qs": "^6.9.4", "cross-fetch": "^3.1.5", "winston": "^3.2.1" diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index aa32b2eab6..17e0195963 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-stack-overflow +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/plugin-home@0.4.21-next.2 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index cd72199203..7e07f10b33 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.1-next.1", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,11 +23,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/plugin-home": "^0.4.21-next.1", - "@backstage/plugin-search-common": "^0.3.3", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/plugin-home": "^0.4.21-next.2", + "@backstage/plugin-search-common": "^0.3.4-next.0", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,10 +42,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index f9e8597d12..c30c6da7e8 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-tech-insights-node@0.3.0-next.2 + ## 0.1.16-next.1 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index f8f028e796..4b720cac92 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.16-next.1", + "version": "0.1.16-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", "@backstage/plugin-tech-insights-common": "^0.2.4", - "@backstage/plugin-tech-insights-node": "^0.3.0-next.1", + "@backstage/plugin-tech-insights-node": "^0.3.0-next.2", "ajv": "^8.10.0", "json-rules-engine": "^6.1.2", "lodash": "^4.17.21", @@ -46,7 +46,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1" + "@backstage/cli": "^0.17.1-next.2" }, "files": [ "dist" diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index e91f179d07..7745f989ba 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-tech-insights-backend +## 0.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/backend-tasks@0.3.1-next.1 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/plugin-tech-insights-node@0.3.0-next.2 + - @backstage/catalog-client@1.0.2-next.0 + ## 0.4.0-next.1 ### Minor Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index e9ae330d21..d6881cb19c 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.4.0-next.1", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,14 +34,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.1", - "@backstage/backend-tasks": "^0.3.1-next.0", - "@backstage/catalog-client": "^1.0.1", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/backend-tasks": "^0.3.1-next.1", + "@backstage/catalog-client": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", "@backstage/plugin-tech-insights-common": "^0.2.4", - "@backstage/plugin-tech-insights-node": "^0.3.0-next.1", + "@backstage/plugin-tech-insights-node": "^0.3.0-next.2", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -54,8 +54,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.24-next.0", - "@backstage/cli": "^0.17.1-next.1", + "@backstage/backend-test-utils": "^0.1.24-next.1", + "@backstage/cli": "^0.17.1-next.2", "@types/supertest": "^2.0.8", "@types/semver": "^7.3.8", "supertest": "^6.1.3", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index 4f194c51eb..a9907265aa 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-tech-insights-node +## 0.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + ## 0.3.0-next.1 ### Minor Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 54e0634c20..4600421e29 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.3.0-next.1", + "version": "0.3.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,15 +33,15 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/config": "^1.0.1-next.0", "@backstage/plugin-tech-insights-common": "^0.2.4", "@types/luxon": "^2.0.5", "luxon": "^2.0.2", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1" + "@backstage/cli": "^0.17.1-next.2" }, "files": [ "dist" diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index 3f60530f37..e59d9d09c3 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-tech-insights +## 0.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.2.1-next.1 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 08796b52e1..be53883371 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.2.1-next.1", + "version": "0.2.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,11 +28,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/plugin-tech-insights-common": "^0.2.4", "@backstage/theme": "^0.2.15", "@backstage/types": "^1.0.0", @@ -47,10 +47,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 27be1b33c4..5821d6036c 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -34,8 +34,8 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index 57ca350fdd..30c46cb6b1 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-techdocs-addons-test-utils +## 0.1.0-next.1 + +### Patch Changes + +- f84e0e2818: Fixed a bug preventing testing of TechDocs Addons whose dom contained `` tags. +- 7c398c6473: The `TechDocsAddonTester` class may now be extended if custom test configuration is needed. +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-techdocs@1.1.1-next.2 + - @backstage/plugin-techdocs-react@0.1.1-next.2 + - @backstage/plugin-catalog@1.2.0-next.2 + - @backstage/plugin-search-react@0.2.0-next.2 + - @backstage/core-app-api@1.0.2-next.1 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration-react@1.1.0-next.2 + - @backstage/test-utils@1.1.0-next.2 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/techdocs-addons-test-utils/api-report.md b/plugins/techdocs-addons-test-utils/api-report.md index a32d2d4854..3808b65b84 100644 --- a/plugins/techdocs-addons-test-utils/api-report.md +++ b/plugins/techdocs-addons-test-utils/api-report.md @@ -10,30 +10,23 @@ import { screen as screen_2 } from 'testing-library__dom'; import { TechDocsEntityMetadata } from '@backstage/plugin-techdocs-react'; import { TechDocsMetadata } from '@backstage/plugin-techdocs-react'; -// @public (undocumented) +// @public export class TechDocsAddonTester { - // (undocumented) + protected constructor(addons: ReactElement[]); atPath(path: string): this; - // (undocumented) build(): React_2.ReactElement< any, string | React_2.JSXElementConstructor >; - // (undocumented) static buildAddonsInTechDocs(addons: ReactElement[]): TechDocsAddonTester; - // (undocumented) renderWithEffects(): Promise< typeof screen_2 & { shadowRoot: ShadowRoot | null; } >; - // (undocumented) - withApis(apis: TechdocsAddonTesterApis): this; - // (undocumented) + withApis(apis: TechdocsAddonTesterApis): this; withDom(dom: ReactElement): this; - // (undocumented) withEntity(entity: Partial): this; - // (undocumented) withMetadata(metadata: Partial): this; } ``` diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index ef4e01d304..55d8685a28 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": "0.1.0-next.0", + "version": "0.1.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,15 +32,15 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/integration-react": "^1.1.0-next.1", - "@backstage/plugin-catalog": "^1.2.0-next.1", - "@backstage/plugin-search-react": "^0.2.0-next.1", - "@backstage/plugin-techdocs": "^1.1.1-next.1", - "@backstage/plugin-techdocs-react": "^0.1.1-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/core-components": "^0.9.4-next.1", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/integration-react": "^1.1.0-next.2", + "@backstage/plugin-catalog": "^1.2.0-next.2", + "@backstage/plugin-search-react": "^0.2.0-next.2", + "@backstage/plugin-techdocs": "^1.1.1-next.2", + "@backstage/plugin-techdocs-react": "^0.1.1-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", @@ -56,8 +56,8 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/dev-utils": "^1.0.2-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/dev-utils": "^1.0.2-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/techdocs-addons-test-utils/src/test-utils.tsx b/plugins/techdocs-addons-test-utils/src/test-utils.tsx index 7894b96154..2c20199038 100644 --- a/plugins/techdocs-addons-test-utils/src/test-utils.tsx +++ b/plugins/techdocs-addons-test-utils/src/test-utils.tsx @@ -46,6 +46,7 @@ const techdocsApi = { const techdocsStorageApi = { getApiOrigin: jest.fn(), + getBaseUrl: jest.fn(), getEntityDocs: jest.fn(), syncEntityDocs: jest.fn(), }; @@ -64,14 +65,18 @@ type TechDocsAddonTesterTestApiPair = TApi extends infer TImpl : never; /** @ignore */ -type TechdocsAddonTesterApis = TechDocsAddonTesterTestApiPair[]; +type TechdocsAddonTesterApis = { + [TIndex in keyof TApiPairs]: TechDocsAddonTesterTestApiPair< + TApiPairs[TIndex] + >; +}; type TechDocsAddonTesterOptions = { dom: ReactElement; entity: Partial; metadata: Partial; componentId: string; - apis: TechdocsAddonTesterApis; + apis: TechdocsAddonTesterApis; path: string; }; @@ -108,22 +113,40 @@ const defaultDom = ( ); /** + * Utility class for rendering TechDocs Addons end-to-end within the TechDocs + * reader page, with a set of givens (e.g. page DOM, metadata, etc). + * + * @example + * ```tsx + * const { getByText } = await TechDocsAddonTester.buildAddonsInTechDocs([]) + * .withDom(TEST_CONTENT) + * .renderWithEffects(); + * + * expect(getByText('TEST_CONTENT')).toBeInTheDocument(); + * ``` + * * @public */ - export class TechDocsAddonTester { private options: TechDocsAddonTesterOptions = defaultOptions; private addons: ReactElement[]; + /** + * Get a TechDocsAddonTester instance for a given set of Addons. + */ static buildAddonsInTechDocs(addons: ReactElement[]) { return new TechDocsAddonTester(addons); } - private constructor(addons: ReactElement[]) { + // Protected in order to allow extension but not direct instantiation. + protected constructor(addons: ReactElement[]) { this.addons = addons; } - withApis(apis: TechdocsAddonTesterApis) { + /** + * Provide mock API implementations if your Addon expects any. + */ + withApis(apis: TechdocsAddonTesterApis) { const refs = apis.map(([ref]) => ref); this.options.apis = this.options.apis .filter(([ref]) => !refs.includes(ref)) @@ -131,28 +154,46 @@ export class TechDocsAddonTester { return this; } + /** + * Provide mock HTML if your Addon expects it in the shadow DOM. + */ withDom(dom: ReactElement) { this.options.dom = dom; return this; } + /** + * Provide mock techdocs_metadata.json values if your Addon needs it. + */ withMetadata(metadata: Partial) { this.options.metadata = metadata; return this; } + /** + * Provide a mock entity if your Addon needs it. This also controls the base + * path at which the Addon is rendered. + */ withEntity(entity: Partial) { this.options.entity = entity; return this; } + /** + * Provide the TechDocs page path at which the Addon is rendered (e.g. the + * part of the path after the entity namespace/kind/name). + */ atPath(path: string) { this.options.path = path; return this; } + /** + * Return a fully configured and mocked TechDocs reader page within a test + * App instance, using the given Addon(s). + */ build() { - const apis: TechdocsAddonTesterApis = [ + const apis: TechdocsAddonTesterApis = [ [techdocsApiRef, techdocsApi], [techdocsStorageApiRef, techdocsStorageApi], [searchApiRef, searchApi], @@ -179,7 +220,9 @@ export class TechDocsAddonTester { techdocsStorageApi.getApiOrigin.mockResolvedValue( 'https://backstage.example.com/api/techdocs', ); - + techdocsStorageApi.getBaseUrl.mockResolvedValue( + `https://backstage.example.com/api/techdocs/${entityName.namespace}/${entityName.kind}/${entityName.name}/${this.options.path}`, + ); techdocsStorageApi.getEntityDocs.mockResolvedValue( renderToStaticMarkup(this.options.dom || defaultDom), ); @@ -215,11 +258,19 @@ export class TechDocsAddonTester { }); } - // Components using useEffect to perform an asynchronous action (such as fetch) must be rendered within an async - // act call to properly get the final state, even with mocked responses. This utility method makes the signature a bit - // cleaner, since act doesn't return the result of the evaluated function. - // https://github.com/testing-library/react-testing-library/issues/281 - // https://github.com/facebook/react/pull/14853 + /** + * Render the Addon within a fully configured and mocked TechDocs reader. + * + * @remarks + * Components using useEffect to perform an asynchronous action (such as + * fetch) must be rendered within an async act call to properly get the final + * state, even with mocked responses. This utility method makes the signature + * a bit cleaner, since act doesn't return the result of the evaluated + * function. + * + * @see https://github.com/testing-library/react-testing-library/issues/281 + * @see https://github.com/facebook/react/pull/14853 + */ async renderWithEffects(): Promise< typeof screen & { shadowRoot: ShadowRoot | null } > { diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index b6f750865b..ddaecb0f1f 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-techdocs-backend +## 1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/plugin-permission-common@0.6.1-next.0 + - @backstage/plugin-techdocs-node@1.1.1-next.1 + - @backstage/catalog-client@1.0.2-next.0 + - @backstage/plugin-catalog-common@1.0.2-next.0 + ## 1.1.1-next.0 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index c88b970474..124de18d8e 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.1.1-next.0", + "version": "1.1.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,16 +34,16 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/catalog-client": "^1.0.1", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/catalog-client": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/plugin-catalog-common": "^1.0.1", - "@backstage/plugin-permission-common": "^0.6.0", - "@backstage/plugin-search-common": "^0.3.3", - "@backstage/plugin-techdocs-node": "^1.1.1-next.0", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/plugin-catalog-common": "^1.0.2-next.0", + "@backstage/plugin-permission-common": "^0.6.1-next.0", + "@backstage/plugin-search-common": "^0.3.4-next.0", + "@backstage/plugin-techdocs-node": "^1.1.1-next.1", "@types/express": "^4.17.6", "dockerode": "^3.3.1", "express": "^4.17.1", @@ -56,9 +56,9 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.24-next.0", - "@backstage/cli": "^0.17.1-next.0", - "@backstage/plugin-search-backend-node": "0.6.1-next.0", + "@backstage/backend-test-utils": "^0.1.24-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/plugin-search-backend-node": "0.6.1-next.1", "@types/dockerode": "^3.3.0", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 30c428220c..076bc12bb8 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 0.1.0-next.2 + +### Patch Changes + +- 52419be116: Create a TechDocs `` addon that allows users to set a font size in the browser's local storage for the text of documentation pages. + + Here's an example on how to use it in a Backstage app: + + ```diff + import { + DefaultTechDocsHome, + TechDocsIndexPage, + TechDocsReaderPage, + } from '@backstage/plugin-techdocs'; + import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; + +import { TextSize } from '@backstage/plugin-techdocs-module-addons-contrib'; + + const AppRoutes = () => { + + // other plugin routes + }> + + + } + > + + + + + + ; + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-techdocs-react@0.1.1-next.2 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/integration-react@1.1.0-next.2 + ## 0.1.0-next.1 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/api-report.md b/plugins/techdocs-module-addons-contrib/api-report.md index 076b05957c..19d2f70a2b 100644 --- a/plugins/techdocs-module-addons-contrib/api-report.md +++ b/plugins/techdocs-module-addons-contrib/api-report.md @@ -10,19 +10,19 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; // @public export const ReportIssue: (props: ReportIssueProps) => JSX.Element | null; -// @public (undocumented) +// @public export type ReportIssueProps = { debounceTime?: number; templateBuilder?: ReportIssueTemplateBuilder; }; -// @public (undocumented) +// @public export type ReportIssueTemplate = { title: string; body: string; }; -// @public (undocumented) +// @public export type ReportIssueTemplateBuilder = ({ selection, }: { @@ -31,4 +31,7 @@ export type ReportIssueTemplateBuilder = ({ // @public export const techdocsModuleAddonsContribPlugin: BackstagePlugin<{}, {}>; + +// @public +export const TextSize: (props: unknown) => JSX.Element | null; ``` diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 79224ef5fb..8a1801f0ba 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": "0.1.0-next.1", + "version": "0.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,11 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/integration-react": "^1.1.0-next.1", - "@backstage/plugin-techdocs-react": "^0.1.1-next.1", + "@backstage/core-components": "^0.9.4-next.1", + "@backstage/core-plugin-api": "^1.0.2-next.1", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/integration-react": "^1.1.0-next.2", + "@backstage/plugin-techdocs-react": "^0.1.1-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", @@ -50,11 +50,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/plugin-techdocs-addons-test-utils": "^0.1.0-next.0", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/plugin-techdocs-addons-test-utils": "^0.1.0-next.1", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/techdocs-module-addons-contrib/src/ReportIssue/ReportIssue.tsx b/plugins/techdocs-module-addons-contrib/src/ReportIssue/ReportIssue.tsx index 2fe8d604e6..c8caa5ddbc 100644 --- a/plugins/techdocs-module-addons-contrib/src/ReportIssue/ReportIssue.tsx +++ b/plugins/techdocs-module-addons-contrib/src/ReportIssue/ReportIssue.tsx @@ -49,10 +49,21 @@ type Style = { }; /** + * Props customizing the Addon. + * * @public */ export type ReportIssueProps = { + /** + * Number of milliseconds after a user highlights some text before the report + * issue link appears above the highlighted text. Defaults to 500ms. + */ debounceTime?: number; + + /** + * An optional function defining how a custom issue title and body should be + * constructed, given some selected text. + */ templateBuilder?: ReportIssueTemplateBuilder; }; diff --git a/plugins/techdocs-module-addons-contrib/src/ReportIssue/types.ts b/plugins/techdocs-module-addons-contrib/src/ReportIssue/types.ts index a4780535ca..0816b45d9d 100644 --- a/plugins/techdocs-module-addons-contrib/src/ReportIssue/types.ts +++ b/plugins/techdocs-module-addons-contrib/src/ReportIssue/types.ts @@ -15,14 +15,26 @@ */ /** + * Properties for creating an issue in a remote issue tracker. + * * @public */ export type ReportIssueTemplate = { + /** + * The title of the issue. + */ title: string; + + /** + * The body or description of the issue. + */ body: string; }; /** + * A function for returning a custom issue template, given a selection of text + * on a TechDocs page. + * * @public */ export type ReportIssueTemplateBuilder = ({ diff --git a/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.test.tsx b/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.test.tsx new file mode 100644 index 0000000000..282d54a0b6 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.test.tsx @@ -0,0 +1,124 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TechDocsAddonTester } from '@backstage/plugin-techdocs-addons-test-utils'; + +import React from 'react'; + +import { fireEvent, waitFor } from '@testing-library/react'; + +import { TextSize } from '..'; + +describe('TextSize', () => { + it('renders without exploding', async () => { + const { getByText } = await TechDocsAddonTester.buildAddonsInTechDocs([ + , + ]) + .withDom(TEST_CONTENT) + .renderWithEffects(); + + expect(getByText('TEST_CONTENT')).toBeInTheDocument(); + }); + + it('changes content text size using slider', async () => { + const { getByTitle, getByText, getByRole, getByDisplayValue } = + await TechDocsAddonTester.buildAddonsInTechDocs([]) + .withDom(TEST_CONTENT) + .renderWithEffects(); + + fireEvent.click(getByTitle('Settings')); + + await waitFor(() => { + expect(getByText('Text size')).toBeInTheDocument(); + }); + + const slider = getByRole('slider'); + + slider.focus(); + + fireEvent.keyDown(slider, { + key: 'ArrowRight', + }); + + await waitFor(() => { + expect(getByDisplayValue('115')).toBeInTheDocument(); + }); + + expect(slider).toHaveTextContent('115%'); + + let style = getComputedStyle(getByText('TEST_CONTENT')); + + expect(style.getPropertyValue('--md-typeset-font-size')).toBe('18.4px'); + + fireEvent.keyDown(slider, { + key: 'ArrowLeft', + }); + + await waitFor(() => { + expect(getByDisplayValue('100')).toBeInTheDocument(); + }); + + expect(slider).toHaveTextContent('100%'); + + style = getComputedStyle(getByText('TEST_CONTENT')); + + expect(style.getPropertyValue('--md-typeset-font-size')).toBe('16px'); + }); + + it('changes content text size using buttons', async () => { + const { + getByTitle, + getByText, + getByRole, + getByLabelText, + getByDisplayValue, + } = await TechDocsAddonTester.buildAddonsInTechDocs([]) + .withDom(TEST_CONTENT) + .renderWithEffects(); + + fireEvent.click(getByTitle('Settings')); + + await waitFor(() => { + expect(getByText('Text size')).toBeInTheDocument(); + }); + + fireEvent.click(getByLabelText('Increase text size')); + + await waitFor(() => { + expect(getByDisplayValue('115')).toBeInTheDocument(); + }); + + const slider = getByRole('slider'); + + expect(slider).toHaveTextContent('115%'); + + let style = getComputedStyle(getByText('TEST_CONTENT')); + + expect(style.getPropertyValue('--md-typeset-font-size')).toBe('18.4px'); + + fireEvent.click(getByLabelText('Decrease text size')); + + await waitFor(() => { + expect(getByDisplayValue('100')).toBeInTheDocument(); + }); + + expect(slider).toHaveTextContent('100%'); + + style = getComputedStyle(getByText('TEST_CONTENT')); + + expect(style.getPropertyValue('--md-typeset-font-size')).toBe('16px'); + }); +}); diff --git a/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.tsx b/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.tsx new file mode 100644 index 0000000000..fc865c7826 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.tsx @@ -0,0 +1,243 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { + ChangeEvent, + MouseEvent, + useMemo, + useState, + useEffect, + useCallback, +} from 'react'; + +import { + withStyles, + makeStyles, + useTheme, + Box, + MenuItem, + ListItemText, + Slider, + IconButton, + Typography, +} from '@material-ui/core'; +import AddIcon from '@material-ui/icons/Add'; +import RemoveIcon from '@material-ui/icons/Remove'; + +import { BackstageTheme } from '@backstage/theme'; +import { useShadowRootElements } from '@backstage/plugin-techdocs-react'; + +const boxShadow = + '0 3px 1px rgba(0,0,0,0.1),0 4px 8px rgba(0,0,0,0.13),0 0 0 1px rgba(0,0,0,0.02)'; + +const StyledSlider = withStyles(theme => ({ + root: { + height: 2, + padding: '15px 0', + }, + thumb: { + height: 18, + width: 18, + backgroundColor: theme.palette.common.white, + boxShadow: boxShadow, + marginTop: -9, + marginLeft: -9, + '&:focus, &:hover, &$active': { + boxShadow: + '0 3px 1px rgba(0,0,0,0.1),0 4px 8px rgba(0,0,0,0.3),0 0 0 1px rgba(0,0,0,0.02)', + // Reset on touch devices, it doesn't add specificity + '@media (hover: none)': { + boxShadow: boxShadow, + }, + }, + }, + active: {}, + valueLabel: { + top: '100%', + left: '50%', + transform: 'scale(1) translate(-50%, -5px) !important', + '& *': { + color: theme.palette.common.black, + fontSize: theme.typography.caption.fontSize, + background: 'transparent', + }, + }, + track: { + height: 2, + }, + rail: { + height: 2, + opacity: 0.5, + }, + mark: { + height: 10, + width: 1, + marginTop: -4, + }, + markActive: { + opacity: 1, + backgroundColor: 'currentColor', + }, +}))(Slider); + +const settings = { + key: 'techdocs.addons.settings.textsize', + defaultValue: 100, +}; + +const marks = [ + { + value: 90, + }, + { + value: 100, + }, + { + value: 115, + }, + { + value: 130, + }, + { + value: 150, + }, +]; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + container: { + color: theme.palette.textSubtle, + display: 'flex', + alignItems: 'center', + margin: 0, + minWidth: 200, + }, + menuItem: { + '&:hover': { + background: 'transparent', + }, + }, + decreaseButton: { + marginRight: theme.spacing(1), + }, + increaseButton: { + marginLeft: theme.spacing(1), + }, +})); + +export const TextSizeAddon = () => { + const classes = useStyles(); + const theme = useTheme(); + const [body] = useShadowRootElements(['body']); + + const [value, setValue] = useState(() => { + const initialValue = localStorage?.getItem(settings.key); + return initialValue ? parseInt(initialValue, 10) : settings.defaultValue; + }); + + const values = useMemo(() => marks.map(mark => mark.value), []); + const index = useMemo(() => values.indexOf(value), [values, value]); + const min = useMemo(() => values[0], [values]); + const max = useMemo(() => values[values.length - 1], [values]); + + const getValueText = useCallback(() => `${value}%`, [value]); + + const handleChangeCommitted = useCallback( + (_event: ChangeEvent<{}>, newValue: number | number[]) => { + if (!Array.isArray(newValue)) { + setValue(newValue); + localStorage?.setItem(settings.key, String(newValue)); + } + }, + [setValue], + ); + + const handleDecreaseClick = useCallback( + (event: MouseEvent) => { + handleChangeCommitted(event, values[index - 1]); + }, + [index, values, handleChangeCommitted], + ); + + const handleIncreaseClick = useCallback( + (event: MouseEvent) => { + handleChangeCommitted(event, values[index + 1]); + }, + [index, values, handleChangeCommitted], + ); + + useEffect(() => { + if (!body) return; + const htmlFontSize = + ( + theme.typography as BackstageTheme['typography'] & { + htmlFontSize?: number; + } + )?.htmlFontSize ?? 16; + body.style.setProperty( + '--md-typeset-font-size', + `${htmlFontSize * (value / 100)}px`, + ); + }, [body, value, theme]); + + return ( + + + Text size + + } + secondary={ + + + + + + + + + + } + disableTypography + /> + + ); +}; diff --git a/plugins/techdocs-module-addons-contrib/src/TextSize/index.ts b/plugins/techdocs-module-addons-contrib/src/TextSize/index.ts new file mode 100644 index 0000000000..ffcf655f63 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/TextSize/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './TextSize'; diff --git a/plugins/techdocs-module-addons-contrib/src/index.ts b/plugins/techdocs-module-addons-contrib/src/index.ts index 09fe1f8671..e2e57b15d1 100644 --- a/plugins/techdocs-module-addons-contrib/src/index.ts +++ b/plugins/techdocs-module-addons-contrib/src/index.ts @@ -20,7 +20,11 @@ * @packageDocumentation */ -export { techdocsModuleAddonsContribPlugin, ReportIssue } from './plugin'; +export { + techdocsModuleAddonsContribPlugin, + ReportIssue, + TextSize, +} from './plugin'; export type { ReportIssueProps, ReportIssueTemplate, diff --git a/plugins/techdocs-module-addons-contrib/src/plugin.ts b/plugins/techdocs-module-addons-contrib/src/plugin.ts index e71ec2a5c7..0d7743da9e 100644 --- a/plugins/techdocs-module-addons-contrib/src/plugin.ts +++ b/plugins/techdocs-module-addons-contrib/src/plugin.ts @@ -20,6 +20,7 @@ import { TechDocsAddonLocations, } from '@backstage/plugin-techdocs-react'; import { ReportIssueAddon, ReportIssueProps } from './ReportIssue'; +import { TextSizeAddon } from './TextSize'; /** * The TechDocs addons contrib plugin @@ -44,3 +45,49 @@ export const ReportIssue = techdocsModuleAddonsContribPlugin.provide( component: ReportIssueAddon, }), ); + +/** + * This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. + * + * @remarks + * The default value for the font size is 100% of the HTML font size, if the theme does not have a `htmlFontSize` in its typography object, the addon will assume 16px as 100%, and remember, this setting is kept in the browser local storage. + * + * @example + * Here's a simple example: + * ``` + * import { + * DefaultTechDocsHome, + * TechDocsIndexPage, + * TechDocsReaderPage, + * } from '@backstage/plugin-techdocs'; + * import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; + * import { TextSize } from '@backstage/plugin-techdocs-module-addons-contrib'; + * + * + * const AppRoutes = () => { + * + * // other plugin routes + * }> + * + * + * } + * > + * + * + * + * + * ; + * }; + * ``` + * + * @public + */ +export const TextSize = techdocsModuleAddonsContribPlugin.provide( + createTechDocsAddonExtension({ + name: 'TextSize', + location: TechDocsAddonLocations.Settings, + component: TextSizeAddon, + }), +); diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index 8fa2b168d3..b56e6c9287 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-techdocs-node +## 1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + ## 1.1.1-next.0 ### Patch Changes diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index d099f7351a..c584dec40c 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -219,7 +219,7 @@ export class TechdocsGenerator implements GeneratorBase { config: Config; scmIntegrations: ScmIntegrationRegistry; }); - static readonly defaultDockerImage = 'spotify/techdocs:v1.0.2'; + static readonly defaultDockerImage = 'spotify/techdocs:v1.0.3'; static fromConfig( config: Config, options: GeneratorOptions, diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index ff164bad93..930e7f9fde 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.1.1-next.0", + "version": "1.1.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -42,12 +42,12 @@ "dependencies": { "@azure/identity": "^2.0.1", "@azure/storage-blob": "^12.5.0", - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/plugin-search-common": "^0.3.3", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/plugin-search-common": "^0.3.4-next.0", "@google-cloud/storage": "^5.6.0", "@trendyol-js/openstack-swift-sdk": "^0.0.5", "@types/express": "^4.17.6", @@ -64,7 +64,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/fs-extra": "^9.0.5", "@types/js-yaml": "^4.0.0", "@types/mime-types": "^2.1.0", diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index 41b17d3bc6..660b8e8cb5 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -53,7 +53,7 @@ export class TechdocsGenerator implements GeneratorBase { * The default docker image (and version) used to generate content. Public * and static so that techdocs-node consumers can use the same version. */ - public static readonly defaultDockerImage = 'spotify/techdocs:v1.0.2'; + public static readonly defaultDockerImage = 'spotify/techdocs:v1.0.3'; private readonly logger: Logger; private readonly containerRunner: ContainerRunner; private readonly options: GeneratorConfig; diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index ae06a45ff3..bb1f2b3097 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-techdocs-react +## 0.1.1-next.2 + +### Patch Changes + +- 52419be116: Create a new addon location called "Settings", it is designed for addons that allow users to customize the reading experience in documentation pages. + + Usage example: + + ```tsx + const TextSize = techdocsModuleAddonsContribPlugin.provide( + createTechDocsAddonExtension({ + name: 'TextSize', + location: TechDocsAddonLocations.Settings, + component: TextSizeAddon, + }), + ); + ``` + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/techdocs-react/api-report.md b/plugins/techdocs-react/api-report.md index fa38feef14..e96cbebd1c 100644 --- a/plugins/techdocs-react/api-report.md +++ b/plugins/techdocs-react/api-report.md @@ -14,37 +14,35 @@ import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { SetStateAction } from 'react'; -// @alpha +// @public export function createTechDocsAddonExtension( options: TechDocsAddonOptions, ): Extension<(props: TComponentProps) => JSX.Element | null>; -// @alpha (undocumented) -export const defaultTechDocsReaderPageValue: TechDocsReaderPageValue; - // @public export type SyncResult = 'cached' | 'updated'; -// @alpha +// @public export const TECHDOCS_ADDONS_WRAPPER_KEY = 'techdocs.addons.wrapper.v1'; -// @alpha +// @public export const TechDocsAddonLocations: Readonly<{ readonly Header: 'Header'; readonly Subheader: 'Subheader'; + readonly Settings: 'Settings'; readonly PrimarySidebar: 'PrimarySidebar'; readonly SecondarySidebar: 'SecondarySidebar'; readonly Content: 'Content'; }>; -// @alpha +// @public export type TechDocsAddonOptions = { name: string; location: keyof typeof TechDocsAddonLocations; component: ComponentType; }; -// @alpha +// @public export const TechDocsAddons: React_2.ComponentType; // @public @@ -132,20 +130,20 @@ export interface TechDocsStorageApi { // @public export const techdocsStorageApiRef: ApiRef; -// @alpha +// @public export const useShadowRoot: () => ShadowRoot | undefined; -// @alpha +// @public export const useShadowRootElements: < TReturnedElement extends HTMLElement = HTMLElement, >( selectors: string[], ) => TReturnedElement[]; -// @alpha +// @public export const useShadowRootSelection: (wait?: number) => Selection | null; -// @alpha +// @public export const useTechDocsAddons: () => { renderComponentByName: (name: string) => JSX.Element | null; renderComponentsByLocation: ( @@ -153,6 +151,6 @@ export const useTechDocsAddons: () => { ) => (JSX.Element | null)[] | null; }; -// @alpha +// @public export const useTechDocsReaderPage: () => TechDocsReaderPageValue; ``` diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 2d967e1062..9bd0d10e39 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": "0.1.1-next.1", + "version": "0.1.1-next.2", "private": false, "publishConfig": { "access": "public", @@ -35,9 +35,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.1", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/version-bridge": "^1.0.1", "@material-ui/core": "^4.12.2", "@material-ui/lab": "4.0.0-alpha.57", @@ -55,7 +55,7 @@ "devDependencies": { "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/test-utils": "^1.1.0-next.2", "@backstage/theme": "^0.2.15" }, "files": [ diff --git a/plugins/techdocs-react/src/addons.tsx b/plugins/techdocs-react/src/addons.tsx index 39d110bee3..49aa5b1bcc 100644 --- a/plugins/techdocs-react/src/addons.tsx +++ b/plugins/techdocs-react/src/addons.tsx @@ -31,13 +31,13 @@ export const TECHDOCS_ADDONS_KEY = 'techdocs.addons.addon.v1'; /** * Marks the registry component. - * @alpha + * @public */ export const TECHDOCS_ADDONS_WRAPPER_KEY = 'techdocs.addons.wrapper.v1'; /** * TechDocs Addon registry. - * @alpha + * @public */ export const TechDocsAddons: React.ComponentType = () => null; @@ -49,7 +49,7 @@ const getDataKeyByName = (name: string) => { /** * Create a TechDocs addon. - * @alpha + * @public */ export function createTechDocsAddonExtension( options: TechDocsAddonOptions, @@ -96,7 +96,7 @@ const getAllTechDocsAddonsData = (collection: ElementCollection) => { /** * hook to use addons in components - * @alpha + * @public */ export const useTechDocsAddons = () => { const node = useOutlet(); diff --git a/plugins/techdocs-react/src/context.tsx b/plugins/techdocs-react/src/context.tsx index 67bf416818..4f2fa26164 100644 --- a/plugins/techdocs-react/src/context.tsx +++ b/plugins/techdocs-react/src/context.tsx @@ -66,10 +66,7 @@ export type TechDocsReaderPageValue = { onReady?: () => void; }; -/** - * @alpha - */ -export const defaultTechDocsReaderPageValue: TechDocsReaderPageValue = { +const defaultTechDocsReaderPageValue: TechDocsReaderPageValue = { title: '', subtitle: '', setTitle: () => {}, @@ -153,7 +150,7 @@ export const TechDocsReaderPageProvider = memo( /** * Hook used to get access to shared state between reader page components. - * @alpha + * @public */ export const useTechDocsReaderPage = () => { const versionedContext = useContext(TechDocsReaderPageContext); diff --git a/plugins/techdocs-react/src/hooks.ts b/plugins/techdocs-react/src/hooks.ts index cc141c9e15..560c548156 100644 --- a/plugins/techdocs-react/src/hooks.ts +++ b/plugins/techdocs-react/src/hooks.ts @@ -20,7 +20,7 @@ import { useTechDocsReaderPage } from './context'; /** * Hook for use within TechDocs addons that provides access to the underlying * shadow root of the current page, allowing the DOM within to be mutated. - * @alpha + * @public */ export const useShadowRoot = () => { const { shadowRoot } = useTechDocsReaderPage(); @@ -31,7 +31,7 @@ export const useShadowRoot = () => { * Convenience hook for use within TechDocs addons that provides access to * elements that match a given selector within the shadow root. * - * @alpha + * @public */ export const useShadowRootElements = < TReturnedElement extends HTMLElement = HTMLElement, @@ -58,7 +58,7 @@ const isValidSelection = (newSelection: Selection) => { /** * Hook for retreiving a selection within the ShadowRoot. - * @alpha + * @public */ export const useShadowRootSelection = (wait: number = 0) => { const shadowRoot = useShadowRoot(); diff --git a/plugins/techdocs-react/src/index.ts b/plugins/techdocs-react/src/index.ts index c1cc3a1791..d4de5f0d29 100644 --- a/plugins/techdocs-react/src/index.ts +++ b/plugins/techdocs-react/src/index.ts @@ -28,11 +28,7 @@ export { } from './addons'; export { techdocsApiRef, techdocsStorageApiRef } from './api'; export type { SyncResult, TechDocsApi, TechDocsStorageApi } from './api'; -export { - defaultTechDocsReaderPageValue, - TechDocsReaderPageProvider, - useTechDocsReaderPage, -} from './context'; +export { TechDocsReaderPageProvider, useTechDocsReaderPage } from './context'; export type { TechDocsReaderPageProviderProps, TechDocsReaderPageProviderRenderFunction, diff --git a/plugins/techdocs-react/src/types.ts b/plugins/techdocs-react/src/types.ts index de74d4f284..d1fcc91db0 100644 --- a/plugins/techdocs-react/src/types.ts +++ b/plugins/techdocs-react/src/types.ts @@ -38,7 +38,7 @@ export type TechDocsEntityMetadata = Entity & { /** * Locations for which TechDocs addons may be declared and rendered. - * @alpha + * @public */ export const TechDocsAddonLocations = Object.freeze({ /** @@ -53,6 +53,12 @@ export const TechDocsAddonLocations = Object.freeze({ */ Subheader: 'Subheader', + /** + * These addons are items added to the settings menu list and are designed to make + * the reader experience customizable, for example accessibility options + */ + Settings: 'Settings', + /** * These addons appear left of the content and above the navigation. */ @@ -102,7 +108,7 @@ export const TechDocsAddonLocations = Object.freeze({ /** * Options for creating a TechDocs addon. - * @alpha + * @public */ export type TechDocsAddonOptions = { name: string; diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 8717877fb7..f080aa4e2d 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-techdocs +## 1.1.1-next.3 + +### Patch Changes + +- cc8ddd0979: revert dependency `event-source-polyfill` to `1.0.25` +- Updated dependencies + - @backstage/core-components@0.9.4-next.2 + +## 1.1.1-next.2 + +### Patch Changes + +- 52419be116: Create a menu in the sub header of documentation pages, it is responsible for rendering TechDocs addons that allow users to customize their reading experience. +- 1af133f779: Updated dependency `event-source-polyfill` to `1.0.26`. +- 2dcb2c9678: Loading SVGs correctly with `bota` with extended characters +- 3a74e203a8: Updated search result components to support rendering content with highlighted matched terms +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-techdocs-react@0.1.1-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/plugin-search-react@0.2.0-next.2 + - @backstage/plugin-search-common@0.3.4-next.0 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + - @backstage/integration@1.2.0-next.1 + - @backstage/integration-react@1.1.0-next.2 + ## 1.1.1-next.1 ### Patch Changes diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index 131a3a062a..a8204bc9af 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -17,6 +17,7 @@ import { IdentityApi } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; +import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; import { TableColumn } from '@backstage/core-components'; import { TableProps } from '@backstage/core-components'; @@ -388,6 +389,7 @@ export const TechDocsSearchResultListItem: ( // @public export type TechDocsSearchResultListItemProps = { result: any; + highlight?: ResultHighlight; lineClamp?: number; asListItem?: boolean; asLink?: boolean; diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index ea899088dd..439cac40c0 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.1.1-next.1", + "version": "1.1.1-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,30 +35,30 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", - "@backstage/integration-react": "^1.1.0-next.1", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", - "@backstage/plugin-search-react": "^0.2.0-next.1", - "@backstage/plugin-techdocs-react": "^0.1.1-next.1", + "@backstage/integration": "^1.2.0-next.1", + "@backstage/integration-react": "^1.1.0-next.2", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", + "@backstage/plugin-search-common": "^0.3.4-next.0", + "@backstage/plugin-search-react": "^0.2.0-next.2", + "@backstage/plugin-techdocs-react": "^0.1.1-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@material-ui/styles": "^4.10.0", "dompurify": "^2.2.9", - "event-source-polyfill": "1.0.26", + "event-source-polyfill": "1.0.25", "git-url-parse": "^11.6.0", "jss": "~10.8.2", "lodash": "^4.17.21", "react-helmet": "6.1.0", "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", - "react-text-truncate": "^0.18.0", "react-use": "^17.2.4" }, "peerDependencies": { @@ -67,10 +67,10 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx index fbab933571..7c76f75eff 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx @@ -32,7 +32,7 @@ import { TechDocsSearch } from '../../../search'; import { TechDocsStateIndicator } from '../TechDocsStateIndicator'; import { useTechDocsReaderDom } from './dom'; -import { withTechDocsReaderProvider } from './context'; +import { withTechDocsReaderProvider } from '../TechDocsReaderProvider'; const useStyles = makeStyles({ search: { diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx index 7a373ab302..92bfbb2e14 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx @@ -28,7 +28,7 @@ import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { techdocsStorageApiRef } from '@backstage/plugin-techdocs-react'; -import { useTechDocsReader } from './context'; +import { useTechDocsReader } from '../TechDocsReaderProvider'; import { addBaseUrl, @@ -58,14 +58,6 @@ const headings: TypographyHeadingsKeys[] = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']; * Hook that encapsulates the behavior of getting raw HTML and applying * transforms to it in order to make it function at a basic level in the * Backstage UI. - * - * Note: this hook is currently being exported so that we can rapidly iterate - * on alternative implementations that extend core functionality. - * There is no guarantee that this hook will continue to be exported by the - * package in the future! - * - * todo: Make public or stop exporting (see others: "altReaderExperiments") - * @internal */ export const useTechDocsReaderDom = ( entityRef: CompoundEntityRef, diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/index.ts b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/index.ts index a7ea76a5d6..b0e2ff856a 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/index.ts +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/index.ts @@ -16,5 +16,3 @@ export { TechDocsReaderPageContent, Reader } from './TechDocsReaderPageContent'; export type { TechDocsReaderPageContentProps } from './TechDocsReaderPageContent'; -export * from './context'; -export * from './dom'; diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageSubheader/TechDocsReaderPageSubheader.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageSubheader/TechDocsReaderPageSubheader.tsx index e0eb0ad2b0..a0013e81ab 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageSubheader/TechDocsReaderPageSubheader.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageSubheader/TechDocsReaderPageSubheader.tsx @@ -14,9 +14,18 @@ * limitations under the License. */ -import React from 'react'; +import React, { MouseEvent, useState, useCallback } from 'react'; -import { Box, makeStyles, Toolbar, ToolbarProps } from '@material-ui/core'; +import { + Box, + makeStyles, + Toolbar, + ToolbarProps, + Menu, + Tooltip, + IconButton, +} from '@material-ui/core'; +import SettingsIcon from '@material-ui/icons/Settings'; import { TechDocsAddonLocations as locations, @@ -44,31 +53,67 @@ export const TechDocsReaderPageSubheader = ({ toolbarProps?: ToolbarProps; }) => { const classes = useStyles(); + const [anchorEl, setAnchorEl] = useState(null); + + const handleClick = useCallback((event: MouseEvent) => { + setAnchorEl(event.currentTarget); + }, []); + + const handleClose = useCallback(() => { + setAnchorEl(null); + }, []); + const { entityMetadata: { value: entityMetadata, loading: entityMetadataLoading }, } = useTechDocsReaderPage(); + const addons = useTechDocsAddons(); + const subheaderAddons = addons.renderComponentsByLocation( locations.Subheader, ); - if (!subheaderAddons) return null; + const settingsAddons = addons.renderComponentsByLocation(locations.Settings); + + if (!subheaderAddons && !settingsAddons) return null; // No entity metadata = 404. Don't render subheader on 404. if (entityMetadataLoading === false && !entityMetadata) return null; return ( - {subheaderAddons && ( - - {subheaderAddons} - - )} + + {subheaderAddons} + {settingsAddons ? ( + <> + + + + + + + {settingsAddons} + + + ) : null} + ); }; diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/context.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderProvider.tsx similarity index 73% rename from plugins/techdocs/src/reader/components/TechDocsReaderPageContent/context.tsx rename to plugins/techdocs/src/reader/components/TechDocsReaderProvider.tsx index 5779ade90c..8ddc4cad69 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/context.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderProvider.tsx @@ -23,20 +23,10 @@ import React, { import { useParams } from 'react-router-dom'; import { useTechDocsReaderPage } from '@backstage/plugin-techdocs-react'; -import { useReaderState, ReaderState } from '../useReaderState'; +import { useReaderState, ReaderState } from './useReaderState'; const TechDocsReaderContext = createContext({} as ReaderState); -/** - * Note: this hook is currently being exported so that we can rapidly - * iterate on alternative implementations that extend core - * functionality. There is no guarantee that this hook will continue to be - * exported by the package in the future! - * - * todo: Make public or stop exporting (ctrl+f "altReaderExperiments") - * @internal - */ - export const useTechDocsReader = () => useContext(TechDocsReaderContext); /** @@ -73,15 +63,6 @@ export const TechDocsReaderProvider = ({ ); }; -/** - * Note: this HOC is currently being exported so that we can rapidly - * iterate on alternative implementations that extend core - * functionality. There is no guarantee that this HOC will continue to be - * exported by the package in the future! - * - * todo: Make public or stop exporting (ctrl+f "altReaderExperiments") - * @internal - */ export const withTechDocsReaderProvider = (Component: ComponentType) => (props: T) => diff --git a/plugins/techdocs/src/reader/components/TechDocsStateIndicator.tsx b/plugins/techdocs/src/reader/components/TechDocsStateIndicator.tsx index 93694280d7..6967356194 100644 --- a/plugins/techdocs/src/reader/components/TechDocsStateIndicator.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsStateIndicator.tsx @@ -21,7 +21,7 @@ import { Alert } from '@material-ui/lab'; import { TechDocsBuildLogs } from './TechDocsBuildLogs'; import { TechDocsNotFound } from './TechDocsNotFound'; -import { useTechDocsReader } from './TechDocsReaderPageContent'; +import { useTechDocsReader } from './TechDocsReaderProvider'; const useStyles = makeStyles(theme => ({ root: { @@ -35,15 +35,6 @@ const useStyles = makeStyles(theme => ({ }, })); -/** - * Note: this component is currently being exported so that we can rapidly - * iterate on alternative implementations that extend core - * functionality. There is no guarantee that this component will continue to be - * exported by the package in the future! - * - * todo: Make public or stop exporting (ctrl+f "altReaderExperiments") - * @internal - */ export const TechDocsStateIndicator = () => { let StateAlert: JSX.Element | null = null; const classes = useStyles(); diff --git a/plugins/techdocs/src/reader/components/index.ts b/plugins/techdocs/src/reader/components/index.ts index 406d623bda..f063501814 100644 --- a/plugins/techdocs/src/reader/components/index.ts +++ b/plugins/techdocs/src/reader/components/index.ts @@ -14,6 +14,11 @@ * limitations under the License. */ +export { TechDocsReaderProvider } from './TechDocsReaderProvider'; +export type { + TechDocsReaderProviderRenderFunction, + TechDocsReaderProviderProps, +} from './TechDocsReaderProvider'; export type { TechDocsReaderPageProps, TechDocsReaderLayoutProps, @@ -22,5 +27,4 @@ export { TechDocsReaderLayout } from './TechDocsReaderPage'; export * from './TechDocsReaderPageHeader'; export * from './TechDocsReaderPageContent'; export * from './TechDocsReaderPageSubheader'; -export * from './TechDocsStateIndicator'; export type { ReaderState, ContentStateTypes } from './useReaderState'; diff --git a/plugins/techdocs/src/reader/transformers/addBaseUrl.ts b/plugins/techdocs/src/reader/transformers/addBaseUrl.ts index 2e3b853e42..96a5888a2a 100644 --- a/plugins/techdocs/src/reader/transformers/addBaseUrl.ts +++ b/plugins/techdocs/src/reader/transformers/addBaseUrl.ts @@ -69,7 +69,9 @@ export const addBaseUrl = ({ const svgContent = await svg.text(); elem.setAttribute( attributeName, - `data:image/svg+xml;base64,${btoa(svgContent)}`, + `data:image/svg+xml;base64,${btoa( + unescape(encodeURIComponent(svgContent)), + )}`, ); } catch (e) { elem.setAttribute('alt', `Error: ${elemAttribute}`); diff --git a/plugins/techdocs/src/search/components/TechDocsSearch.tsx b/plugins/techdocs/src/search/components/TechDocsSearch.tsx index f11fa38948..509c991353 100644 --- a/plugins/techdocs/src/search/components/TechDocsSearch.tsx +++ b/plugins/techdocs/src/search/components/TechDocsSearch.tsx @@ -143,13 +143,14 @@ const TechDocsSearchBar = (props: TechDocsSearchProps) => { noOptionsText="No results found" value={null} options={options} - renderOption={({ document }) => ( + renderOption={({ document, highlight }) => ( )} loading={loading} diff --git a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx index db5751654d..6181e05235 100644 --- a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx +++ b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx @@ -17,7 +17,8 @@ import React, { PropsWithChildren } from 'react'; import { Divider, ListItem, ListItemText, makeStyles } from '@material-ui/core'; import { Link } from '@backstage/core-components'; -import TextTruncate from 'react-text-truncate'; +import { ResultHighlight } from '@backstage/plugin-search-common'; +import { HighlightedSearchResultText } from '@backstage/plugin-search-react'; const useStyles = makeStyles({ flexContainer: { @@ -36,6 +37,7 @@ const useStyles = makeStyles({ */ export type TechDocsSearchResultListItemProps = { result: any; + highlight?: ResultHighlight; lineClamp?: number; asListItem?: boolean; asLink?: boolean; @@ -52,31 +54,80 @@ export const TechDocsSearchResultListItem = ( ) => { const { result, + highlight, lineClamp = 5, asListItem = true, asLink = true, title, } = props; const classes = useStyles(); - const TextItem = () => ( - - } - /> - ); + const TextItem = () => { + const resultTitle = highlight?.fields.title ? ( + + ) : ( + result.title + ); + + const entityTitle = highlight?.fields.entityTitle ? ( + + ) : ( + result.entityTitle + ); + + const resultName = highlight?.fields.name ? ( + + ) : ( + result.name + ); + + return ( + + {resultTitle} | {entityTitle ?? resultName} docs + + ) + } + secondary={ + + {highlight?.fields.text ? ( + + ) : ( + result.text + )} + + } + /> + ); + }; const LinkWrapper = ({ children }: PropsWithChildren<{}>) => asLink ? {children} : <>{children}; diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index 637d1dd93f..a16b25a673 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-todo-backend +## 0.1.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.13.3-next.2 + - @backstage/config@1.0.1-next.0 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/integration@1.2.0-next.1 + - @backstage/catalog-client@1.0.2-next.0 + ## 0.1.29-next.0 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 83e21cb0e7..690b9be4e1 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo-backend", "description": "A Backstage backend plugin that lets you browse TODO comments in your source code", - "version": "0.1.29-next.0", + "version": "0.1.29-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,12 +29,12 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.13.3-next.0", - "@backstage/catalog-client": "^1.0.1", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", + "@backstage/backend-common": "^0.13.3-next.2", + "@backstage/catalog-client": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/config": "^1.0.1-next.0", "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.0-next.0", + "@backstage/integration": "^1.2.0-next.1", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -43,7 +43,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.0", + "@backstage/cli": "^0.17.1-next.2", "@types/supertest": "^2.0.8", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index 6d343f7e67..87de10a707 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-todo +## 0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.4-next.1 + - @backstage/plugin-catalog-react@1.1.0-next.2 + - @backstage/catalog-model@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.2-next.1 + ## 0.2.7-next.1 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 36ae1d199e..1185eb6b74 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.7-next.1", + "version": "0.2.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,11 +30,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.0.1", - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/catalog-model": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.0-next.1", + "@backstage/plugin-catalog-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -45,10 +45,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index fa3edcf546..6461ba753b 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -34,8 +34,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,10 +48,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 9112ad9c38..f7396220d7 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -24,8 +24,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.4-next.0", - "@backstage/core-plugin-api": "^1.0.2-next.0", + "@backstage/core-components": "^0.9.4-next.2", + "@backstage/core-plugin-api": "^1.0.2-next.1", "@backstage/errors": "^1.0.0", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", @@ -40,10 +40,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.1-next.1", - "@backstage/core-app-api": "^1.0.2-next.0", - "@backstage/dev-utils": "^1.0.2-next.1", - "@backstage/test-utils": "^1.1.0-next.1", + "@backstage/cli": "^0.17.1-next.2", + "@backstage/core-app-api": "^1.0.2-next.1", + "@backstage/dev-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index f4a7a4dd3b..ae74848af6 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -243,6 +243,7 @@ const NO_WARNING_PACKAGES = [ 'plugins/catalog-common', 'plugins/catalog-graph', 'plugins/catalog-react', + 'plugins/codescene', 'plugins/graphiql', 'plugins/org', 'plugins/periskop', diff --git a/storybook/.storybook/main.js b/storybook/.storybook/main.js index 8ed4949cf3..f493bd2de6 100644 --- a/storybook/.storybook/main.js +++ b/storybook/.storybook/main.js @@ -32,6 +32,7 @@ module.exports = ({ args }) => { return { stories, addons: [ + '@storybook/addon-controls', '@storybook/addon-a11y', '@storybook/addon-actions', '@storybook/addon-links', diff --git a/storybook/package.json b/storybook/package.json index 9a9c7d4a8c..eafe73a991 100644 --- a/storybook/package.json +++ b/storybook/package.json @@ -9,14 +9,15 @@ }, "dependencies": { "@sucrase/webpack-loader": "^2.0.0", - "sucrase": "^3.21.0", "react": "^17.0.2", + "react-dom": "^17.0.2", "react-hot-loader": "^4.13.0", - "react-dom": "^17.0.2" + "sucrase": "^3.21.0" }, "devDependencies": { "@storybook/addon-a11y": "^6.4.21", "@storybook/addon-actions": "^6.4.21", + "@storybook/addon-controls": "^6.4.22", "@storybook/addon-links": "^6.4.21", "@storybook/addon-storysource": "^6.4.21", "@storybook/addons": "^6.4.21", @@ -24,9 +25,9 @@ "storybook-dark-mode": "^1.0.9" }, "peerDependencies": { - "@backstage/theme": "link:../packages/theme", - "@backstage/test-utils": "link:../packages/test-utils", "@backstage/core-app-api": "link:../packages/core-app-api", - "@backstage/core-plugin-api": "link:../packages/core-plugin-api" + "@backstage/core-plugin-api": "link:../packages/core-plugin-api", + "@backstage/test-utils": "link:../packages/test-utils", + "@backstage/theme": "link:../packages/theme" } } diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 4660d682bc..8c6380c291 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -1381,6 +1381,24 @@ util-deprecate "^1.0.2" uuid-browser "^3.1.0" +"@storybook/addon-controls@^6.4.22": + version "6.4.22" + resolved "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.4.22.tgz#42c7f426eb7ba6d335e8e14369d6d13401878665" + integrity sha512-f/M/W+7UTEUnr/L6scBMvksq+ZA8GTfh3bomE5FtWyOyaFppq9k8daKAvdYNlzXAOrUUsoZVJDgpb20Z2VBiSQ== + dependencies: + "@storybook/addons" "6.4.22" + "@storybook/api" "6.4.22" + "@storybook/client-logger" "6.4.22" + "@storybook/components" "6.4.22" + "@storybook/core-common" "6.4.22" + "@storybook/csf" "0.0.2--canary.87bc651.0" + "@storybook/node-logger" "6.4.22" + "@storybook/store" "6.4.22" + "@storybook/theming" "6.4.22" + core-js "^3.8.2" + lodash "^4.17.21" + ts-dedent "^2.0.0" + "@storybook/addon-links@^6.4.21": version "6.4.22" resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.22.tgz#c0ed9e9ef6505cf1562e1476bbc5064c82dadbe2" diff --git a/yarn.lock b/yarn.lock index 1da34a0eec..03a992be5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -44,6 +44,11 @@ "@types/node" "^10.1.0" long "^4.0.0" +"@apollo/utils.logger@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-1.0.0.tgz#6e3460a2250c2ef7c2c3b0be6b5e148a1596f12b" + integrity sha512-dx9XrjyisD2pOa+KsB5RcDbWIAdgC91gJfeyLCgy0ctJMjQe7yZK5kdWaWlaOoCeX0z6YI9iYlg7vMPyMpQF3Q== + "@apollographql/apollo-tools@^0.5.3": version "0.5.3" resolved "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.5.3.tgz#ba241d50f0849150ca0de54fd2927160033bc0bc" @@ -203,7 +208,7 @@ dependencies: tslib "^2.0.0" -"@azure/identity@^2.0.1": +"@azure/identity@^2.0.1", "@azure/identity@^2.0.4": version "2.0.4" resolved "https://registry.npmjs.org/@azure/identity/-/identity-2.0.4.tgz#f5cfde0daf1b9ebaaff3ed6c504f50d7d7c939a5" integrity sha512-ZgFubAsmo7dji63NLPaot6O7pmDfceAUPY57uphSCr0hmRj+Cakqb4SUz5SohCHFtscrhcmejRU903Fowz6iXg== @@ -1423,6 +1428,36 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" +"@backstage/catalog-client@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@backstage/catalog-client/-/catalog-client-1.0.1.tgz#f19888635825b3104b0e293409d924fb5e21feb9" + integrity sha512-2JUEqtR3v361JM6JDjTt8k/tlZd27RB/ZQ2Vwp5seJf4QYXfR9s5AM4M35l/A5vosDKhGrxMAq3t2s4gcH9vVg== + dependencies: + "@backstage/catalog-model" "^1.0.1" + "@backstage/errors" "^1.0.0" + cross-fetch "^3.1.5" + +"@backstage/catalog-model@^1.0.0", "@backstage/catalog-model@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@backstage/catalog-model/-/catalog-model-1.0.1.tgz#16acb8cf52083dd038da7d9fae38811fd88d55e5" + integrity sha512-VxKQ+WzcsxAWtwWyeGw04vTefkmwxi6XweXSNRhNddXAVqsAbDcCYBUc9jylu0bYVXXWYJkEl8kiwyawUloPPQ== + dependencies: + "@backstage/config" "^1.0.0" + "@backstage/errors" "^1.0.0" + "@backstage/types" "^1.0.0" + ajv "^8.10.0" + json-schema "^0.4.0" + lodash "^4.17.21" + uuid "^8.0.0" + +"@backstage/config@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@backstage/config/-/config-1.0.0.tgz#7af40758ae3f8e1d9ef3a07f063a1fd9cf5c364e" + integrity sha512-0M8UPHjCev3i/Puz/DGV7hor/vujx27bpWip5UTjachzBorI5xB0CBV1GfZ1UZMm5R5py7RJ+lKdmSJVFdw9IA== + dependencies: + "@backstage/types" "^1.0.0" + lodash "^4.17.21" + "@backstage/core-components@^0.9.0", "@backstage/core-components@^0.9.3": version "0.9.3" resolved "https://registry.npmjs.org/@backstage/core-components/-/core-components-0.9.3.tgz#79d8bcea06281da492730fe8eb14aa18877b27c4" @@ -1508,6 +1543,14 @@ lodash "^4.17.21" luxon "^2.0.2" +"@backstage/plugin-catalog-common@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@backstage/plugin-catalog-common/-/plugin-catalog-common-1.0.1.tgz#97d70bfb6083e576e2163af19fd096e9f97f7b88" + integrity sha512-zPf8OGSjH+ZftMnjBxTgwLtgapnO1L7fzulLQ2RRaWrUcXGk8N3szQBDcqwxfBFiWSIX1G4vvRi/BGXFMUMlnw== + dependencies: + "@backstage/plugin-permission-common" "^0.6.0" + "@backstage/search-common" "^0.3.3" + "@backstage/plugin-catalog-react@^1.0.0", "@backstage/plugin-catalog-react@^1.0.1": version "1.0.1" resolved "https://registry.npmjs.org/@backstage/plugin-catalog-react/-/plugin-catalog-react-1.0.1.tgz#647cb19bff2885bb4e1e289bb1b751a7e9a36477" @@ -1556,6 +1599,17 @@ react-router "6.0.0-beta.0" react-use "^17.2.4" +"@backstage/plugin-permission-common@^0.6.0": + version "0.6.0" + resolved "https://registry.npmjs.org/@backstage/plugin-permission-common/-/plugin-permission-common-0.6.0.tgz#85464aa10d1f271252775e5eb30ecfd88e2af152" + integrity sha512-wx5TUDFilRqmMJP8TxjR5GuulFFOPHNwoK6eNMuz5ESzLzPhiJDovqaXjqpxsdCVGNb2VJOUlND3SzbwjQ65aA== + dependencies: + "@backstage/config" "^1.0.0" + "@backstage/errors" "^1.0.0" + cross-fetch "^3.1.5" + uuid "^8.0.0" + zod "^3.11.6" + "@backstage/plugin-permission-react@^0.4.0": version "0.4.0" resolved "https://registry.npmjs.org/@backstage/plugin-permission-react/-/plugin-permission-react-0.4.0.tgz#3135b8bbd0e303afafeeae7b9a0d4de7d9e1198c" @@ -1569,6 +1623,14 @@ react-use "^17.2.4" swr "^1.1.2" +"@backstage/plugin-search-common@0.3.3", "@backstage/plugin-search-common@^0.3.3": + version "0.3.3" + resolved "https://registry.npmjs.org/@backstage/plugin-search-common/-/plugin-search-common-0.3.3.tgz#e9251172163731aef61626b3e1ec40504a38cb11" + integrity sha512-CARcpoMFEQJdpe+Rm9m/mPhMOsWM0V+zncIHOLuKlzsMrQRTcwmcFoPqBdtlfdT9wEJTu1bci2ccsDsnZiSrhA== + dependencies: + "@backstage/plugin-permission-common" "^0.6.0" + "@backstage/types" "^1.0.0" + "@backstage/plugin-stack-overflow@^0.1.0": version "0.1.0" resolved "https://registry.npmjs.org/@backstage/plugin-stack-overflow/-/plugin-stack-overflow-0.1.0.tgz#5f5ee8b30d684b7c71f746fe923c16875a62d621" @@ -1588,6 +1650,13 @@ qs "^6.9.4" react-use "^17.2.4" +"@backstage/search-common@^0.3.3": + version "0.3.3" + resolved "https://registry.npmjs.org/@backstage/search-common/-/search-common-0.3.3.tgz#756af22187283b754aefdc436c651231054be269" + integrity sha512-DtWd1Nrpvm2fkJRkw6bW8WeB6cFOvxsJ//o/fcoMsD5NCnaFtE1kFlCEt6QuUl6chAg6d+cX0rU+DJjSIC1rgQ== + dependencies: + "@backstage/plugin-search-common" "0.3.3" + "@balena/dockerignore@^1.0.2": version "1.0.2" resolved "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" @@ -2041,19 +2110,19 @@ dependencies: tiny-lru "7.0.6" -"@eslint/eslintrc@^1.2.2": - version "1.2.2" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz#4989b9e8c0216747ee7cca314ae73791bb281aae" - integrity sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg== +"@eslint/eslintrc@^1.2.3": + version "1.2.3" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz#fcaa2bcef39e13d6e9e7f6271f4cc7cae1174886" + integrity sha512-uGo44hIwoLGNyduRpjdEpovcbMdd+Nv7amtmJxnKmI8xj6yd5LncmSwDa5NgX/41lIFJtkjD6YdVfgEzPfJ5UA== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.3.1" + espree "^9.3.2" globals "^13.9.0" ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" - minimatch "^3.0.4" + minimatch "^3.1.2" strip-json-comments "^3.1.1" "@fmvilas/pseudo-yaml-ast@^0.3.1": @@ -2111,9 +2180,9 @@ xcase "^2.0.1" "@google-cloud/container@^3.0.0": - version "3.0.0" - resolved "https://registry.npmjs.org/@google-cloud/container/-/container-3.0.0.tgz#b28d086152ac19f22f2574b7e0a39774379fb885" - integrity sha512-Jr+QKc6kZ9eehZunvemocB4hDd1nE3OBPo8zb0VX9lv7y+PPxksJl2RPEktFRNs32mQ9/kWLsvjLdGAHYsaOug== + version "3.0.1" + resolved "https://registry.npmjs.org/@google-cloud/container/-/container-3.0.1.tgz#46bcbc05e1d45e0f182f6eda49d82edcc2c0118e" + integrity sha512-5Ae76MFhGJm+PtQM8Wn/2BCOzLH9Aej8HdGRcsF/DA1ejUy+Q6HzwsHPTcyNExRrtxC4jjcB59IQn0fwEVayZQ== dependencies: google-gax "^2.24.1" @@ -2176,10 +2245,10 @@ teeny-request "^7.1.3" xdg-basedir "^4.0.0" -"@graphiql/toolkit@^0.4.3": - version "0.4.3" - resolved "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.4.3.tgz#2653d045693d902f7faaf87b9047e8786397ec48" - integrity sha512-L0l6BezvTXmWZhtdmZxirhYwKzcZToAciQY0A13KRAWSpJ9bb/ZdkBpcz3fOXrsjuJHf0wBr6Vk9kztJ6lV7uA== +"@graphiql/toolkit@^0.4.4": + version "0.4.4" + resolved "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.4.4.tgz#c5f2cd0d7fc47707f68406655836aedc5e6ca2b1" + integrity sha512-HrppQ5u0uJPYpImLqQUJWNrS9E97Cmz8DO3Dn0dXeCg1iBoKjRnZoFf2rjFF5ge9Uc9RihL181Uph/Iw9YYMFg== dependencies: "@n1ru4l/push-pull-async-iterable-iterator" "^3.1.0" meros "^1.1.4" @@ -2241,16 +2310,16 @@ tslib "~2.3.0" "@graphql-codegen/graphql-modules-preset@^2.3.2": - version "2.3.8" - resolved "https://registry.npmjs.org/@graphql-codegen/graphql-modules-preset/-/graphql-modules-preset-2.3.8.tgz#6b7bc5fed2890c1893e1e3779921821265055023" - integrity sha512-mYQG2+cbyG3AB1mKR3bqcUUHinbDpCfU/JzHu48t9S/db0HHDzo00WtUMnYPBPd5gohXJ1D1y4h6noPU0gt8bg== + version "2.3.11" + resolved "https://registry.npmjs.org/@graphql-codegen/graphql-modules-preset/-/graphql-modules-preset-2.3.11.tgz#ba3c8435badfd6ffea0906a53e3fcb20e00602d9" + integrity sha512-nhh2C7Aq98pbVkD9gwwTIBO8GYbw13ztaaJn11YW4X515OcxYbrDTldqoNerBNlQvghiYYSSW/hUGll9f5sIvg== dependencies: "@graphql-codegen/plugin-helpers" "^2.4.0" - "@graphql-codegen/visitor-plugin-common" "2.7.4" - "@graphql-tools/utils" "8.6.3" + "@graphql-codegen/visitor-plugin-common" "2.8.0" + "@graphql-tools/utils" "8.6.9" change-case-all "1.0.14" parse-filepath "^1.0.2" - tslib "~2.3.0" + tslib "~2.4.0" "@graphql-codegen/plugin-helpers@^2.3.2", "@graphql-codegen/plugin-helpers@^2.4.0", "@graphql-codegen/plugin-helpers@^2.4.1": version "2.4.2" @@ -2274,32 +2343,32 @@ tslib "~2.3.0" "@graphql-codegen/typescript-resolvers@^2.4.3": - version "2.6.1" - resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-2.6.1.tgz#5963da60de79cfb847b55b2433cd9f65a33d7aad" - integrity sha512-tb8qiIYRDbypHvEVBi04OlItABPeormhd6gh26Q0FO/dD+tLx1V85A6wnHC4jExWPP9+/3PwHJL1pq/0n1kxlA== + version "2.6.4" + resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-2.6.4.tgz#857e24279603f4e8f7293385a90a1f2498eb672e" + integrity sha512-BTV5q9d7V+4mVyYRnE8N7HyArmvDbUEY5JwyV94jhlN0AOq2zKQBrs8MRvx8v1VenjTGV+PlnDpF3aEtQu8o+g== dependencies: "@graphql-codegen/plugin-helpers" "^2.4.0" - "@graphql-codegen/typescript" "^2.4.8" - "@graphql-codegen/visitor-plugin-common" "2.7.4" + "@graphql-codegen/typescript" "^2.4.11" + "@graphql-codegen/visitor-plugin-common" "2.8.0" "@graphql-tools/utils" "^8.1.1" auto-bind "~4.0.0" - tslib "~2.3.0" + tslib "~2.4.0" -"@graphql-codegen/typescript@^2.4.2", "@graphql-codegen/typescript@^2.4.8": - version "2.4.8" - resolved "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-2.4.8.tgz#e8110baba9713cde72d57a5c95aa27400363ed9a" - integrity sha512-tVsHIkuyenBany7c5IMU1yi4S1er2hgyXJGNY7PcyhpJMx0eChmbqz1VTiZxDEwi8mDBS2mn3TaSJMh6xuJM5g== +"@graphql-codegen/typescript@^2.4.11", "@graphql-codegen/typescript@^2.4.2": + version "2.4.11" + resolved "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-2.4.11.tgz#b9d8bddaeb79ff4a85e1d0f9c774afba7423177c" + integrity sha512-K3oDLPJRH9Wgpg9TOvb7L+xrJZ8HxkIzV2umqGn54c+8DQjvnRFBIYRO0THgUBMnEauE2sEy6RZkGHGfgQUruA== dependencies: "@graphql-codegen/plugin-helpers" "^2.4.0" "@graphql-codegen/schema-ast" "^2.4.1" - "@graphql-codegen/visitor-plugin-common" "2.7.4" + "@graphql-codegen/visitor-plugin-common" "2.8.0" auto-bind "~4.0.0" - tslib "~2.3.0" + tslib "~2.4.0" -"@graphql-codegen/visitor-plugin-common@2.7.4": - version "2.7.4" - resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-2.7.4.tgz#fbc8aec9df0035b8f29fa64a6356cbb02062da5d" - integrity sha512-aaDoEudDD+B7DK/UwDSL2Fzej75N9hNJ3N8FQuTIeDyw6FNGWUxmkjVBLQGlzfnYfK8IYkdfYkrPn3Skq0pVxA== +"@graphql-codegen/visitor-plugin-common@2.8.0": + version "2.8.0" + resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-2.8.0.tgz#f1de3bd5ee123e6f72c06423912a3a83a6044938" + integrity sha512-29MOaxBog7qaEhmeCzJn2mONSbcA+slCTzHN4nJ3aZl4KrC9V32rXlQpG5x0qHbFQ1LaG1f5gPO83xbiAeMBIw== dependencies: "@graphql-codegen/plugin-helpers" "^2.4.0" "@graphql-tools/optimize" "^1.0.1" @@ -2310,7 +2379,7 @@ dependency-graph "^0.11.0" graphql-tag "^2.11.0" parse-filepath "^1.0.2" - tslib "~2.3.0" + tslib "~2.4.0" "@graphql-tools/apollo-engine-loader@^7.0.5": version "7.2.11" @@ -2522,13 +2591,6 @@ value-or-promise "^1.0.11" ws "^8.3.0" -"@graphql-tools/utils@8.6.3": - version "8.6.3" - resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.3.tgz#ce9fc9adce4d45b229e314a2261290a88a252aed" - integrity sha512-CNyP7Uu7dlVMQ32IpHWOxz4yic9BYXXVkDhG0UdTKSszvzHdgMilemE9MpUrGzzBPsTe3aYTtNGyPUkyh9yTXA== - dependencies: - tslib "~2.3.0" - "@graphql-tools/utils@8.6.9", "@graphql-tools/utils@^8.1.1", "@graphql-tools/utils@^8.3.0", "@graphql-tools/utils@^8.5.1", "@graphql-tools/utils@^8.5.2", "@graphql-tools/utils@^8.6.0": version "8.6.9" resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.9.tgz#fe1b81df29c9418b41b7a1ffe731710b93d3a1fe" @@ -3233,11 +3295,11 @@ integrity sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw== "@keyv/redis@^2.2.3": - version "2.3.4" - resolved "https://registry.npmjs.org/@keyv/redis/-/redis-2.3.4.tgz#441b7fd1e27d2c361ae0180afd9182a45ac6ee68" - integrity sha512-9DqSKV2v5nEcEJa6WajOiWw4GX1rE07Z2oNWaE4XjfPHWLvG46+uOlF0b3Xa5WBaExkWVc7bo5pLAOSK7lAaew== + version "2.3.5" + resolved "https://registry.npmjs.org/@keyv/redis/-/redis-2.3.5.tgz#8ff4fecf9b5520cac2a346e6216db59474df3385" + integrity sha512-dO9sn1HEPVkh1b7Cn/jcLyi7sDFKmnGQIaXw4wTIhJzkwcev24CffvEU26B+KRUNBu/2PgNVNRfFmEpy1smb4w== dependencies: - ioredis "^5.0.3" + ioredis "^5.0.4" "@kubernetes/client-node@^0.16.0": version "0.16.3" @@ -4016,7 +4078,7 @@ react-beautiful-dnd "^13.0.0" react-double-scrollbar "0.0.15" -"@material-ui/core@^4.11.0", "@material-ui/core@^4.11.3", "@material-ui/core@^4.12.1", "@material-ui/core@^4.12.2", "@material-ui/core@^4.9.13": +"@material-ui/core@^4.11.0", "@material-ui/core@^4.11.3", "@material-ui/core@^4.12.1", "@material-ui/core@^4.12.2", "@material-ui/core@^4.9.10", "@material-ui/core@^4.9.13": version "4.12.4" resolved "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz#4ac17488e8fcaf55eb6a7f5efb2a131e10138a73" integrity sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ== @@ -4063,7 +4125,7 @@ prop-types "^15.7.2" react-is "^16.8.0 || ^17.0.0" -"@material-ui/lab@^4.0.0-alpha.60": +"@material-ui/lab@^4.0.0-alpha.57", "@material-ui/lab@^4.0.0-alpha.60": version "4.0.0-alpha.61" resolved "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.61.tgz#9bf8eb389c0c26c15e40933cc114d4ad85e3d978" integrity sha512-rSzm+XKiNUjKegj8bzt5+pygZeckNLOr+IjykH8sYdVk7dE9y2ZuUSofiMV2bJk3qU+JHwexmw+q0RyNZB9ugg== @@ -4138,9 +4200,9 @@ react-is "^16.8.0 || ^17.0.0" "@maxim_mazurok/gapi.client.calendar@^3.0.20220408": - version "3.0.20220429" - resolved "https://registry.npmjs.org/@maxim_mazurok/gapi.client.calendar/-/gapi.client.calendar-3.0.20220429.tgz#ccd5116bd5222a586782e83c4f1370179c600a2b" - integrity sha512-vzjnM+bRo2Heq8BuaWEQUxnB+yi7KmCqs6YfgZITp/84r3IKRLQuu5vAiaHu37kOYKKswRVJ+K5vBU6B742jag== + version "3.0.20220505" + resolved "https://registry.npmjs.org/@maxim_mazurok/gapi.client.calendar/-/gapi.client.calendar-3.0.20220505.tgz#14a72876308481cb97a2ffa859543b1fa0ee258e" + integrity sha512-ZzsJdybuX/RvcDU8eF7XCyHdKYuHU6Z12326hB2+f4IWkMrDTQCayu05cRXZEuvP2YwoPm8gglPpV+flYk1d3g== dependencies: "@types/gapi.client" "*" @@ -4185,9 +4247,9 @@ typescript "~4.6.3" "@microsoft/microsoft-graph-types@^2.6.0": - version "2.19.0" - resolved "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.19.0.tgz#df95ab3b59308221a6063fc11a9235d6558e890e" - integrity sha512-TvSbalr8bpNN74dqXQQkpfoMCtEyaMECqi6Yk1WcOCYLL7k7z7ABErafFXH9uBmqSIXYchKSyR4IJNh9Sd4BYA== + version "2.20.0" + resolved "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.20.0.tgz#fc532a5dc146c0b8a6f78a633fe930535f8cdc42" + integrity sha512-T1EPoYdH4124Rg+h261dvW2qAeSRAotHM/6lv10fDsYX4DWsppvresmfhGbPrLApK/lRTRj93bn4/Nwwmdv4Zg== "@microsoft/tsdoc-config@~0.16.1": version "0.16.1" @@ -4748,19 +4810,19 @@ resolved "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz#1108b9ea661ca6c81e4a8bfa63a09eb27d5bc2db" integrity sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig== -"@octokit/webhooks-types@5.5.1": - version "5.5.1" - resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.5.1.tgz#3ab94e890bee827302c6312e80497426d6627cbf" - integrity sha512-FaBbqZS2e4fCdQvUqeBKpJJOVsRxGcrf0NA91WBXz9GP5/4xgQgdjpbzAcDOSfESBYDYD78HeI5VeihfCW28Ew== +"@octokit/webhooks-types@5.6.0": + version "5.6.0" + resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.6.0.tgz#cbc908ef0df997de7f65da4e4003ecb8430410d3" + integrity sha512-y3MqE6N6Ksg1+YV0sXVpW2WP7Y24h7rUp2hDJuzoqWdKGr7owmRDyHC72INwfCYNzura/vsNPXvc6Xbfp4wGGw== "@octokit/webhooks@^9.0.1", "@octokit/webhooks@^9.14.1": - version "9.23.0" - resolved "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.23.0.tgz#16fc24284afdf3e119d32928dd3f8b338890e56c" - integrity sha512-4+imw+CajrKpafaE9oLCtXyU3ZAcCLwuoeZ3XmFruQZCEcBBJYE/juSFvU3x1HkFFeKwsUyr+nRikRwiK/VSmA== + version "9.24.0" + resolved "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.24.0.tgz#3e3b194ee67151f674e8d0d565c8179828a12b3d" + integrity sha512-s1nqplA+j4sP7Cz40jn/Q2ipkKRKJ7Gi+NzZiSnwNfisYNduLHEwMUJVBEKc5I0r6GMcZZRJOe6PJ2rJXYW66g== dependencies: "@octokit/request-error" "^2.0.2" "@octokit/webhooks-methods" "^2.0.0" - "@octokit/webhooks-types" "5.5.1" + "@octokit/webhooks-types" "5.6.0" aggregate-error "^3.1.0" "@open-draft/until@^1.0.3": @@ -4877,9 +4939,9 @@ integrity sha512-8UiDeDbjCImFSfOegGu13otQ7OdP9FOYpcLjeouppnhs+MPeIEAtYS+jCcBKmi3reyTagC15/KVSRhde1wS1vg== "@roadiehq/backstage-plugin-buildkite@^2.0.0": - version "2.0.1" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-2.0.1.tgz#a17cf1e827b7b27f6c4f36bb5959004cac40712c" - integrity sha512-Dd38wPv4N3GHDNxu6XsJm7jfIHru0avE2lwmIlZsKn9+Ad+CbeTdjkYjObctIynzjhrETJrNpmZath57yCVe1A== + version "2.0.3" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-2.0.3.tgz#73f3586c176c4c2ffe55af78ee8ce86c3c363dc6" + integrity sha512-Jna1m/pj52G7qz0PKmldQUXHsw5IUTxtgxVh2n1X2CTq+o10xySVspmEyEmLdNxkeQdYO+a280fYWjEKo9xoyQ== dependencies: "@backstage/catalog-model" "^1.0.0" "@backstage/core-components" "^0.9.0" @@ -4920,9 +4982,9 @@ zustand "3.6.9" "@roadiehq/backstage-plugin-github-pull-requests@^2.0.0": - version "2.1.1" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-2.1.1.tgz#90bc2e82c47ddf5fe40063ddcfff9efdb464f046" - integrity sha512-/855fB7F0Ss4h7iTayBu/SVbWLM5iw3401ER5uWf1IoSpXorJECEW0lfzroJtWMGse6LfNfbuWqTKnp2vTSosg== + version "2.1.2" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-2.1.2.tgz#1c8289679bb109a70c30b5ba090ea7d751553764" + integrity sha512-VXv1D1JhifX0B9nukxFa61MyXouPTXEYkeNwYB+Y3e0VfoPEGzAeE/Ub23rP8aVcYsbuyCA+6u/HQsrw6Vgpxw== dependencies: "@backstage/catalog-model" "^1.0.0" "@backstage/core-components" "^0.9.0" @@ -4985,14 +5047,14 @@ "@rollup/pluginutils" "^3.0.8" "@rollup/plugin-node-resolve@^13.0.0": - version "13.2.1" - resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.2.1.tgz#cdee815cf02c180ff0a42536ca67a8f67e299f84" - integrity sha512-btX7kzGvp1JwShQI9V6IM841YKNPYjKCvUbNrQ2EcVYbULtUd/GH6wZ/qdqH13j9pOHBER+EZXNN2L8RSJhVRA== + version "13.3.0" + resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz#da1c5c5ce8316cef96a2f823d111c1e4e498801c" + integrity sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw== dependencies: "@rollup/pluginutils" "^3.1.0" "@types/resolve" "1.17.1" - builtin-modules "^3.1.0" deepmerge "^4.2.2" + is-builtin-module "^3.1.0" is-module "^1.0.0" resolve "^1.19.0" @@ -5346,9 +5408,9 @@ "@types/react-dom" "<18.0.0" "@testing-library/user-event@^14.0.0": - version "14.1.1" - resolved "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.1.1.tgz#e1ff6118896e4b22af31e5ea2f9da956adde23d8" - integrity sha512-XrjH/iEUqNl9lF2HX9YhPNV7Amntkcnpw0Bo1KkRzowNDcgSN9i0nm4Q8Oi5wupgdfPaJNMAWa61A+voD6Kmwg== + version "14.2.0" + resolved "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.2.0.tgz#8293560f8f80a00383d6c755ec3e0b918acb1683" + integrity sha512-+hIlG4nJS6ivZrKnOP7OGsDu9Fxmryj9vCl8x0ZINtTJcCHs2zLsYif5GzuRiBF2ck5GZG2aQr7Msg+EHlnYVQ== "@tokenizer/token@^0.3.0": version "0.3.0" @@ -5414,7 +5476,7 @@ dependencies: ansi-regex "*" -"@types/archiver@^5.1.0", "@types/archiver@^5.1.1": +"@types/archiver@^5.1.0", "@types/archiver@^5.3.1": version "5.3.1" resolved "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.1.tgz#02991e940a03dd1a32678fead4b4ca03d0e387ca" integrity sha512-wKYZaSXaDvTZuInAWjCeGG7BEAgTWG2zZW0/f7IYFcoHB2X2d9lkVFnrOlXl3W6NrvO6Ml3FLLu8Uksyymcpnw== @@ -5487,6 +5549,13 @@ dependencies: "@babel/types" "^7.3.0" +"@types/base64-stream@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@types/base64-stream/-/base64-stream-1.0.2.tgz#5a6c99eb4701a3d2aafd3082d8b44be7b1be1325" + integrity sha512-pPTps4oDwasxGcxpG6Ub8rAkVSPdekoolze0oza1mMFdlgXXKXE2zqCePBfemvWlGI92k9jE7kH3nz0+tJEXQw== + dependencies: + "@types/node" "*" + "@types/body-parser@*", "@types/body-parser@1.19.2", "@types/body-parser@^1.19.0": version "1.19.2" resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" @@ -5529,10 +5598,10 @@ dependencies: classnames "*" -"@types/codemirror@^0.0.109": - version "0.0.109" - resolved "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.109.tgz#89d575ff1c7b462c4c3b8654f8bb38e5622e9036" - integrity sha512-cSdiHeeLjvGn649lRTNeYrVCDOgDrtP+bDDSFDd1TF+i0jKGPDRozno2NOJ9lTniso+taiv4kiVS8dgM8Jm5lg== +"@types/codemirror@^5.0.0": + version "5.60.5" + resolved "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz#5b989a3b4bbe657458cf372c92b6bfda6061a2b7" + integrity sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg== dependencies: "@types/tern" "*" @@ -5746,10 +5815,10 @@ "@types/node" "*" "@types/ssh2" "*" -"@types/dockerode@^3.2.7", "@types/dockerode@^3.3.0": - version "3.3.8" - resolved "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.8.tgz#afb844b8e8cf54160e1686832903a1444912ff79" - integrity sha512-/Hip29GzPBWfbSS87lyQDVoB7Ja+kr8oOFWXsySxNFa7jlyj3Yws8LaZRmn1xZl7uJH3Xxsg0oI09GHpT1pIBw== +"@types/dockerode@^3.3.0", "@types/dockerode@^3.3.8": + version "3.3.9" + resolved "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.9.tgz#8c6e519fd4d0d86717b2c6a864904f4e6aa8af40" + integrity sha512-SYRN5FF/qmwpxUT6snJP5D8k0wgoUKOGVs625XvpRJOOUi6s//UYI4F0tbyE3OmzpI70Fo1+aqpzX27zCrInww== dependencies: "@types/docker-modem" "*" "@types/node" "*" @@ -5915,9 +5984,9 @@ "@types/node" "*" "@types/http-proxy@*", "@types/http-proxy@^1.17.4", "@types/http-proxy@^1.17.8": - version "1.17.8" - resolved "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" - integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== + version "1.17.9" + resolved "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" + integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== dependencies: "@types/node" "*" @@ -6204,7 +6273,7 @@ resolved "https://registry.npmjs.org/@types/node/-/node-12.20.48.tgz#55f70bd432b6515828c0298689776861b90ca4fa" integrity sha512-4kxzqkrpwYtn6okJUcb2lfUu9ilnb3yhUOH6qX3nug8D2DupZ2drIkff2yJzYcNJVl3begnlcaBJ7tqiTTzjnQ== -"@types/node@^14.14.31", "@types/node@^14.14.32": +"@types/node@^14.14.31": version "14.18.16" resolved "https://registry.npmjs.org/@types/node/-/node-14.18.16.tgz#878f670ba3f00482bf859b6550b6010610fc54b5" integrity sha512-X3bUMdK/VmvrWdoTkz+VCn6nwKwrKCFTHtqwBIaQJNx4RUIBBUFXM00bqPz/DsDd+Icjmzm6/tyYZzeGVqb6/Q== @@ -6214,10 +6283,10 @@ resolved "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz#bc43c990c3c9be7281868bbc7b8fdd6e2b57adfa" integrity sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A== -"@types/node@^16.11.26", "@types/node@^16.9.2": - version "16.11.33" - resolved "https://registry.npmjs.org/@types/node/-/node-16.11.33.tgz#566713b1b626f781c5c58fe3531307283e00720c" - integrity sha512-0PJ0vg+JyU0MIan58IOIFRtSvsb7Ri+7Wltx2qAg94eMOrpg4+uuP3aUHCpxXc1i0jCXiC+zIamSZh3l9AbcQA== +"@types/node@^16.0.0", "@types/node@^16.11.26", "@types/node@^16.9.2": + version "16.11.34" + resolved "https://registry.npmjs.org/@types/node/-/node-16.11.34.tgz#520224e4be4448c279ecad09639ab460cc441a50" + integrity sha512-UrWGDyLAlQ2Z8bNOGWTsqbP9ZcBeTYBVuTRNxXTztBy5KhWUFI3BaeDWoCP/CzV/EVGgO1NTYzv9ZytBI9GAEw== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -6371,10 +6440,10 @@ dependencies: "@types/react" "*" -"@types/react-syntax-highlighter@^13.5.2": - version "13.5.2" - resolved "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-13.5.2.tgz#357cc03581dc434c57c3b31f70e0eecdbf7b3ab0" - integrity sha512-sRZoKZBGKaE7CzMvTTgz+0x/aVR58ZYUTfB7HN76vC+yQnvo1FWtzNARBt0fGqcLGEVakEzMu/CtPzssmanu8Q== +"@types/react-syntax-highlighter@^15.0.0": + version "15.5.1" + resolved "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.1.tgz#0c459cdd94a882df05778e93a1514430cc641043" + integrity sha512-+yD6D8y21JqLf89cRFEyRfptVMqo2ROHyAlysRvFwT28gT5gDo3KOiXHwGilHcq9y/OKTjlWK0f/hZUicrBFPQ== dependencies: "@types/react" "*" @@ -6407,9 +6476,9 @@ "@types/react" "*" "@types/react@*", "@types/react@^16.13.1 || ^17.0.0", "@types/react@^17": - version "17.0.44" - resolved "https://registry.npmjs.org/@types/react/-/react-17.0.44.tgz#c3714bd34dd551ab20b8015d9d0dbec812a51ec7" - integrity sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g== + version "17.0.45" + resolved "https://registry.npmjs.org/@types/react/-/react-17.0.45.tgz#9b3d5b661fd26365fefef0e766a1c6c30ccf7b3f" + integrity sha512-YfhQ22Lah2e3CHPsb93tRwIGNiSwkuz1/blk4e6QrWS0jQzCSNbGLtOEYhPg02W0yGTTmpajp7dCTbBAMN3qsg== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -6616,9 +6685,9 @@ "@types/node" "*" "@types/swagger-ui-react@^4.1.1": - version "4.1.1" - resolved "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-4.1.1.tgz#6ae70f5b966941eb6655d79d1114d9b9ef69a980" - integrity sha512-tZqX/nShvNqtJ7WAfwOK7mphK1jqmEre4mUJh+R1RyCFVODsMTG4My2nqjXpSm8NfhVGmbFH3giD17AXmgsaJw== + version "4.11.0" + resolved "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-4.11.0.tgz#3ac84bc8e2f6e57b9ff4533ec31934f697e1a2c4" + integrity sha512-WPMR+GWbLd7zvY/uOTGzGzP44zK2rIZSnU00+pDR2YANnEV6/qj0kqYfdSY1Vk6qdvI7dR0Tx8JEMgUUrUQDjw== dependencies: "@types/react" "*" @@ -6790,13 +6859,13 @@ integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== "@typescript-eslint/eslint-plugin@^5.9.0": - version "5.20.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.20.0.tgz#022531a639640ff3faafaf251d1ce00a2ef000a1" - integrity sha512-fapGzoxilCn3sBtC6NtXZX6+P/Hef7VDbyfGqTTpzYydwhlkevB+0vE0EnmHPVTVSy68GUncyJ/2PcrFBeCo5Q== + version "5.23.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.23.0.tgz#bc4cbcf91fbbcc2e47e534774781b82ae25cc3d8" + integrity sha512-hEcSmG4XodSLiAp1uxv/OQSGsDY6QN3TcRU32gANp+19wGE1QQZLRS8/GV58VRUoXhnkuJ3ZxNQ3T6Z6zM59DA== dependencies: - "@typescript-eslint/scope-manager" "5.20.0" - "@typescript-eslint/type-utils" "5.20.0" - "@typescript-eslint/utils" "5.20.0" + "@typescript-eslint/scope-manager" "5.23.0" + "@typescript-eslint/type-utils" "5.23.0" + "@typescript-eslint/utils" "5.23.0" debug "^4.3.2" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -6817,13 +6886,13 @@ eslint-utils "^3.0.0" "@typescript-eslint/parser@^5.9.0": - version "5.20.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.20.0.tgz#4991c4ee0344315c2afc2a62f156565f689c8d0b" - integrity sha512-UWKibrCZQCYvobmu3/N8TWbEeo/EPQbS41Ux1F9XqPzGuV7pfg6n50ZrFo6hryynD8qOTTfLHtHjjdQtxJ0h/w== + version "5.23.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.23.0.tgz#443778e1afc9a8ff180f91b5e260ac3bec5e2de1" + integrity sha512-V06cYUkqcGqpFjb8ttVgzNF53tgbB/KoQT/iB++DOIExKmzI9vBJKjZKt/6FuV9c+zrDsvJKbJ2DOCYwX91cbw== dependencies: - "@typescript-eslint/scope-manager" "5.20.0" - "@typescript-eslint/types" "5.20.0" - "@typescript-eslint/typescript-estree" "5.20.0" + "@typescript-eslint/scope-manager" "5.23.0" + "@typescript-eslint/types" "5.23.0" + "@typescript-eslint/typescript-estree" "5.23.0" debug "^4.3.2" "@typescript-eslint/scope-manager@5.20.0": @@ -6834,6 +6903,14 @@ "@typescript-eslint/types" "5.20.0" "@typescript-eslint/visitor-keys" "5.20.0" +"@typescript-eslint/scope-manager@5.23.0": + version "5.23.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.23.0.tgz#4305e61c2c8e3cfa3787d30f54e79430cc17ce1b" + integrity sha512-EhjaFELQHCRb5wTwlGsNMvzK9b8Oco4aYNleeDlNuL6qXWDF47ch4EhVNPh8Rdhf9tmqbN4sWDk/8g+Z/J8JVw== + dependencies: + "@typescript-eslint/types" "5.23.0" + "@typescript-eslint/visitor-keys" "5.23.0" + "@typescript-eslint/scope-manager@5.9.0": version "5.9.0" resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz#02dfef920290c1dcd7b1999455a3eaae7a1a3117" @@ -6842,12 +6919,12 @@ "@typescript-eslint/types" "5.9.0" "@typescript-eslint/visitor-keys" "5.9.0" -"@typescript-eslint/type-utils@5.20.0": - version "5.20.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.20.0.tgz#151c21cbe9a378a34685735036e5ddfc00223be3" - integrity sha512-WxNrCwYB3N/m8ceyoGCgbLmuZwupvzN0rE8NBuwnl7APgjv24ZJIjkNzoFBXPRCGzLNkoU/WfanW0exvp/+3Iw== +"@typescript-eslint/type-utils@5.23.0": + version "5.23.0" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.23.0.tgz#f852252f2fc27620d5bb279d8fed2a13d2e3685e" + integrity sha512-iuI05JsJl/SUnOTXA9f4oI+/4qS/Zcgk+s2ir+lRmXI+80D8GaGwoUqs4p+X+4AxDolPpEpVUdlEH4ADxFy4gw== dependencies: - "@typescript-eslint/utils" "5.20.0" + "@typescript-eslint/utils" "5.23.0" debug "^4.3.2" tsutils "^3.21.0" @@ -6856,6 +6933,11 @@ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.20.0.tgz#fa39c3c2aa786568302318f1cb51fcf64258c20c" integrity sha512-+d8wprF9GyvPwtoB4CxBAR/s0rpP25XKgnOvMf/gMXYDvlUC3rPFHupdTQ/ow9vn7UDe5rX02ovGYQbv/IUCbg== +"@typescript-eslint/types@5.23.0": + version "5.23.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.23.0.tgz#8733de0f58ae0ed318dbdd8f09868cdbf9f9ad09" + integrity sha512-NfBsV/h4dir/8mJwdZz7JFibaKC3E/QdeMEDJhiAE3/eMkoniZ7MjbEMCGXw6MZnZDMN3G9S0mH/6WUIj91dmw== + "@typescript-eslint/types@5.9.0": version "5.9.0" resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz#e5619803e39d24a03b3369506df196355736e1a3" @@ -6874,6 +6956,19 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@5.23.0": + version "5.23.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.23.0.tgz#dca5f10a0a85226db0796e8ad86addc9aee52065" + integrity sha512-xE9e0lrHhI647SlGMl+m+3E3CKPF1wzvvOEWnuE3CCjjT7UiRnDGJxmAcVKJIlFgK6DY9RB98eLr1OPigPEOGg== + dependencies: + "@typescript-eslint/types" "5.23.0" + "@typescript-eslint/visitor-keys" "5.23.0" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/typescript-estree@5.9.0": version "5.9.0" resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz#0e5c6f03f982931abbfbc3c1b9df5fbf92a3490f" @@ -6887,7 +6982,19 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@5.20.0", "@typescript-eslint/utils@^5.10.0": +"@typescript-eslint/utils@5.23.0": + version "5.23.0" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.23.0.tgz#4691c3d1b414da2c53d8943310df36ab1c50648a" + integrity sha512-dbgaKN21drqpkbbedGMNPCtRPZo1IOUr5EI9Jrrh99r5UW5Q0dz46RKXeSBoPV+56R6dFKpbrdhgUNSJsDDRZA== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.23.0" + "@typescript-eslint/types" "5.23.0" + "@typescript-eslint/typescript-estree" "5.23.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/utils@^5.10.0": version "5.20.0" resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.20.0.tgz#b8e959ed11eca1b2d5414e12417fd94cae3517a5" integrity sha512-lHONGJL1LIO12Ujyx8L8xKbwWSkoUKFSO+0wDAqGXiudWB2EO7WEUT+YZLtVbmOmSllAjLb9tpoIPwpRe5Tn6w== @@ -6907,6 +7014,14 @@ "@typescript-eslint/types" "5.20.0" eslint-visitor-keys "^3.0.0" +"@typescript-eslint/visitor-keys@5.23.0": + version "5.23.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.23.0.tgz#057c60a7ca64667a39f991473059377a8067c87b" + integrity sha512-Vd4mFNchU62sJB8pX19ZSPog05B0Y0CE2UxAZPT5k4iqhRYjPnqyY3woMxCd0++t9OTqkgjST+1ydLBi7e2Fvg== + dependencies: + "@typescript-eslint/types" "5.23.0" + eslint-visitor-keys "^3.0.0" + "@typescript-eslint/visitor-keys@5.9.0": version "5.9.0" resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz#7585677732365e9d27f1878150fab3922784a1a6" @@ -7128,10 +7243,10 @@ acorn-import-assertions@^1.7.6: resolved "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz#580e3ffcae6770eebeec76c3b9723201e9d01f78" integrity sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA== -acorn-jsx@^5.3.1: - version "5.3.1" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" - integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^7.1.1: version "7.1.1" @@ -7153,6 +7268,11 @@ acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0: resolved "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== +acorn@^8.7.1: + version "8.7.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -7376,11 +7496,12 @@ apollo-server-caching@^3.3.0: dependencies: lru-cache "^6.0.0" -apollo-server-core@^3.6.7: - version "3.6.7" - resolved "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-3.6.7.tgz#6a52ce48fe1a79da9691c3fff4ea1031e9225602" - integrity sha512-OnZ9vu7LrYy2rvEu+nbgqucw6VyTSIPAEjK87c4rkzlVOxpwtGUaQ4FMWD9zBIj7yLq9q22b638E8LdYoaTAjQ== +apollo-server-core@^3.7.0: + version "3.7.0" + resolved "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-3.7.0.tgz#7ec060d269d73d6761cd1eb3d419436e09fa6974" + integrity sha512-xUCDjrBzPVbttbh/HenuQdivco/dcXE2oIDYwCU6FU2RBXqxWFmuCl2Xe7VPA/5Frw/4snJDLCyVte9PA5edww== dependencies: + "@apollo/utils.logger" "^1.0.0" "@apollographql/apollo-tools" "^0.5.3" "@apollographql/graphql-playground-html" "1.6.29" "@graphql-tools/mock" "^8.1.2" @@ -7391,8 +7512,8 @@ apollo-server-core@^3.6.7: apollo-server-caching "^3.3.0" apollo-server-env "^4.2.1" apollo-server-errors "^3.3.1" - apollo-server-plugin-base "^3.5.2" - apollo-server-types "^3.5.2" + apollo-server-plugin-base "^3.5.3" + apollo-server-types "^3.5.3" async-retry "^1.2.1" fast-json-stable-stringify "^2.1.0" graphql-tag "^2.11.0" @@ -7401,6 +7522,7 @@ apollo-server-core@^3.6.7: lru-cache "^6.0.0" sha.js "^2.4.11" uuid "^8.0.0" + whatwg-mimetype "^3.0.0" apollo-server-env@^4.2.1: version "4.2.1" @@ -7414,10 +7536,10 @@ apollo-server-errors@^3.3.1: resolved "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-3.3.1.tgz#ba5c00cdaa33d4cbd09779f8cb6f47475d1cd655" integrity sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA== -apollo-server-express@^3.0.0, apollo-server-express@^3.6.7: - version "3.6.7" - resolved "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-3.6.7.tgz#9b83ba088cc40ea98bc0f903f9bfed41ea98fdf8" - integrity sha512-B4gH5j8t3XxTCIa9bl7Iq/F3YFzMxX/LV4Sc+L/3xkHm648u576G5Lkskl8HsoTGSzzyeVcVsPDoYHiBjCAN0Q== +apollo-server-express@^3.0.0, apollo-server-express@^3.7.0: + version "3.7.0" + resolved "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-3.7.0.tgz#dc4cacc25f9528d3a18e2557b52990bf000b454c" + integrity sha512-176LSK7YBxwfleurtbfr5SYMheNNJSHrQa2h4QuosLqhfFJkfTpI2iBW56N737U47QfyueCOvkjNZVq86e3n2g== dependencies: "@types/accepts" "^1.3.5" "@types/body-parser" "1.19.2" @@ -7425,35 +7547,35 @@ apollo-server-express@^3.0.0, apollo-server-express@^3.6.7: "@types/express" "4.17.13" "@types/express-serve-static-core" "4.17.28" accepts "^1.3.5" - apollo-server-core "^3.6.7" - apollo-server-types "^3.5.2" + apollo-server-core "^3.7.0" + apollo-server-types "^3.5.3" body-parser "^1.19.0" cors "^2.8.5" parseurl "^1.3.3" -apollo-server-plugin-base@^3.5.2: - version "3.5.2" - resolved "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-3.5.2.tgz#18a08353f5ea207a07f2c1e66dd7ef2335ce8c84" - integrity sha512-SwIf1waDmNDb0kmn57QR++InwK6Iv/X2slpm/aFIoqFBe91r6uJfakJvQZuh8dLEgk68gxqFsT8zHRpxBclE+g== +apollo-server-plugin-base@^3.5.3: + version "3.5.3" + resolved "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-3.5.3.tgz#620ca8e9337e5d661c3915375bd6720d0aa205ce" + integrity sha512-zojm3qiUGYtM5k1PPrCJnLZSDNqvWvmIDvqBjCu3wI3iNZqNm3MOA86eYGFfaBi/WNu3qYIj6QE3T7w0XjRV1A== dependencies: - apollo-server-types "^3.5.2" + apollo-server-types "^3.5.3" -apollo-server-types@^3.5.2: - version "3.5.2" - resolved "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-3.5.2.tgz#903d499a70b9010764cbab4d704ddb8c086aa06f" - integrity sha512-vhcbIWsBkoNibABOym4AAPBoNDjokhjUQokKYdwZMeqrb850PMQdNJFrGyXT5onP408Ghv4O8PfgBuPQmeJhVQ== +apollo-server-types@^3.5.3: + version "3.5.3" + resolved "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-3.5.3.tgz#e874bd99135c5c6550fe5f904b3b521b340e6ea3" + integrity sha512-Qf5mMVTDyABEeyjGecwMsk0y0km4KuW8/j/UwBDQkAAW1QRy+w8nqi+wvSoA5hNXiYCdJN4U4nxTxm9+2eiT4w== dependencies: apollo-reporting-protobuf "^3.3.1" apollo-server-caching "^3.3.0" apollo-server-env "^4.2.1" apollo-server@^3.0.0: - version "3.6.7" - resolved "https://registry.npmjs.org/apollo-server/-/apollo-server-3.6.7.tgz#6779de1dfd33afce08dff905e561f628d71ad83d" - integrity sha512-WERZqaVCkZJMoOc9y692NribgNtKbHDjOwiAmgXI2WBlON2oUvCwgxPvsMg+bXVpQx4itrMyj31a2N6BeKmbmQ== + version "3.7.0" + resolved "https://registry.npmjs.org/apollo-server/-/apollo-server-3.7.0.tgz#8755c1e1f08825a61003667551e5915373db9f87" + integrity sha512-sMD9V0cScsuXKtqtpLBpeU3s0eRyG12n3HtHGg9LNBanYkxS4/I1i0JozO0r0e2kO5yyJ1gc6UWim9+NDxUrnA== dependencies: - apollo-server-core "^3.6.7" - apollo-server-express "^3.6.7" + apollo-server-core "^3.7.0" + apollo-server-express "^3.7.0" express "^4.17.1" aproba@^1.0.3: @@ -7487,7 +7609,7 @@ archiver-utils@^2.1.0: normalize-path "^3.0.0" readable-stream "^2.0.0" -archiver@^5.0.2, archiver@^5.3.0: +archiver@^5.0.2, archiver@^5.3.1: version "5.3.1" resolved "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz#21e92811d6f09ecfce649fbefefe8c79e57cbbb6" integrity sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w== @@ -7738,13 +7860,6 @@ async-retry@^1.2.1, async-retry@^1.3.3: dependencies: retry "0.13.1" -async@^2.6.2: - version "2.6.4" - resolved "https://registry.npmjs.org/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - async@^3.2.0, async@^3.2.3: version "3.2.3" resolved "https://registry.npmjs.org/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" @@ -7799,9 +7914,9 @@ aws-sdk-mock@^5.2.1: traverse "^0.6.6" aws-sdk@^2.1122.0, aws-sdk@^2.840.0, aws-sdk@^2.948.0: - version "2.1125.0" - resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1125.0.tgz#2a73f5bf1e5e8f8dbc873ef87cfe14925721ba2e" - integrity sha512-2syNkKDqDcDmB/chc61a5xx+KYzaarLs1/KshE0b1Opp2oSq2FARyUBbk59HgwKaDUB61uPF33ZG9sHiIVx2hQ== + version "2.1132.0" + resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1132.0.tgz#0cb615e97db5a5133914ba0f2bdc8ea10eef4069" + integrity sha512-NPDesfTrNx8UMQ5VuosQNlFFFhswJ8cGVcVltZBXKVl1kW0BCp52XQBySSruIznaRX7vG6Ir2+nox0NdL05qBQ== dependencies: buffer "4.9.2" events "1.1.1" @@ -8057,6 +8172,11 @@ base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1: resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +base64-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/base64-stream/-/base64-stream-1.0.0.tgz#157ae00bc7888695e884e1fcc51c551fdfa8a1fa" + integrity sha512-BQQZftaO48FcE1Kof9CmXMFaAdqkcNorgc8CxesZv9nMbbTF1EFyQe89UOuh//QMmdtfUDXyO8rgUalemL5ODA== + base64id@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" @@ -8524,10 +8644,10 @@ buffers@~0.1.1: resolved "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s= -builtin-modules@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484" - integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw== +builtin-modules@^3.0.0: + version "3.2.0" + resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" + integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== builtin-status-codes@^3.0.0: version "3.0.0" @@ -9385,10 +9505,10 @@ component-inherit@0.0.3: resolved "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= -compress-brotli@^1.3.6: - version "1.3.6" - resolved "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.6.tgz#64bd6f21f4f3e9841dbac392f4c29218caf5e9d9" - integrity sha512-au99/GqZtUtiCBliqLFbWlhnCxn+XSYjwZ77q6mKN4La4qOXDoLVPZ50iXr0WmAyMxl8yqoq3Yq4OeQNPPkyeQ== +compress-brotli@^1.3.8: + version "1.3.8" + resolved "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db" + integrity sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ== dependencies: "@types/json-buffer" "~3.0.0" json-buffer "~3.0.1" @@ -9652,16 +9772,16 @@ cookie@0.4.1: resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== +cookie@0.4.2, cookie@^0.4.1, cookie@^0.4.2, cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + cookie@0.5.0: version "0.5.0" resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== -cookie@^0.4.1, cookie@^0.4.2, cookie@~0.4.1: - version "0.4.2" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - cookiejar@^2.1.3: version "2.1.3" resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" @@ -9698,9 +9818,9 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.10: integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-js@^3.4.1, core-js@^3.6.5: - version "3.22.4" - resolved "https://registry.npmjs.org/core-js/-/core-js-3.22.4.tgz#f4b3f108d45736935aa028444a69397e40d8c531" - integrity sha512-1uLykR+iOfYja+6Jn/57743gc9n73EWiOnSJJ4ba3B4fOEYDBv25MagmEZBxTp5cWq4b/KPx/l77zgsp28ju4w== + version "3.22.5" + resolved "https://registry.npmjs.org/core-js/-/core-js-3.22.5.tgz#a5f5a58e663d5c0ebb4e680cd7be37536fb2a9cf" + integrity sha512-VP/xYuvJ0MJWRAobcmQ8F2H6Bsn+s7zqAAjFaHGBMc5AQm7zaelhD1LGduFn2EehEcQcU+br6t+fwbpQ5d1ZWA== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -9816,9 +9936,9 @@ cron@^1.8.2: moment-timezone "^0.5.x" cronstrue@^2.2.0: - version "2.4.0" - resolved "https://registry.npmjs.org/cronstrue/-/cronstrue-2.4.0.tgz#16c6d10a17b90c37a71c7e8fb3bb67d0243d70e5" - integrity sha512-KDJgE8XoT0Nupt1iljNGAQnxkfITwIYkL7mHrzH4a0AWyrj7Xk6GVCNPN3Avs7tU2yYoNuDculMKp9T3jysbPA== + version "2.5.0" + resolved "https://registry.npmjs.org/cronstrue/-/cronstrue-2.5.0.tgz#1d69bd53520ce536789fb666d9fd562065b491c6" + integrity sha512-2uhcYEmXEH52Prn1biZ1HSaQwGwUy4fxFiq3U3vKwLYngL14j8f4pZeQt9f1J6tWDaLFeLRgcCHtO45r78ECyw== cross-env@^7.0.0: version "7.0.3" @@ -10146,9 +10266,9 @@ cypress-plugin-snapshots@^1.4.4: unidiff "1.0.2" cypress@^9.5.0: - version "9.6.0" - resolved "https://registry.npmjs.org/cypress/-/cypress-9.6.0.tgz#84473b3362255fa8f5e627a596e58575c9e5320f" - integrity sha512-nNwt9eBQmSENamwa8LxvggXksfyzpyYaQ7lNBLgks3XZ6dPE/6BCQFBzeAyAPt/bNXfH3tKPkAyhiAZPYkWoEg== + version "9.6.1" + resolved "https://registry.npmjs.org/cypress/-/cypress-9.6.1.tgz#a7d6b5a53325b3dc4960181f5800a5ade0f085eb" + integrity sha512-ECzmV7pJSkk+NuAhEw6C3D+RIRATkSb2VAHXDY6qGZbca/F9mv5pPsj2LO6Ty6oIFVBTrwCyL9agl28MtJMe2g== dependencies: "@cypress/request" "^2.88.10" "@cypress/xvfb" "^1.2.4" @@ -10515,7 +10635,7 @@ debug@4.3.2: dependencies: ms "2.1.2" -debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: +debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -10790,10 +10910,10 @@ detect-port-alt@^1.1.6: address "^1.0.1" debug "^2.6.0" -devtools-protocol@0.0.981744: - version "0.0.981744" - resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.981744.tgz#9960da0370284577d46c28979a0b32651022bacf" - integrity sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg== +devtools-protocol@0.0.982423: + version "0.0.982423" + resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.982423.tgz#39ac3791d4c5b90ebb416d4384663b7b0cc44154" + integrity sha512-FnVW2nDbjGNw1uD/JRC+9U5768W7e1TfUwqbDTcSsAu1jXFjITSX8w3rkW5FEpHRMPPGpvNSmO1pOpqByiWscA== dezalgo@1.0.3, dezalgo@^1.0.0: version "1.0.3" @@ -11234,10 +11354,10 @@ engine.io@~3.5.0: engine.io-parser "~2.2.0" ws "~7.4.2" -enhanced-resolve@^5.9.2: - version "5.9.2" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9" - integrity sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA== +enhanced-resolve@^5.9.3: + version "5.9.3" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz#44a342c012cbc473254af5cc6ae20ebd0aae5d88" + integrity sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -11348,75 +11468,75 @@ es6-error@^4.1.1: resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -esbuild-android-64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz#5b94a1306df31d55055f64a62ff6b763a47b7f64" - integrity sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw== +esbuild-android-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz#09f12a372eed9743fd77ff6d889ac14f7b340c21" + integrity sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ== -esbuild-android-arm64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz#78acc80773d16007de5219ccce544c036abd50b8" - integrity sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA== +esbuild-android-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz#f608d00ea03fe26f3b1ab92a30f99220390f3071" + integrity sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA== -esbuild-darwin-64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz#e02b1291f629ebdc2aa46fabfacc9aa28ff6aa46" - integrity sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA== +esbuild-darwin-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz#31528daa75b4c9317721ede344195163fae3e041" + integrity sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g== -esbuild-darwin-arm64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz#01eb6650ec010b18c990e443a6abcca1d71290a9" - integrity sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ== +esbuild-darwin-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz#247f770d86d90a215fa194f24f90e30a0bd97245" + integrity sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw== -esbuild-freebsd-64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz#790b8786729d4aac7be17648f9ea8e0e16475b5e" - integrity sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig== +esbuild-freebsd-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz#479414d294905055eb396ebe455ed42213284ee0" + integrity sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ== -esbuild-freebsd-arm64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz#b66340ab28c09c1098e6d9d8ff656db47d7211e6" - integrity sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ== +esbuild-freebsd-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz#cedeb10357c88533615921ae767a67dc870a474c" + integrity sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg== -esbuild-linux-32@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz#7927f950986fd39f0ff319e92839455912b67f70" - integrity sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g== +esbuild-linux-32@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz#d9f008c4322d771f3958f59c1eee5a05cdf92485" + integrity sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg== -esbuild-linux-64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz#4893d07b229d9cfe34a2b3ce586399e73c3ac519" - integrity sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q== +esbuild-linux-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz#ba58d7f66858913aeb1ab5c6bde1bbd824731795" + integrity sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ== -esbuild-linux-arm64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz#8442402e37d0b8ae946ac616784d9c1a2041056a" - integrity sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA== +esbuild-linux-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz#708785a30072702b5b1c16b65cf9c25c51202529" + integrity sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ== -esbuild-linux-arm@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz#d5dbf32d38b7f79be0ec6b5fb2f9251fd9066986" - integrity sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA== +esbuild-linux-arm@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz#4e8b5deaa7ab60d0d28fab131244ef82b40684f4" + integrity sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ== -esbuild-linux-mips64le@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz#95081e42f698bbe35d8ccee0e3a237594b337eb5" - integrity sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ== +esbuild-linux-mips64le@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz#6f3bf3023f711084e5a1e8190487d2020f39f0f7" + integrity sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw== -esbuild-linux-ppc64le@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz#dceb0a1b186f5df679618882a7990bd422089b47" - integrity sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q== +esbuild-linux-ppc64le@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz#900e718a4ea3f6aedde8424828eeefdd4b48d4b9" + integrity sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ== -esbuild-linux-riscv64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz#61fb8edb75f475f9208c4a93ab2bfab63821afd2" - integrity sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ== +esbuild-linux-riscv64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz#dcbff622fa37047a75d2ff7a1d8d2949d80277e4" + integrity sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA== -esbuild-linux-s390x@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz#34c7126a4937406bf6a5e69100185fd702d12fe0" - integrity sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ== +esbuild-linux-s390x@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz#3f725a7945b419406c99d93744b28552561dcdfd" + integrity sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA== esbuild-loader@^2.18.0: version "2.18.0" @@ -11430,61 +11550,61 @@ esbuild-loader@^2.18.0: tapable "^2.2.0" webpack-sources "^2.2.0" -esbuild-netbsd-64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz#322ea9937d9e529183ee281c7996b93eb38a5d95" - integrity sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q== +esbuild-netbsd-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz#e10e40b6a765798b90d4eb85901cc85c8b7ff85e" + integrity sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA== -esbuild-openbsd-64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz#1ca29bb7a2bf09592dcc26afdb45108f08a2cdbd" - integrity sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ== +esbuild-openbsd-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz#935ec143f75ce10bd9cdb1c87fee00287eb0edbc" + integrity sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA== -esbuild-sunos-64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz#c9446f7d8ebf45093e7bb0e7045506a88540019b" - integrity sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA== +esbuild-sunos-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz#0e7aa82b022a2e6d55b0646738b2582c2d72c3c0" + integrity sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg== -esbuild-windows-32@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz#f8e9b4602fd0ccbd48e5c8d117ec0ba4040f2ad1" - integrity sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw== +esbuild-windows-32@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz#3f1538241f31b538545f4b5841b248cac260fa35" + integrity sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q== -esbuild-windows-64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz#280f58e69f78535f470905ce3e43db1746518107" - integrity sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw== +esbuild-windows-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz#b100c59f96d3c2da2e796e42fee4900d755d3e03" + integrity sha512-E2wm+5FwCcLpKsBHRw28bSYQw0Ikxb7zIMxw3OPAkiaQhLVr3dnVO8DofmbWhhf6b97bWzg37iSZ45ZDpLw7Ow== -esbuild-windows-arm64@0.14.38: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz#d97e9ac0f95a4c236d9173fa9f86c983d6a53f54" - integrity sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw== +esbuild-windows-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz#00268517e665b33c89778d61f144e4256b39f631" + integrity sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA== esbuild@^0.14.1, esbuild@^0.14.10, esbuild@^0.14.6: - version "0.14.38" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.38.tgz#99526b778cd9f35532955e26e1709a16cca2fb30" - integrity sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA== + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz#c926b2259fe6f6d3a94f528fb42e103c5a6d909a" + integrity sha512-2kKujuzvRWYtwvNjYDY444LQIA3TyJhJIX3Yo4+qkFlDDtGlSicWgeHVJqMUP/2sSfH10PGwfsj+O2ro1m10xQ== optionalDependencies: - esbuild-android-64 "0.14.38" - esbuild-android-arm64 "0.14.38" - esbuild-darwin-64 "0.14.38" - esbuild-darwin-arm64 "0.14.38" - esbuild-freebsd-64 "0.14.38" - esbuild-freebsd-arm64 "0.14.38" - esbuild-linux-32 "0.14.38" - esbuild-linux-64 "0.14.38" - esbuild-linux-arm "0.14.38" - esbuild-linux-arm64 "0.14.38" - esbuild-linux-mips64le "0.14.38" - esbuild-linux-ppc64le "0.14.38" - esbuild-linux-riscv64 "0.14.38" - esbuild-linux-s390x "0.14.38" - esbuild-netbsd-64 "0.14.38" - esbuild-openbsd-64 "0.14.38" - esbuild-sunos-64 "0.14.38" - esbuild-windows-32 "0.14.38" - esbuild-windows-64 "0.14.38" - esbuild-windows-arm64 "0.14.38" + esbuild-android-64 "0.14.39" + esbuild-android-arm64 "0.14.39" + esbuild-darwin-64 "0.14.39" + esbuild-darwin-arm64 "0.14.39" + esbuild-freebsd-64 "0.14.39" + esbuild-freebsd-arm64 "0.14.39" + esbuild-linux-32 "0.14.39" + esbuild-linux-64 "0.14.39" + esbuild-linux-arm "0.14.39" + esbuild-linux-arm64 "0.14.39" + esbuild-linux-mips64le "0.14.39" + esbuild-linux-ppc64le "0.14.39" + esbuild-linux-riscv64 "0.14.39" + esbuild-linux-s390x "0.14.39" + esbuild-netbsd-64 "0.14.39" + esbuild-openbsd-64 "0.14.39" + esbuild-sunos-64 "0.14.39" + esbuild-windows-32 "0.14.39" + esbuild-windows-64 "0.14.39" + esbuild-windows-arm64 "0.14.39" escalade@^3.1.1: version "3.1.1" @@ -11717,11 +11837,11 @@ eslint-webpack-plugin@^3.1.1: schema-utils "^3.1.1" eslint@^8.6.0: - version "8.14.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz#62741f159d9eb4a79695b28ec4989fcdec623239" - integrity sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw== + version "8.15.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz#fea1d55a7062da48d82600d2e0974c55612a11e9" + integrity sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA== dependencies: - "@eslint/eslintrc" "^1.2.2" + "@eslint/eslintrc" "^1.2.3" "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" chalk "^4.0.0" @@ -11732,7 +11852,7 @@ eslint@^8.6.0: eslint-scope "^7.1.1" eslint-utils "^3.0.0" eslint-visitor-keys "^3.3.0" - espree "^9.3.1" + espree "^9.3.2" esquery "^1.4.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -11748,7 +11868,7 @@ eslint@^8.6.0: json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" - minimatch "^3.0.4" + minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.1" regexpp "^3.2.0" @@ -11762,13 +11882,13 @@ esm@^3.2.25: resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -espree@^9.3.1: - version "9.3.1" - resolved "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" - integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== +espree@^9.3.2: + version "9.3.2" + resolved "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596" + integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA== dependencies: - acorn "^8.7.0" - acorn-jsx "^5.3.1" + acorn "^8.7.1" + acorn-jsx "^5.3.2" eslint-visitor-keys "^3.3.0" esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: @@ -11825,10 +11945,10 @@ etag@~1.8.1: resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -event-source-polyfill@1.0.26: - version "1.0.26" - resolved "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.26.tgz#86c04d088ef078279168eefa028f928fec5059a4" - integrity sha512-IwDLs9fUTcGAyacHBeS53T8wcEkDyDn0UP4tfQqJ4wQP8AyH0mszuQf2ULTylnpI0sMquzJ4usrNV7+uztwI9A== +event-source-polyfill@1.0.25: + version "1.0.25" + resolved "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.25.tgz#d8bb7f99cb6f8119c2baf086d9f6ee0514b6d9c8" + integrity sha512-hQxu6sN1Eq4JjoI7ITdQeGGUN193A2ra83qC0Ltm9I2UJVAten3OFVN6k5RX4YWeCS0BoC8xg/5czOCIHVosQg== event-stream@=3.3.4: version "3.3.4" @@ -11877,60 +11997,60 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: safe-buffer "^5.1.1" "example-app@link:packages/app": - version "0.2.71-next.1" + version "0.2.71-next.2" dependencies: "@backstage/app-defaults" "^1.0.2-next.0" - "@backstage/catalog-model" "^1.0.1" - "@backstage/cli" "^0.17.1-next.1" - "@backstage/config" "^1.0.0" - "@backstage/core-app-api" "^1.0.2-next.0" - "@backstage/core-components" "^0.9.4-next.0" - "@backstage/core-plugin-api" "^1.0.2-next.0" - "@backstage/integration-react" "^1.1.0-next.1" - "@backstage/plugin-airbrake" "^0.3.5-next.1" + "@backstage/catalog-model" "^1.0.2-next.0" + "@backstage/cli" "^0.17.1-next.2" + "@backstage/config" "^1.0.1-next.0" + "@backstage/core-app-api" "^1.0.2-next.1" + "@backstage/core-components" "^0.9.4-next.1" + "@backstage/core-plugin-api" "^1.0.2-next.1" + "@backstage/integration-react" "^1.1.0-next.2" + "@backstage/plugin-airbrake" "^0.3.5-next.2" "@backstage/plugin-apache-airflow" "^0.1.13-next.0" - "@backstage/plugin-api-docs" "^0.8.5-next.1" - "@backstage/plugin-azure-devops" "^0.1.21-next.1" - "@backstage/plugin-badges" "^0.2.29-next.1" - "@backstage/plugin-catalog" "^1.2.0-next.1" - "@backstage/plugin-catalog-common" "^1.0.1" - "@backstage/plugin-catalog-graph" "^0.2.17-next.1" - "@backstage/plugin-catalog-import" "^0.8.8-next.1" - "@backstage/plugin-catalog-react" "^1.1.0-next.1" - "@backstage/plugin-circleci" "^0.3.5-next.1" - "@backstage/plugin-cloudbuild" "^0.3.5-next.1" - "@backstage/plugin-code-coverage" "^0.1.32-next.1" - "@backstage/plugin-cost-insights" "^0.11.27-next.0" - "@backstage/plugin-explore" "^0.3.36-next.1" + "@backstage/plugin-api-docs" "^0.8.5-next.2" + "@backstage/plugin-azure-devops" "^0.1.21-next.2" + "@backstage/plugin-badges" "^0.2.29-next.2" + "@backstage/plugin-catalog" "^1.2.0-next.2" + "@backstage/plugin-catalog-common" "^1.0.2-next.0" + "@backstage/plugin-catalog-graph" "^0.2.17-next.2" + "@backstage/plugin-catalog-import" "^0.8.8-next.2" + "@backstage/plugin-catalog-react" "^1.1.0-next.2" + "@backstage/plugin-circleci" "^0.3.5-next.2" + "@backstage/plugin-cloudbuild" "^0.3.5-next.2" + "@backstage/plugin-code-coverage" "^0.1.32-next.2" + "@backstage/plugin-cost-insights" "^0.11.27-next.1" + "@backstage/plugin-explore" "^0.3.36-next.2" "@backstage/plugin-gcalendar" "^0.3.1-next.1" "@backstage/plugin-gcp-projects" "^0.3.24-next.0" - "@backstage/plugin-github-actions" "^0.5.5-next.1" - "@backstage/plugin-gocd" "^0.1.11-next.1" - "@backstage/plugin-graphiql" "^0.2.37-next.0" - "@backstage/plugin-home" "^0.4.21-next.1" - "@backstage/plugin-jenkins" "^0.7.4-next.1" - "@backstage/plugin-kafka" "^0.3.5-next.1" - "@backstage/plugin-kubernetes" "^0.6.5-next.1" - "@backstage/plugin-lighthouse" "^0.3.5-next.1" + "@backstage/plugin-github-actions" "^0.5.5-next.2" + "@backstage/plugin-gocd" "^0.1.11-next.2" + "@backstage/plugin-graphiql" "^0.2.37-next.1" + "@backstage/plugin-home" "^0.4.21-next.2" + "@backstage/plugin-jenkins" "^0.7.4-next.2" + "@backstage/plugin-kafka" "^0.3.5-next.2" + "@backstage/plugin-kubernetes" "^0.6.5-next.2" + "@backstage/plugin-lighthouse" "^0.3.5-next.2" "@backstage/plugin-newrelic" "^0.3.23-next.0" - "@backstage/plugin-newrelic-dashboard" "^0.1.13-next.1" - "@backstage/plugin-org" "^0.5.5-next.1" - "@backstage/plugin-pagerduty" "0.3.32-next.1" - "@backstage/plugin-permission-react" "^0.4.1-next.0" - "@backstage/plugin-rollbar" "^0.4.5-next.1" - "@backstage/plugin-scaffolder" "^1.2.0-next.1" - "@backstage/plugin-search" "^0.8.1-next.1" - "@backstage/plugin-search-common" "^0.3.3" - "@backstage/plugin-search-react" "^0.2.0-next.1" - "@backstage/plugin-sentry" "^0.3.43-next.1" + "@backstage/plugin-newrelic-dashboard" "^0.1.13-next.2" + "@backstage/plugin-org" "^0.5.5-next.2" + "@backstage/plugin-pagerduty" "0.3.32-next.2" + "@backstage/plugin-permission-react" "^0.4.1-next.1" + "@backstage/plugin-rollbar" "^0.4.5-next.2" + "@backstage/plugin-scaffolder" "^1.2.0-next.2" + "@backstage/plugin-search" "^0.8.1-next.2" + "@backstage/plugin-search-common" "^0.3.4-next.0" + "@backstage/plugin-search-react" "^0.2.0-next.2" + "@backstage/plugin-sentry" "^0.3.43-next.2" "@backstage/plugin-shortcuts" "^0.2.6-next.0" - "@backstage/plugin-stack-overflow" "^0.1.1-next.1" - "@backstage/plugin-tech-insights" "^0.2.1-next.1" + "@backstage/plugin-stack-overflow" "^0.1.1-next.2" + "@backstage/plugin-tech-insights" "^0.2.1-next.2" "@backstage/plugin-tech-radar" "^0.5.12-next.0" - "@backstage/plugin-techdocs" "^1.1.1-next.1" - "@backstage/plugin-techdocs-module-addons-contrib" "^0.1.0-next.1" - "@backstage/plugin-techdocs-react" "^0.1.1-next.1" - "@backstage/plugin-todo" "^0.2.7-next.1" + "@backstage/plugin-techdocs" "^1.1.1-next.2" + "@backstage/plugin-techdocs-module-addons-contrib" "^0.1.0-next.2" + "@backstage/plugin-techdocs-react" "^0.1.1-next.2" + "@backstage/plugin-todo" "^0.2.7-next.2" "@backstage/plugin-user-settings" "^0.4.4-next.0" "@backstage/theme" "^0.2.15" "@material-ui/core" "^4.12.2" @@ -12077,11 +12197,11 @@ express-promise-router@^4.1.0: methods "^1.0.0" express-session@^1.17.1: - version "1.17.2" - resolved "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz#397020374f9bf7997f891b85ea338767b30d0efd" - integrity sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ== + version "1.17.3" + resolved "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz#14b997a15ed43e5949cb1d073725675dd2777f36" + integrity sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw== dependencies: - cookie "0.4.1" + cookie "0.4.2" cookie-signature "1.0.6" debug "2.6.9" depd "~2.0.0" @@ -12228,17 +12348,16 @@ fast-equals@^2.0.0: resolved "https://registry.npmjs.org/fast-equals/-/fast-equals-2.0.4.tgz#3add9410585e2d7364c2deeb6a707beadb24b927" integrity sha512-caj/ZmjHljPrZtbzJ3kfH5ia/k4mTJe/qSiXAGzxZWRZgsgDV0cvNaQULqUX8t0/JVlzzEdYOwCN5DmzTxoD4w== -fast-glob@^3.1.1: - version "3.2.2" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" - integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" + glob-parent "^5.1.2" merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" + micromatch "^4.0.4" fast-json-parse@^1.0.3: version "1.0.3" @@ -13052,7 +13171,7 @@ github-from-package@0.0.0: resolved "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= -glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.2: +glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -13170,15 +13289,15 @@ globalthis@^1.0.1: define-properties "^1.1.3" globby@^11.0.0, globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.0.4: - version "11.0.4" - resolved "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + version "11.1.0" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" globby@^7.1.1: @@ -13284,11 +13403,11 @@ grapheme-splitter@^1.0.4: integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== graphiql@^1.5.12, graphiql@^1.8.8: - version "1.8.8" - resolved "https://registry.npmjs.org/graphiql/-/graphiql-1.8.8.tgz#eef760097b20901c0427f831ee6403fbdb2711b8" - integrity sha512-0AwnT7YnLU0Y+rQSZgdL7HxFJtAC2emyQAzsaqTglur/gSqw+4115LYi9tNRLGnFpxGE8giTslYLh9P0RdhiWg== + version "1.8.9" + resolved "https://registry.npmjs.org/graphiql/-/graphiql-1.8.9.tgz#96063ace9379699e873da078bf0f2ae7062f370e" + integrity sha512-X+olqol3VfOrFrsAfYzgNbvHoEE0lDUtg52+f3yLeNY4Ens+rAH4RSdH4wVtoRdh3CafmhVsfLQvn04hHkgftQ== dependencies: - "@graphiql/toolkit" "^0.4.3" + "@graphiql/toolkit" "^0.4.4" codemirror "^5.65.3" codemirror-graphql "^1.3.0" copy-to-clipboard "^3.2.0" @@ -13377,9 +13496,9 @@ graphql@^15.5.1: integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== graphql@^16.0.0, graphql@^16.3.0: - version "16.3.0" - resolved "https://registry.npmjs.org/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05" - integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A== + version "16.5.0" + resolved "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85" + integrity sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA== grouped-queue@^2.0.0: version "2.0.0" @@ -13894,10 +14013,10 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -husky@^7.0.4: - version "7.0.4" - resolved "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535" - integrity sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ== +husky@^8.0.0: + version "8.0.1" + resolved "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz#511cb3e57de3e3190514ae49ed50f6bc3f50b3e9" + integrity sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw== hyphenate-style-name@^1.0.2, hyphenate-style-name@^1.0.3: version "1.0.3" @@ -13992,9 +14111,9 @@ immer@9.0.7: integrity sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA== immer@^9.0.1, immer@^9.0.7: - version "9.0.12" - resolved "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" - integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== + version "9.0.13" + resolved "https://registry.npmjs.org/immer/-/immer-9.0.13.tgz#cee90eb7d46513d58daab0d7c2e6ef69aa4c1786" + integrity sha512-LufFIoBO2q3CZoUiObiV6ICK7QsrxOIo8ReQHggmYHA7aSbQdsAiZ+mkR3cjRD5ZxC/0P6EMdx2kk6oj1qyFLw== immutable@^3.x.x: version "3.8.2" @@ -14231,7 +14350,7 @@ invert-kv@^1.0.0: resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= -ioredis@^5.0.3: +ioredis@^5.0.4: version "5.0.4" resolved "https://registry.npmjs.org/ioredis/-/ioredis-5.0.4.tgz#0d4abfd818adfc5ef5029fddac4b8f503a1433b7" integrity sha512-qFJw3MnPNsJF1lcIOP3vztbsasOXK3nDdNAgjQj7t7/Bn/w10PGchTOpqylQNxjzPbLoYDu34LjeJtSWiKBntQ== @@ -14358,6 +14477,13 @@ is-buffer@^2.0.0: resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== +is-builtin-module@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.1.0.tgz#6fdb24313b1c03b75f8b9711c0feb8c30b903b00" + integrity sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg== + dependencies: + builtin-modules "^3.0.0" + is-callable@^1.1.4, is-callable@^1.2.4: version "1.2.4" resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" @@ -14915,9 +15041,9 @@ isomorphic-form-data@^2.0.0: form-data "^2.3.2" isomorphic-git@^1.8.0: - version "1.17.1" - resolved "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.17.1.tgz#ac5a095b78cf5ceef51954f5df4b1bdd24943e5f" - integrity sha512-JLZzAmc78yELH6+bZgMzqV0KGEi2duo+URWmyEnSbhhibHwDsMIlUw5tr1ZVHjC2CUQtU0X/5EY9Sbzsyx7nug== + version "1.17.2" + resolved "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.17.2.tgz#d49eda3122dfa3b860f0c68d651297c6403b715f" + integrity sha512-KtYyJye7Ad1XSgObsw7dwn3OaEcGUy04BHv6D+qBz2BWY7T7q7HXBzoSOiVvVMbOo+K2EZ2MUT+g2QkpJCPQLQ== dependencies: async-lock "^1.1.0" clean-git-ref "^2.0.1" @@ -15670,7 +15796,7 @@ json-buffer@3.0.1, json-buffer@^3.0.1, json-buffer@~3.0.1: resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: +json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== @@ -16052,11 +16178,11 @@ keyv@^3.0.0: json-buffer "3.0.0" keyv@^4.0.0, keyv@^4.0.3: - version "4.2.2" - resolved "https://registry.npmjs.org/keyv/-/keyv-4.2.2.tgz#4b6f602c0228ef4d8214c03c520bef469ed6b768" - integrity sha512-uYS0vKTlBIjNCAUqrjlxmruxOEiZxZIHXyp32sdcGmP+ukFrmWUnE//RcPXJH3Vxrni1H2gsQbjHE0bH7MtMQQ== + version "4.2.7" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.2.7.tgz#00b8994d46098e8eb8c933cb29aaaf18be5effea" + integrity sha512-HeOstD8SXvtWoQhMMBCelcUuZsiV7T7MwsADtOXT0KuwYP9nCxrSoMDeLXNDTLN3VFSuRp38JzoGbbTboq3QQw== dependencies: - compress-brotli "^1.3.6" + compress-brotli "^1.3.8" json-buffer "3.0.1" kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: @@ -16183,9 +16309,9 @@ ldapjs@^2.2.0: verror "^1.8.1" leasot@^12.0.0: - version "12.0.0" - resolved "https://registry.npmjs.org/leasot/-/leasot-12.0.0.tgz#78c5df2c941c7285374c8d992866e22163241b22" - integrity sha512-TMe3cJTRUMpXsOFNXCig5U84wM44y84vawkl2fC7iAJif88l/b7BtTt49VrkMsivlxlqHYVu5PjuxB9sRQf39w== + version "12.5.0" + resolved "https://registry.npmjs.org/leasot/-/leasot-12.5.0.tgz#d2b0273d0eaa3fc20ded2ede81b46b9c6f158451" + integrity sha512-bx2hqCDZ6EVzdaM+aIBNO12Ff0BscGVWPf23Wzj5FLCEXZuJR729Wn5Naom8dJcqpEbsk2XXzvdHus/3WZqW5w== dependencies: async "^3.2.0" chalk "^4.1.0" @@ -16697,7 +16823,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.7.0, lodash@~4.17.0, lodash@~4.17.15, lodash@~4.17.4: +lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.7.0, lodash@~4.17.0, lodash@~4.17.15, lodash@~4.17.4: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -16834,9 +16960,9 @@ lunr@^2.3.9: integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== luxon@^2.0.2, luxon@^2.3.0: - version "2.3.2" - resolved "https://registry.npmjs.org/luxon/-/luxon-2.3.2.tgz#5f2f3002b8c39b60a7b7ad24b2a85d90dc5db49c" - integrity sha512-MlAQQVMFhGk4WUA6gpfsy0QycnKP0+NlCBJRVRNPxxSIbjrCbQ65nrpJD3FVyJNZLuJ0uoqL57ye6BmDYgHaSw== + version "2.4.0" + resolved "https://registry.npmjs.org/luxon/-/luxon-2.4.0.tgz#9435806545bb32d4234dab766ab8a3d54847a765" + integrity sha512-w+NAwWOUL5hO0SgwOHsMBAmZ15SoknmQXhSO0hIbJCAmPKSsGeK8MlmhYh2w6Iib38IxN2M+/ooXWLbeis7GuA== lz-string@^1.4.4: version "1.4.4" @@ -16998,9 +17124,9 @@ markdown-table@^3.0.0: integrity sha512-CBbaYXKSGnE1uLRpKA1SWgIRb2PQrpkllNWpZtZe6VojOJ4ysqiq7/2glYcmKsOYN09QgH/HEBX5hIshAeiK6A== marked@^4.0.14: - version "4.0.14" - resolved "https://registry.npmjs.org/marked/-/marked-4.0.14.tgz#7a3a5fa5c80580bac78c1ed2e3b84d7bd6fc3870" - integrity sha512-HL5sSPE/LP6U9qKgngIIPTthuxC0jrfxpYMZ3LdGDD3vTnLs59m2Z7r6+LNDR3ToqEQdkKd6YaaEfJhodJmijQ== + version "4.0.15" + resolved "https://registry.npmjs.org/marked/-/marked-4.0.15.tgz#0216b7c9d5fcf6ac5042343c41d81a8b1b5e1b4a" + integrity sha512-esX5lPdTfG4p8LDkv+obbRCyOKzB+820ZZyMOXJZygZBHrH9b3xXR64X4kT3sPe9Nx8qQXbmcz6kFSMt4Nfk6Q== match-sorter@^6.0.2: version "6.3.1" @@ -17280,6 +17406,11 @@ merge2@^1.3.0: resolved "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== +merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + merge@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" @@ -18453,9 +18584,9 @@ npm-packlist@^3.0.0: npm-normalize-package-bin "^1.0.1" npm-packlist@^5.0.0: - version "5.0.2" - resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.0.2.tgz#a5eb2503faec92ad6853a2bbb2231dced6cfc549" - integrity sha512-jLhcNisUgpz6v2KC75qSeEYAM8UBMYjQ2OhlCOJjB4Ovu7XXnD25UqZ6hOQNeGShL/2ju3LL2E/zBbsuzkIQ8w== + version "5.0.3" + resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.0.3.tgz#0aec03bc2d6d488ca71396d7afb463563c3274f7" + integrity sha512-KuSbzgejxdsAWbNNyEs8EsyDHsO+nJF6k+9WuWzFbSNh5tFHs4lDApXw7kntKpuehfp8lKRzJkMtz0+WmGvTIw== dependencies: glob "^8.0.1" ignore-walk "^5.0.1" @@ -18803,9 +18934,9 @@ openid-client@^4.1.1: oidc-token-hash "^5.0.1" openid-client@^5.1.3: - version "5.1.5" - resolved "https://registry.npmjs.org/openid-client/-/openid-client-5.1.5.tgz#cac1e50015937e5af70be45e1ae5b1cb113f1f74" - integrity sha512-m41p7V/iXyqc0WZeo20uwKk8NPDAtYd3JS0uWjttcqwvFo4YNYAKegMAMea1qG5RClddQ6rV9ec/TP6ZvsCrYw== + version "5.1.6" + resolved "https://registry.npmjs.org/openid-client/-/openid-client-5.1.6.tgz#e5eb2032ecfdcfc108660b5c525910a14e352f11" + integrity sha512-HTFaXWdUHvLFw4GaEMgC0jXYBgpjgzQQNHW1pZsSqJorSgrXzxJ+4u/LWCGaClDEse5HLjXRV+zU5Bn3OefiZw== dependencies: jose "^4.1.4" lru-cache "^6.0.0" @@ -19792,15 +19923,6 @@ popper.js@1.16.1-lts: resolved "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" integrity sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA== -portfinder@^1.0.28: - version "1.0.28" - resolved "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" - posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -20477,14 +20599,14 @@ pupa@^2.1.1: dependencies: escape-goat "^2.0.0" -puppeteer@^13.1.1: - version "13.7.0" - resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-13.7.0.tgz#18e16f83e397cf02f7a0804c67c1603d381cfb0b" - integrity sha512-U1uufzBjz3+PkpCxFrWzh4OrMIdIb2ztzCu0YEPfRHjHswcSwHZswnK+WdsOQJsRV8WeTg3jLhJR4D867+fjsA== +puppeteer@^14.0.0: + version "14.0.0" + resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-14.0.0.tgz#829e97b70fa81746bb88ec2d72f11a7429cc84ab" + integrity sha512-Aj/cySGBMWpUYEWV0YOcwyhq5lOxuuiGScgdj/OvslAm/ydoywiI8OzAIXT4HzKmNTmzm/fKKHHtcsQa/fFgdw== dependencies: cross-fetch "3.1.5" debug "4.3.4" - devtools-protocol "0.0.981744" + devtools-protocol "0.0.982423" extract-zip "2.0.1" https-proxy-agent "5.0.1" pkg-dir "4.2.0" @@ -20493,7 +20615,7 @@ puppeteer@^13.1.1: rimraf "3.0.2" tar-fs "2.1.1" unbzip2-stream "1.4.3" - ws "8.5.0" + ws "8.6.0" q@^1.5.1: version "1.5.1" @@ -20646,6 +20768,15 @@ rc-progress@3.2.4: classnames "^2.2.6" rc-util "^5.16.1" +rc-progress@3.3.2: + version "3.3.2" + resolved "https://registry.npmjs.org/rc-progress/-/rc-progress-3.3.2.tgz#57362d49bb6b7b09fec84bf18220619294bde675" + integrity sha512-m+1LtVlXIomz8lcghfF/kViT5h/NtdWp87hnFL+FlnrxyZCEuB4N5BKNN6ctZa3a1Mae+4SMO8AG5lScjU06Ig== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "^2.2.6" + rc-util "^5.16.1" + rc-util@^5.16.1: version "5.16.1" resolved "https://registry.npmjs.org/rc-util/-/rc-util-5.16.1.tgz#374db7cb735512f05165ddc3d6b2c61c21b8b4e3" @@ -20771,9 +20902,9 @@ react-helmet@6.1.0: react-side-effect "^2.1.0" react-hook-form@^7.12.2, react-hook-form@^7.13.0: - version "7.29.0" - resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.29.0.tgz#5e7e41a483b70731720966ed8be52163ea1fecf1" - integrity sha512-NcJqWRF6el5HMW30fqZRt27s+lorvlCCDbTpAyHoodQeYWXgQCvZJJQLC1kRMKdrJknVH0NIg3At6TUzlZJFOQ== + version "7.31.1" + resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.31.1.tgz#16c357dd366bc226172e6acbb5a1672873bbfb28" + integrity sha512-QjtjZ8r8KtEBWWpcXLyQordCraTFxILtyQpaz5KLLxN2YzcC+FZ9LLtOnNGuOnzZo9gCoB+viK3ZHV9Mb2htmQ== react-hot-loader@^4.13.0: version "4.13.0" @@ -20852,9 +20983,9 @@ react-markdown@^8.0.0: vfile "^5.0.0" react-query@^3.34.16: - version "3.34.19" - resolved "https://registry.npmjs.org/react-query/-/react-query-3.34.19.tgz#0ff049b6e0d2ed148e9abfdd346625d0e88dc229" - integrity sha512-JO0Ymi58WKmvnhgg6bGIrYIeKb64KsKaPWo8JcGnmK2jJxAs2XmMBzlP75ZepSU7CHzcsWtIIyhMrLbX3pb/3w== + version "3.39.0" + resolved "https://registry.npmjs.org/react-query/-/react-query-3.39.0.tgz#0caca7b0da98e65008bbcd4df0d25618c2100050" + integrity sha512-Od0IkSuS79WJOhzWBx/ys0x13+7wFqgnn64vBqqAAnZ9whocVhl/y1padD5uuZ6EIkXbFbInax0qvY7zGM0thA== dependencies: "@babel/runtime" "^7.5.5" broadcast-channel "^3.4.1" @@ -21900,9 +22031,9 @@ rollup@^0.63.4: "@types/node" "*" rollup@^2.60.2: - version "2.70.2" - resolved "https://registry.npmjs.org/rollup/-/rollup-2.70.2.tgz#808d206a8851628a065097b7ba2053bd83ba0c0d" - integrity sha512-EitogNZnfku65I1DD5Mxe8JYRUCy0hkK5X84IlDtUs+O6JRMpRciXTzyCUuX11b5L5pvjH+OmFXiQ3XjabcXgg== + version "2.72.1" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.72.1.tgz#861c94790537b10008f0ca0fbc60e631aabdd045" + integrity sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA== optionalDependencies: fsevents "~2.3.2" @@ -23266,9 +23397,9 @@ stylis@^4.0.6: integrity sha512-OFFeUXFgwnGOKvEXaSv0D0KQ5ADP0n6g3SVONx6I/85JzNZ3u50FRwB3lVIk1QO2HNdI75tbVzc4Z66Gdp9voA== sucrase@^3.18.0, sucrase@^3.20.2: - version "3.20.3" - resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.20.3.tgz#424f1e75b77f955724b06060f1ae708f5f0935cf" - integrity sha512-azqwq0/Bs6RzLAdb4dXxsCgMtAaD2hzmUr4UhSfsxO46JFPAwMnnb441B/qsudZiS6Ylea3JXZe3Q497lsgXzQ== + version "3.21.0" + resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.21.0.tgz#6a5affdbe716b22e4dc99c57d366ad0d216444b9" + integrity sha512-FjAhMJjDcifARI7bZej0Bi1yekjWQHoEvWIXhLPwDhC6O4iZ5PtGb86WV56riW87hzpgB13wwBKO9vKAiWu5VQ== dependencies: commander "^4.0.0" glob "7.1.6" @@ -23385,9 +23516,9 @@ swagger-client@^3.18.4: url "~0.11.0" swagger-ui-react@^4.1.3: - version "4.10.3" - resolved "https://registry.npmjs.org/swagger-ui-react/-/swagger-ui-react-4.10.3.tgz#72b7eb432f3e1ad09a81556af75d22ac3a66ae40" - integrity sha512-rxLVM8hv6aH+8BEJuyfejt2BweV2TLB8KiifE/8CAk96PoDyQeCTnLgivTdXIuDqdSSSajlzTq0ccw0QMYQbvA== + version "4.11.0" + resolved "https://registry.npmjs.org/swagger-ui-react/-/swagger-ui-react-4.11.0.tgz#995597c050c2c63fafdfd1874661fa3b329008e4" + integrity sha512-QAQVoT7a9CfhyxTmy9MrXCL9l4Y2B60QMAthdTsZdHAH3mGsZF0KH18a+gFncGTN4sotuyIDiOgoPRP5idiz6g== dependencies: "@babel/runtime-corejs3" "^7.16.8" "@braintree/sanitize-url" "=6.0.0" @@ -23532,20 +23663,20 @@ tdigest@^0.1.1: bintrees "1.0.1" "techdocs-cli-embedded-app@link:packages/techdocs-cli-embedded-app": - version "0.2.70-next.1" + version "0.2.70-next.2" dependencies: "@backstage/app-defaults" "^1.0.2-next.0" - "@backstage/catalog-model" "^1.0.1" - "@backstage/cli" "^0.17.1-next.1" - "@backstage/config" "^1.0.0" - "@backstage/core-app-api" "^1.0.2-next.0" - "@backstage/core-components" "^0.9.4-next.0" - "@backstage/core-plugin-api" "^1.0.2-next.0" - "@backstage/integration-react" "^1.1.0-next.1" - "@backstage/plugin-catalog" "^1.2.0-next.1" - "@backstage/plugin-techdocs" "^1.1.1-next.1" - "@backstage/plugin-techdocs-react" "^0.1.1-next.1" - "@backstage/test-utils" "^1.1.0-next.1" + "@backstage/catalog-model" "^1.0.2-next.0" + "@backstage/cli" "^0.17.1-next.2" + "@backstage/config" "^1.0.1-next.0" + "@backstage/core-app-api" "^1.0.2-next.1" + "@backstage/core-components" "^0.9.4-next.1" + "@backstage/core-plugin-api" "^1.0.2-next.1" + "@backstage/integration-react" "^1.1.0-next.2" + "@backstage/plugin-catalog" "^1.2.0-next.2" + "@backstage/plugin-techdocs" "^1.1.1-next.2" + "@backstage/plugin-techdocs-react" "^0.1.1-next.2" + "@backstage/test-utils" "^1.1.0-next.2" "@backstage/theme" "^0.2.15" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" @@ -23634,14 +23765,14 @@ test-exclude@^6.0.0: minimatch "^3.0.4" testcontainers@^8.1.2: - version "8.6.1" - resolved "https://registry.npmjs.org/testcontainers/-/testcontainers-8.6.1.tgz#a37b1eb938665f333594837caaed806ea51f7217" - integrity sha512-yRRx55tVOwExivh6BSrbZXItmRUm5qdMks1nN3n2P7n4DIJOl4VHIcI3HiRucU4hMsbT8lXx68+xQFqz3W+ZSQ== + version "8.10.0" + resolved "https://registry.npmjs.org/testcontainers/-/testcontainers-8.10.0.tgz#fae18c4b2016eb4b0d8cc992c47738e26d1d0717" + integrity sha512-7Kwcw9JFav2H+J9/0JF9ZYaxn4nvboLHyh0xpKHw8Imtoc8H2w/HgKJGgpn+hi6X1y1I0F24Z+jYkARYBgbdHQ== dependencies: "@balena/dockerignore" "^1.0.2" - "@types/archiver" "^5.1.1" - "@types/dockerode" "^3.2.7" - archiver "^5.3.0" + "@types/archiver" "^5.3.1" + "@types/dockerode" "^3.3.8" + archiver "^5.3.1" byline "^5.0.0" debug "^4.3.4" docker-compose "^0.23.17" @@ -24044,7 +24175,7 @@ tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.2.0, tslib@^2.3.0, resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== -tslib@^2.1.0: +tslib@^2.1.0, tslib@~2.4.0: version "2.4.0" resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== @@ -24584,10 +24715,10 @@ url@^0.11.0, url@~0.11.0: punycode "1.3.2" querystring "0.2.0" -use-immer@^0.6.0: - version "0.6.0" - resolved "https://registry.npmjs.org/use-immer/-/use-immer-0.6.0.tgz#ca6aa5ade93018e2c65cf128d19ada54fc23f70d" - integrity sha512-dFGRfvWCqPDTOt/S431ETYTg6+uxbpb7A1pptufwXVzGJY3RlXr38+3wyLNpc6SbbmAKjWl6+EP6uW74fkEsXQ== +use-immer@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/use-immer/-/use-immer-0.7.0.tgz#e3bfbb806b5e3ff6e37441be74c306d91c1e0962" + integrity sha512-Re4hjrP3a/2ABZjAc0b7AK9s626bnO+H33RO2VUhiDZ2StBz5B663K6WNNlr4QtHWaGUmvLpwt3whFvvWuolQw== use-memo-one@^1.1.1: version "1.1.1" @@ -24956,9 +25087,9 @@ webpack-dev-middleware@^5.3.1: schema-utils "^4.0.0" webpack-dev-server@^4.7.3: - version "4.8.1" - resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.8.1.tgz#58f9d797710d6e25fa17d6afab8708f958c11a29" - integrity sha512-dwld70gkgNJa33czmcj/PlKY/nOy/BimbrgZRaR9vDATBQAYgLzggR0nxDtPLJiLrMgZwbE6RRfJ5vnBBasTyg== + version "4.9.0" + resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.0.tgz#737dbf44335bb8bde68f8f39127fc401c97a1557" + integrity sha512-+Nlb39iQSOSsFv0lWUuUTim3jDQO8nhK3E68f//J2r5rIcp4lULHXz2oZ0UVdEeWXEh5lSzYUlzarZhDAeAVQw== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -24980,7 +25111,6 @@ webpack-dev-server@^4.7.3: ipaddr.js "^2.0.1" open "^8.0.9" p-retry "^4.5.0" - portfinder "^1.0.28" rimraf "^3.0.2" schema-utils "^4.0.0" selfsigned "^2.0.1" @@ -25009,9 +25139,9 @@ webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5, webpack@^5.66.0: - version "5.70.0" - resolved "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz#3461e6287a72b5e6e2f4872700bc8de0d7500e6d" - integrity sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw== + version "5.72.1" + resolved "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz#3500fc834b4e9ba573b9f430b2c0a61e1bb57d13" + integrity sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" @@ -25022,13 +25152,13 @@ webpack@^5, webpack@^5.66.0: acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.9.2" + enhanced-resolve "^5.9.3" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" graceful-fs "^4.2.9" - json-parse-better-errors "^1.0.2" + json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" @@ -25069,6 +25199,11 @@ whatwg-mimetype@^2.3.0: resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-mimetype@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" + integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -25178,9 +25313,9 @@ winston-transport@^4.5.0: triple-beam "^1.3.0" winston@^3.2.1: - version "3.6.0" - resolved "https://registry.npmjs.org/winston/-/winston-3.6.0.tgz#be32587a099a292b88c49fac6fa529d478d93fb6" - integrity sha512-9j8T75p+bcN6D00sF/zjFVmPp+t8KMPB1MzbbzYjeN9VWxdsYnTB40TkbNUEXAmILEfChMvAMgidlX64OG3p6w== + version "3.7.2" + resolved "https://registry.npmjs.org/winston/-/winston-3.7.2.tgz#95b4eeddbec902b3db1424932ac634f887c400b1" + integrity sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng== dependencies: "@dabh/diagnostics" "^2.0.2" async "^3.2.3" @@ -25302,16 +25437,21 @@ write-pkg@^4.0.0: type-fest "^0.4.1" write-json-file "^3.2.0" -ws@8.5.0, ws@^8.4.2: - version "8.5.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== +ws@8.6.0, ws@^8.0.0, ws@^8.3.0: + version "8.6.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz#e5e9f1d9e7ff88083d0c0dd8281ea662a42c9c23" + integrity sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw== -ws@^7.3.1, ws@^7.4.6, ws@^8.3.0: +ws@^7.3.1, ws@^7.4.6: version "7.5.7" resolved "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== +ws@^8.4.2: + version "8.5.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + ws@~7.4.2: version "7.4.6" resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" @@ -25717,9 +25857,9 @@ zip-stream@^4.1.0: readable-stream "^3.6.0" zod@^3.11.6, zod@^3.9.5: - version "3.14.4" - resolved "https://registry.npmjs.org/zod/-/zod-3.14.4.tgz#e678fe9e5469f4663165a5c35c8f3dc66334a5d6" - integrity sha512-U9BFLb2GO34Sfo9IUYp0w3wJLlmcyGoMd75qU9yf+DrdGA4kEx6e+l9KOkAlyUO0PSQzZCa3TR4qVlcmwqSDuw== + version "3.15.1" + resolved "https://registry.npmjs.org/zod/-/zod-3.15.1.tgz#9e404cd8002ccffb03baa94cff2e1638ed49d82f" + integrity sha512-WAdjcoOxa4S9oc/u7fTbC3CC7uVqptLLU0LKqS8RDBOrCXp2t5avM8BUfgNVZJymGWAx6SEUYxWPPoYuQ5rgwQ== zustand@3.6.9: version "3.6.9"