diff --git a/.changeset/breezy-ways-try.md b/.changeset/breezy-ways-try.md deleted file mode 100644 index 15e831a673..0000000000 --- a/.changeset/breezy-ways-try.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -'@backstage/cli': minor ---- - -Switch from `ts-jest` to `@sucrase/jest-plugin`, improving performance and aligning transpilation with bundling. - -In order to switch back to `ts-jest`, install `ts-jest@^26.4.3` as a dependency in the root of your repo and add the following in the root `package.json`: - -```json -"jest": { - "globals": { - "ts-jest": { - "isolatedModules": true - } - }, - "transform": { - "\\.esm\\.js$": "@backstage/cli/config/jestEsmTransform.js", - "\\.(js|jsx|ts|tsx)$": "ts-jest", - "\\.(bmp|gif|jpg|jpeg|png|frag|xml|svg)$": "@backstage/cli/config/jestFileTransform.js", - "\\.(yaml)$": "yaml-jest" - } -} -``` - -Note that this will override the default jest transforms included with the `@backstage/cli`. - -It is possible that some test code needs a small migration as a result of this change, which stems from a difference in how `sucrase` and `ts-jest` transform module re-exports. - -Consider the following code: - -```ts -import * as utils from './utils'; - -jest.spyOn(utils, 'myUtility').mockReturnValue(3); -``` - -If the `./utils` import for example refers to an index file that in turn re-exports from `./utils/myUtility`, you would have to change the code to the following to work around the fact that the exported object from `./utils` ends up not having configurable properties, thus breaking `jest.spyOn`. - -```ts -import * as utils from './utils/myUtility'; - -jest.spyOn(utils, 'myUtility').mockReturnValue(3); -``` diff --git a/.changeset/catalog-search-item.md b/.changeset/catalog-search-item.md deleted file mode 100644 index c1a12ec161..0000000000 --- a/.changeset/catalog-search-item.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -A `` component is now available for use in custom Search Experiences. diff --git a/.changeset/chilly-owls-punch.md b/.changeset/chilly-owls-punch.md new file mode 100644 index 0000000000..35fb581a81 --- /dev/null +++ b/.changeset/chilly-owls-punch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Exports `CatalogLayout` and `CreateComponentButton` for catalog customization. diff --git a/.changeset/clean-frogs-brake.md b/.changeset/clean-frogs-brake.md new file mode 100644 index 0000000000..ccbe551853 --- /dev/null +++ b/.changeset/clean-frogs-brake.md @@ -0,0 +1,10 @@ +--- +'@backstage/create-app': patch +--- + +Adding .DS_Store pattern to .gitignore in Scaffolded Backstage App. To migrate an existing app that pattern should be added manually. + +```diff ++# macOS ++.DS_Store +``` diff --git a/.changeset/cuddly-yaks-sneeze.md b/.changeset/cuddly-yaks-sneeze.md deleted file mode 100644 index 47d24d1cdb..0000000000 --- a/.changeset/cuddly-yaks-sneeze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-api': patch ---- - -Improve forwards compatibility with `@backstage/core-app-api` and `@backstage/core-plugin-api` by re-using route reference types and factory methods from `@backstage/core-plugin-api`. diff --git a/.changeset/cyan-suns-chew.md b/.changeset/cyan-suns-chew.md deleted file mode 100644 index 95d51c23fe..0000000000 --- a/.changeset/cyan-suns-chew.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -Move `canvas` package to `devDependencies`. diff --git a/.changeset/dull-poets-learn.md b/.changeset/dull-poets-learn.md new file mode 100644 index 0000000000..b504c0c6a3 --- /dev/null +++ b/.changeset/dull-poets-learn.md @@ -0,0 +1,52 @@ +--- +'@backstage/plugin-catalog-backend': patch +'@backstage/create-app': patch +--- + +This release enables the new catalog processing engine which is a major milestone for the catalog! + +This update makes processing more scalable across multiple instances, adds support for deletions and ui flagging of entities that are no longer referenced by a location. + +**Changes Required** to `catalog.ts` + +```diff +-import { useHotCleanup } from '@backstage/backend-common'; + import { + CatalogBuilder, +- createRouter, +- runPeriodically ++ createRouter + } from '@backstage/plugin-catalog-backend'; + import { Router } from 'express'; + import { PluginEnvironment } from '../types'; + + export default async function createPlugin(env: PluginEnvironment): Promise { +- const builder = new CatalogBuilder(env); ++ const builder = await CatalogBuilder.create(env); + const { + entitiesCatalog, + locationsCatalog, +- higherOrderOperation, ++ locationService, ++ processingEngine, + locationAnalyzer, + } = await builder.build(); + +- useHotCleanup( +- module, +- runPeriodically(() => higherOrderOperation.refreshAllLocations(), 100000), +- ); ++ await processingEngine.start(); + + return await createRouter({ + entitiesCatalog, + locationsCatalog, +- higherOrderOperation, ++ locationService, + locationAnalyzer, + logger: env.logger, + config: env.config, +``` + +As this is a major internal change we have taken some precaution by still allowing the old catalog to be enabled by keeping your `catalog.ts` in it's current state. +If you encounter any issues and have to revert to the previous catalog engine make sure to raise an issue immediately as the old catalog engine is deprecated and will be removed in a future release. diff --git a/.changeset/early-baboons-double.md b/.changeset/early-baboons-double.md deleted file mode 100644 index efbf0f559e..0000000000 --- a/.changeset/early-baboons-double.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Fixes a type bug where supplying all app icons to `createApp` was required, rather than just a partial list. diff --git a/.changeset/eight-doors-melt.md b/.changeset/eight-doors-melt.md deleted file mode 100644 index 7a44216746..0000000000 --- a/.changeset/eight-doors-melt.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Updated the `@gitbeaker/node` dependency past the broken one without a `dist` folder. - -See [this issue](https://github.com/jdalrymple/gitbeaker/issues/1861) for more details. - -If you get build errors that look like the following in your Backstage instance, you may want to also bump all of your `@gitbeaker/*` dependencies to at least `^30.2.0`. - -``` -node:internal/modules/cjs/loader:356 - throw err; - ^ - -Error: Cannot find module '/path/to/project/node_modules/@gitbeaker/node/dist/index.js'. Please verify that the package.json has a valid "main" entry - at tryPackage (node:internal/modules/cjs/loader:348:19) - at Function.Module._findPath (node:internal/modules/cjs/loader:561:18) - at Function.Module._resolveFilename (node:internal/modules/cjs/loader:926:27) - at Function.Module._load (node:internal/modules/cjs/loader:773:27) - at Module.require (node:internal/modules/cjs/loader:1012:19) - at require (node:internal/modules/cjs/helpers:93:18) - at Object. (/path/to/project/test.js:4:18) - at Module._compile (node:internal/modules/cjs/loader:1108:14) - at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10) - at Module.load (node:internal/modules/cjs/loader:988:32) { - code: 'MODULE_NOT_FOUND', - path: '/path/to/project/node_modules/@gitbeaker/node/package.json', - requestPath: '@gitbeaker/node' -} -``` - -you could also consider pinning the version to an older one in your `package.json` either root or `packages/backend/package.json`, before the breakage occurred. - -```json -"resolutions": { - "**/@gitbeaker/node": "29.2.4", - "**/@gitbeaker/core": "29.2.4", - "**/@gitbeaker/requester-utils": "29.2.4" -} -``` - -Be aware that this is only required short term until we can release our updated versions of `@backstage/plugin-scaffolder-backend`. diff --git a/.changeset/empty-berries-melt.md b/.changeset/empty-berries-melt.md deleted file mode 100644 index ab1125262a..0000000000 --- a/.changeset/empty-berries-melt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Restructure the next catalog types and files a bit diff --git a/.changeset/fair-points-grin.md b/.changeset/fair-points-grin.md new file mode 100644 index 0000000000..5c5b21b610 --- /dev/null +++ b/.changeset/fair-points-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Provide a more clear error message when database connection fails. diff --git a/.changeset/fast-trees-arrive.md b/.changeset/fast-trees-arrive.md new file mode 100644 index 0000000000..f74b6c1c9a --- /dev/null +++ b/.changeset/fast-trees-arrive.md @@ -0,0 +1,24 @@ +--- +'@backstage/cli': patch +--- + +Make `yarn dev` in newly created backend plugins respect the `PLUGIN_PORT` environment variable. + +You can achieve the same in your created backend plugins by making sure to properly call the port and CORS methods on your service builder. Typically in a file named `src/service/standaloneServer.ts` inside your backend plugin package, replace the following: + +```ts +const service = createServiceBuilder(module) + .enableCors({ origin: 'http://localhost:3000' }) + .addRouter('/my-plugin', router); +``` + +With something like the following: + +```ts +let service = createServiceBuilder(module) + .setPort(options.port) + .addRouter('/my-plugin', router); +if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); +} +``` diff --git a/.changeset/few-cats-type.md b/.changeset/few-cats-type.md deleted file mode 100644 index 45a59d5ada..0000000000 --- a/.changeset/few-cats-type.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -'@backstage/core-app-api': patch -'@backstage/core-components': patch -'@backstage/core-plugin-api': patch ---- - -This change adds automatic error boundaries around extensions. - -This means that all exposed parts of a plugin are wrapped in a general error boundary component, that is plugin aware. The default design for the error box is borrowed from `@backstage/errors`. To override the default "fallback", one must provide a component named `ErrorBoundaryFallback` to `createApp`, like so: - -```ts -const app = createApp({ - components: { - ErrorBoundaryFallback: props => { - // a custom fallback component - return ( - <> -

Oops.

-

- The plugin {props.plugin.getId()} failed with {props.error.message} -

- - - ); - }, - }, -}); -``` - -The props here include: - -- `error`. An `Error` object or something that inherits it that represents the error that was thrown from any inner component. -- `resetError`. A callback that will simply attempt to mount the children of the error boundary again. -- `plugin`. A `BackstagePlugin` that can be used to look up info to be presented in the error message. For instance, you may want to keep a map of your internal plugins and team names or slack channels and present these when an error occurs. Typically, you'll do that by getting the plugin ID with `plugin.getId()`. diff --git a/.changeset/fresh-vans-nail.md b/.changeset/fresh-vans-nail.md new file mode 100644 index 0000000000..64af4ee60b --- /dev/null +++ b/.changeset/fresh-vans-nail.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-splunk-on-call': patch +--- + +Added config schema to expose `splunkOnCall.eventsRestEndpoint` config option to the frontend diff --git a/.changeset/funny-toys-talk.md b/.changeset/funny-toys-talk.md new file mode 100644 index 0000000000..6e6a779ab8 --- /dev/null +++ b/.changeset/funny-toys-talk.md @@ -0,0 +1,5 @@ +--- +'@backstage/codemods': patch +--- + +Fix execution of `jscodeshift` on windows. diff --git a/.changeset/fuzzy-jobs-relate.md b/.changeset/fuzzy-jobs-relate.md new file mode 100644 index 0000000000..6828d6c3c0 --- /dev/null +++ b/.changeset/fuzzy-jobs-relate.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Switches the default catalog processing engine to use a batched streaming task execution strategy for higher parallelism. diff --git a/.changeset/giant-snakes-watch.md b/.changeset/giant-snakes-watch.md deleted file mode 100644 index 553518b678..0000000000 --- a/.changeset/giant-snakes-watch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Skip running docker tests unless in CI diff --git a/.changeset/gorgeous-pumas-tickle.md b/.changeset/gorgeous-pumas-tickle.md new file mode 100644 index 0000000000..2f653fae84 --- /dev/null +++ b/.changeset/gorgeous-pumas-tickle.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Rely on `SELECT ... FOR UPDATE SKIP LOCKED` where available in order to speed up processing item acquisition and reduce work duplication. diff --git a/.changeset/healthy-windows-dance.md b/.changeset/healthy-windows-dance.md new file mode 100644 index 0000000000..1015fb63c3 --- /dev/null +++ b/.changeset/healthy-windows-dance.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Use the correct parameter to create a public repository in Bitbucket Server for the v2 templates diff --git a/.changeset/heavy-terms-vanish.md b/.changeset/heavy-terms-vanish.md deleted file mode 100644 index 90a1b31e53..0000000000 --- a/.changeset/heavy-terms-vanish.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-actions': patch ---- - -Add missing token on job list call to GitHub API diff --git a/.changeset/hip-trees-heal.md b/.changeset/hip-trees-heal.md deleted file mode 100644 index 422402dcee..0000000000 --- a/.changeset/hip-trees-heal.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Omits the `upgrade-insecure-requests` Content-Security-Policy directive by default, to prevent automatic HTTPS request upgrading for HTTP-deployed Backstage sites. - -If you previously disabled this using `false` in your `app-config.yaml`, this line is no longer necessary: - -```diff -backend: - csp: -- upgrade-insecure-requests: false -``` - -To keep the existing behavior of `upgrade-insecure-requests` Content-Security-Policy being _enabled_, add the key with an empty array as the value in your `app-config.yaml`: - -```diff -backend: -+ csp: -+ upgrade-insecure-requests: [] -``` - -Read more on [upgrade-insecure-requests here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/upgrade-insecure-requests). diff --git a/.changeset/honest-rabbits-divide.md b/.changeset/honest-rabbits-divide.md new file mode 100644 index 0000000000..bf4b457383 --- /dev/null +++ b/.changeset/honest-rabbits-divide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Fix the link to the documentation page when no owned documents are displayed diff --git a/.changeset/khaki-dancers-admire.md b/.changeset/khaki-dancers-admire.md deleted file mode 100644 index 7c5c61aa90..0000000000 --- a/.changeset/khaki-dancers-admire.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@backstage/catalog-model': patch -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-scaffolder-backend': patch ---- - -Introduce conditional steps in scaffolder templates. - -A step can now include an `if` property that only executes a step if the -condition is truthy. The condition can include handlebar templates. - -```yaml -- id: register - if: '{{ not parameters.dryRun }}' - name: Register - action: catalog:register - input: - repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}' - catalogInfoPath: '/catalog-info.yaml' -``` - -Also introduces a `not` helper in handlebar templates that allows to negate -boolean expressions. diff --git a/.changeset/kind-tools-kneel.md b/.changeset/kind-tools-kneel.md new file mode 100644 index 0000000000..6296ac7011 --- /dev/null +++ b/.changeset/kind-tools-kneel.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Make refresh interval configurable for the `NextCatalogBuilder` using `.setRefreshIntervalSeconds()`. + +Change `DefaultProcessingDatabase` constructor to accept an options object instead of individual arguments. diff --git a/.changeset/slimy-games-brake.md b/.changeset/lazy-cougars-rule.md similarity index 53% rename from .changeset/slimy-games-brake.md rename to .changeset/lazy-cougars-rule.md index a8fafb09f3..cc6ec91bd5 100644 --- a/.changeset/slimy-games-brake.md +++ b/.changeset/lazy-cougars-rule.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder-backend': patch --- -Add `debug:log` action for debugging. +Adds support to enable LFS for hosted Bitbucket diff --git a/.changeset/long-socks-fold.md b/.changeset/long-socks-fold.md deleted file mode 100644 index 23a7811685..0000000000 --- a/.changeset/long-socks-fold.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/integration-react': patch -'@backstage/plugin-catalog': patch ---- - -Move `ScmIntegrationIcon` from `@backstage/plugin-catalog` to -`@backstage/integration-react` and make it customizable using -`app.getSystemIcon()`. diff --git a/.changeset/modern-ladybugs-perform.md b/.changeset/modern-ladybugs-perform.md deleted file mode 100644 index 182b0899db..0000000000 --- a/.changeset/modern-ladybugs-perform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': minor ---- - -Scaffolding a repository in Bitbucket will now use the apiBaseUrl if it is provided instead of only the host parameter diff --git a/.changeset/nice-spoons-try.md b/.changeset/nice-spoons-try.md new file mode 100644 index 0000000000..c0992fa05e --- /dev/null +++ b/.changeset/nice-spoons-try.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Fix a react warning in ``. diff --git a/.changeset/nine-hornets-wave.md b/.changeset/nine-hornets-wave.md deleted file mode 100644 index 7eab7fadc5..0000000000 --- a/.changeset/nine-hornets-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Provide a link to the template source on the `TemplateCard`. diff --git a/.changeset/old-crabs-jump.md b/.changeset/old-crabs-jump.md deleted file mode 100644 index 9441f3aeb7..0000000000 --- a/.changeset/old-crabs-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Updated dependencies diff --git a/.changeset/olive-singers-sparkle.md b/.changeset/olive-singers-sparkle.md deleted file mode 100644 index 14e45867a0..0000000000 --- a/.changeset/olive-singers-sparkle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-plugin-api': patch ---- - -Apply fixes to the extension creation API that were mistakenly applied to `@backstage/core-app-api` instead. diff --git a/.changeset/perfect-toes-search.md b/.changeset/perfect-toes-search.md deleted file mode 100644 index 65aceb6f08..0000000000 --- a/.changeset/perfect-toes-search.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -'@backstage/create-app': patch -'@backstage/plugin-scaffolder-backend': patch ---- - -Migrating old `backstage.io/v1alpha1` templates to `backstage.io/v1beta2` - -Deprecating the `create-react-app` Template. We're planning on removing the `create-react-app` templater, as it's been a little tricky to support and takes 15mins to run in a container. We've currently cached a copy of the output for `create-react-app` and ship that under our sample templates folder. If you want to continue using it, we suggest copying the template out of there and putting it in your own repository as it will be removed in upcoming releases. - -We also recommend removing this entry from your `app-config.yaml` if it exists: - -```diff -- - type: url -- target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml -- rules: -- - allow: [Template] -``` diff --git a/.changeset/pink-bags-tickle.md b/.changeset/pink-bags-tickle.md deleted file mode 100644 index 9c600459e7..0000000000 --- a/.changeset/pink-bags-tickle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Deprecate and disable the extension creation methods, which were added to this package by mistake and should only exist within `@backstage/core-plugin-api`. diff --git a/.changeset/pink-llamas-sniff.md b/.changeset/pink-llamas-sniff.md new file mode 100644 index 0000000000..98addd691c --- /dev/null +++ b/.changeset/pink-llamas-sniff.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-app-backend': patch +'@backstage/plugin-badges-backend': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-code-coverage-backend': patch +'@backstage/plugin-proxy-backend': patch +'@backstage/plugin-rollbar-backend': patch +'@backstage/plugin-search-backend': patch +'@backstage/plugin-techdocs-backend': patch +--- + +Make `yarn dev` respect the `PLUGIN_PORT` environment variable. diff --git a/.changeset/pretty-dryers-turn.md b/.changeset/pretty-dryers-turn.md deleted file mode 100644 index 9b80d8f6b7..0000000000 --- a/.changeset/pretty-dryers-turn.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-catalog': patch -'@backstage/plugin-catalog-react': patch ---- - -Expose `getEntitySourceLocation`, `getEntityMetadataViewUrl`, and -`getEntityMetadataEditUrl` from `@backstage/plugin-catalog-react`. diff --git a/.changeset/purple-papayas-exist.md b/.changeset/purple-papayas-exist.md new file mode 100644 index 0000000000..4c77558476 --- /dev/null +++ b/.changeset/purple-papayas-exist.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings': patch +--- + +Fix a bug that prevented changing themes on the user settings page when the theme `id` didn't match exactly the theme `variant`. diff --git a/.changeset/real-bulldogs-greet.md b/.changeset/real-bulldogs-greet.md deleted file mode 100644 index 49d8a65d54..0000000000 --- a/.changeset/real-bulldogs-greet.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/catalog-client': patch -'@backstage/plugin-catalog-import': patch ---- - -Display preview result final step. diff --git a/.changeset/search-cross-the-goal.md b/.changeset/search-cross-the-goal.md deleted file mode 100644 index 580b28ac23..0000000000 --- a/.changeset/search-cross-the-goal.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/search-common': patch -'@backstage/plugin-search-backend-node': patch -'@backstage/plugin-search': patch ---- - -The ` set of components exported by the Search Plugin are now updated to use the Search Backend API. These will be made available as the default non-"next" versions in a follow-up release. - -The interfaces for decorators and collators in the Search Backend have also seen minor, breaking revisions ahead of a general release. If you happen to be building on top of these interfaces, check and update your implementations accordingly. The APIs will be considered more stable in a follow-up release. diff --git a/.changeset/sharp-candles-type.md b/.changeset/sharp-candles-type.md new file mode 100644 index 0000000000..259e2151c0 --- /dev/null +++ b/.changeset/sharp-candles-type.md @@ -0,0 +1,5 @@ +--- +'@backstage/config-loader': patch +--- + +Removed workaround for breaking change in typescript 4.3 and bump `typescript-json-schema` instead. This should again allow the usage of `@items.visibility ` to set the visibility of array items. diff --git a/.changeset/shiny-hotels-tell.md b/.changeset/shiny-hotels-tell.md deleted file mode 100644 index 7443a8d639..0000000000 --- a/.changeset/shiny-hotels-tell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-deployments': patch ---- - -Add deployment statuses to the GithubDeployments plugin diff --git a/.changeset/silent-lions-collect.md b/.changeset/silent-lions-collect.md deleted file mode 100644 index 76747871ef..0000000000 --- a/.changeset/silent-lions-collect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Update `createApp` options to allow plugins with unknown output types in order to improve forwards and backwards compatibility. diff --git a/.changeset/sour-brooms-dream.md b/.changeset/sour-brooms-dream.md deleted file mode 100644 index 4cb5a0e584..0000000000 --- a/.changeset/sour-brooms-dream.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fix error message formatting in the packaging process. - -error.errors can be undefined which will lead to a TypeError, swallowing the actual error message in the process. - -For instance, if you break your tsconfig.json with invalid syntax, backstage-cli will not be able to build anything and it will be very hard to find out why because the underlying error message is hidden behind a TypeError. diff --git a/.changeset/strange-chicken-explain.md b/.changeset/strange-chicken-explain.md deleted file mode 100644 index 0b2dffbccb..0000000000 --- a/.changeset/strange-chicken-explain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -A new card that shows components that depend on the active component diff --git a/.changeset/famous-rockets-share.md b/.changeset/tall-bears-taste.md similarity index 51% rename from .changeset/famous-rockets-share.md rename to .changeset/tall-bears-taste.md index 8b5a216fc9..050c47867c 100644 --- a/.changeset/famous-rockets-share.md +++ b/.changeset/tall-bears-taste.md @@ -2,4 +2,4 @@ '@backstage/core-components': patch --- -Use app.title for helmet in header +Add title prop in SupportButton component diff --git a/.changeset/tame-hotels-itch.md b/.changeset/tame-hotels-itch.md deleted file mode 100644 index 2ae7b005a6..0000000000 --- a/.changeset/tame-hotels-itch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/integration': patch ---- - -Download archives as compressed tar files for Bitbucket to keep executable permissions. diff --git a/.changeset/techdocs-metal-clouds-work.md b/.changeset/techdocs-metal-clouds-work.md new file mode 100644 index 0000000000..64d18dcc02 --- /dev/null +++ b/.changeset/techdocs-metal-clouds-work.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Adding support for user owned document filter for TechDocs custom Homepage diff --git a/.changeset/thick-donkeys-carry.md b/.changeset/thick-donkeys-carry.md new file mode 100644 index 0000000000..41cd319654 --- /dev/null +++ b/.changeset/thick-donkeys-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Migrate from the `command-exists-promise` dependency to `command-exists`. diff --git a/.changeset/thirty-turkeys-sing.md b/.changeset/thirty-turkeys-sing.md new file mode 100644 index 0000000000..07b3aaa8b7 --- /dev/null +++ b/.changeset/thirty-turkeys-sing.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-model': patch +--- + +Removed unused `typescript-json-schema` dependency. diff --git a/.changeset/tough-ravens-change.md b/.changeset/tough-ravens-change.md new file mode 100644 index 0000000000..f0567655a6 --- /dev/null +++ b/.changeset/tough-ravens-change.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Use the correct parameter to create a public repository in Bitbucket Server. diff --git a/.changeset/tricky-goats-boil.md b/.changeset/tricky-goats-boil.md deleted file mode 100644 index 36d5806d8e..0000000000 --- a/.changeset/tricky-goats-boil.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Update gitbeaker past the broken version without a dist folder diff --git a/.changeset/violet-birds-lay.md b/.changeset/violet-birds-lay.md new file mode 100644 index 0000000000..841603058f --- /dev/null +++ b/.changeset/violet-birds-lay.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-proxy-backend': patch +--- + +Bump http-proxy-middleware from 0.19.2 to 2.0.0 diff --git a/.changeset/warm-bikes-warn.md b/.changeset/warm-bikes-warn.md deleted file mode 100644 index a0f6fa73af..0000000000 --- a/.changeset/warm-bikes-warn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Exported AboutCard contents and utility functions diff --git a/.changeset/wild-wasps-turn.md b/.changeset/wild-wasps-turn.md deleted file mode 100644 index 2bdb0d832d..0000000000 --- a/.changeset/wild-wasps-turn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-proxy-backend': patch ---- - -Fixed proxy requests to the base URL of routes without a trailing slash redirecting to the `target` with the full path appended. diff --git a/.changeset/yellow-schools-matter.md b/.changeset/yellow-schools-matter.md new file mode 100644 index 0000000000..15a65a7bcb --- /dev/null +++ b/.changeset/yellow-schools-matter.md @@ -0,0 +1,6 @@ +--- +'@backstage/core': patch +'@backstage/core-components': patch +--- + +Use the Backstage `Link` component in the `Button` diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 206c1a7883..fda500ed02 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,7 +4,7 @@ # The last matching pattern takes precedence. # https://help.github.com/articles/about-codeowners/ -* @backstage/maintainers +* @backstage/reviewers /docs/features/techdocs @backstage/techdocs-core /docs/features/search @backstage/techdocs-core /docs/assets/search @backstage/techdocs-core diff --git a/.github/workflows/master-win.yml b/.github/workflows/master-win.yml index 3850146388..c61ee4798b 100644 --- a/.github/workflows/master-win.yml +++ b/.github/workflows/master-win.yml @@ -53,6 +53,10 @@ jobs: - name: verify type dependencies run: yarn lint:type-deps + # The core packages need to be built for the codemods tests to work + - name: build core packages + run: lerna run --scope @backstage/core-* build + - name: test run: yarn lerna -- run test env: diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 0ab8d8390d..936c27c7cf 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -36,9 +36,33 @@ To become a maintainer you need to demonstrate the following: If a maintainer is no longer interested or cannot perform the maintainer duties listed above, they should volunteer to be moved to emeritus status. In extreme cases this can also occur by a vote of the sponsors and maintainers per the voting process below. +# Reviewers + +The project also contains a team called [@backstage/reviewers](https://github.com/orgs/backstage/teams/reviewers). This is the team of people who are the fallback in [`CODEOWNERS`](./.github/CODEOWNERS). This team will typically contain the maintainers, and a small number of additional people who are permitted to approve and merge pull requests. The purpose of this group is to offload some of the review work from the maintainers, simplifying and speeding up the review process for contributors. + +This responsibility is distinct from the maintainer role. A reviewer must not approve and merge changes that have a level of impact that a maintainer should oversee; see below for clarification. For that class of changes, a reviewer can still review the pull request thoroughly without approving it (e.g. with a comment on the pull request), and is expected to notify `@backstage/maintainers` for final approval. Note that it is best to not use the GitHub review approve functionality for this, since that would let Hall of Fame members self-merge the pull request before maintainers get the chance to look at it. + +The following is a non-exhaustive list of types of change, for which a reviewer should defer final decision and merge to a maintainer: + +- A larger refactoring that significantly affects the structure of/between packages +- Changes that settle or alter the trajectory of contested ongoing topics in issues or elsewhere +- Changes that affect the [Architecture Decision Records](./docs/architecture-decisions) +- Changes to APIs that have large customer impact, such as the core APIs in `@backstage/core-*` packages, or significant `@backstage/cli` changes. +- Pull requests whose build checks are not passing fully +- Additions and removals of entire packages +- Releases (e.g. pull requests titled `Version Packages`) + +A maintainer may suggest an addition to the reviewers team by opening a pull request that modifies [`OWNERS.md`](./OWNERS.md) accordingly. Prospective reviewers are not expected to do this themselves, but should rather ask a maintainer to sponsor their addition. All of the maintainers and sponsors are called to vote on the addition (see the section below about voting). If the vote passes, the pull request can be approved and merged, and the corresponding addition to the GitHub team can be made. + +A reviewer can elect to remove themselves from the reviewers group by opening, or asking a maintainer to open, a pull request that modifies [`OWNERS.md`](./OWNERS.md) accordingly. A maintainer will approve and merge the pull request, and the corresponding removal from the GitHub team can be made. + +A maintainer can call on the other maintainers and sponsors for a vote to remove a reviewer (see the section below about conflict resolution and voting). If the vote passes, a maintainer creates a pull request that modifies [`OWNERS.md`](./OWNERS.md) accordingly. After approval by another maintainer, the pull request can be merged, and the corresponding removal from the GitHub team can be made. + # Conflict resolution and voting -In general, we prefer that technical issues and maintainer membership are amicably worked out between the persons involved. If a dispute cannot be decided independently, the sponsors and maintainers can be called in to decide an issue. If the sponsors and maintainers themselves cannot decide an issue, the issue will be resolved by voting. The voting process is a simple majority in which each sponsor receives two votes and each maintainer receives one vote. +In general, we prefer that technical issues and membership are amicably worked out between the persons involved. If a dispute cannot be decided independently, the sponsors and maintainers can be called in to decide an issue. If the sponsors and maintainers themselves cannot decide an issue, the issue will be resolved by voting. + +In all cases in this document where voting is mentioned, the voting process is a simple majority in which each sponsor receives two votes and each maintainer receives one vote. If such a majority is reached, the vote is said to have _passed_. # Adding new projects to the Backstage GitHub organization diff --git a/OWNERS.md b/OWNERS.md index cdbc234183..6615046540 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -16,6 +16,18 @@ This page lists all active sponsors and maintainers. - Ben Lambert ([benjdlambert](https://github.com/benjdlambert)) (Discord: @blam) - Johan Haals ([jhaals](https://github.com/jhaals)) (Discord: @jhaals) +# Reviewers + +See [`GOVERNANCE.md`](./GOVERNANCE.md) for details about how the reviewers team +works. + +- Patrik Oldsberg ([rugvip](https://github.com/rugvip)) (Discord: @Rugvip) +- Fredrik Adelöw ([freben](https://github.com/freben)) (Discord: @freben) +- Ben Lambert ([benjdlambert](https://github.com/benjdlambert)) (Discord: @blam) +- Johan Haals ([jhaals](https://github.com/jhaals)) (Discord: @jhaals) +- Himanshu Mishra ([OrkoHunter](https://github.com/OrkoHunter)) (Discord: @OrkoHunter) +- Tim Hansen ([timbonicus](https://github.com/timbonicus)) (Discord: @timbonicus) + # Emeritus maintainers - Stefan Ålund ([stefanalund](https://github.com/stefanalund)) (Discord: @stalund) diff --git a/docs/plugins/backend-plugin.md b/docs/plugins/backend-plugin.md index 4480cd69e3..7a57cefa9c 100644 --- a/docs/plugins/backend-plugin.md +++ b/docs/plugins/backend-plugin.md @@ -111,3 +111,42 @@ curl localhost:7000/api/carmen/health ``` This should return `{"status":"ok"}` like before. Success! + +## Making Use of a Database + +The Backstage backend comes with a builtin facility for SQL database access. +Most plugins that have persistence needs will choose to make use of this +facility, so that Backstage operators can manage database needs uniformly. + +As part of the environment object that is passed to your `createPlugin` +function, there is a `database` field. You can use that to get a +[Knex](http://knexjs.org/) connection object. + +```ts +// in packages/backend/src/plugins/carmen.ts +export default async function createPlugin(env: PluginEnvironment) { + const db: Knex = await env.database.getClient(); + + // You will then pass this client into your actual plugin implementation + // code, maybe similar to the following: + const model = new CarmenDatabaseModel(db); + return await createRouter({ + model: model, + logger: env.logger, + }); +} +``` + +You may note that the `getClient` call has no parameters. This is because all +plugin database needs are configured under the `backend.database` config key of +your `app-config.yaml`. The framework may even make sure behind the scenes that +the logical database is created automatically if it doesn't exist, based on +rules that the Backstage operator decides on. + +The framework does not handle database schema migrations for you, however. The +builtin plugins in the main repo have chosen to use the Knex library to manage +schema migrations as well, but you can do so in any manner that you see fit. + +See the [Knex library documentation](http://knexjs.org/) for examples and +details on how to write schema migrations and perform SQL queries against your +database.. diff --git a/microsite/data/plugins/gke-usage.yaml b/microsite/data/plugins/gke-usage.yaml new file mode 100644 index 0000000000..42d3e3a287 --- /dev/null +++ b/microsite/data/plugins/gke-usage.yaml @@ -0,0 +1,15 @@ +--- +title: GKE Usage +author: BESTSELLER +authorUrl: bestsellerit.com +category: Discovery +description: This plugin will show you the cost and resource usage of your application within GKE. +documentation: https://github.com/BESTSELLER/backstage-plugin-gkeusage/blob/master/README.md +iconUrl: https://bestsellerit.com/img/google-container-engine_avatar.svg +npmPackageName: '@bestsellerit/backstage-plugin-gkeusage' +tags: + - gke + - cost + - google + - usage + - metering diff --git a/microsite/package.json b/microsite/package.json index 3112bbfe17..1894e37d84 100644 --- a/microsite/package.json +++ b/microsite/package.json @@ -20,7 +20,7 @@ "docusaurus": "^2.0.0-alpha.70", "js-yaml": "^4.1.0", "prettier": "^2.3.1", - "yarn-lock-check": "^1.0.4" + "yarn-lock-check": "^1.0.5" }, "prettier": "@spotify/prettier-config" } diff --git a/microsite/siteConfig.js b/microsite/siteConfig.js index 5d61e55bc1..ea78fb462a 100644 --- a/microsite/siteConfig.js +++ b/microsite/siteConfig.js @@ -92,10 +92,8 @@ const siteConfig = { cleanUrl: true, // Open Graph and Twitter card images. - ogImage: - 'logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png', - twitterImage: - 'logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png', + ogImage: 'img/sharing-opengraph.png', + twitterImage: 'img/twitter-summary.png', // For sites with a sizable amount of content, set collapsible to true. // Expand/collapse the links and subcategories under categories. diff --git a/microsite/static/img/cortex.png b/microsite/static/img/cortex.png index 6a45d0ca06..d16b3f9c32 100644 Binary files a/microsite/static/img/cortex.png and b/microsite/static/img/cortex.png differ diff --git a/microsite/static/img/sharing-opengraph.png b/microsite/static/img/sharing-opengraph.png new file mode 100644 index 0000000000..7d304f81ed Binary files /dev/null and b/microsite/static/img/sharing-opengraph.png differ diff --git a/microsite/static/img/twitter-summary.png b/microsite/static/img/twitter-summary.png new file mode 100644 index 0000000000..7330b071ee Binary files /dev/null and b/microsite/static/img/twitter-summary.png differ diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 6f71394265..a89235bf98 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -9,13 +9,6 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/code-frame@^7.0.0": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" - integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== - dependencies: - "@babel/highlight" "^7.12.13" - "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": version "7.12.11" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -227,11 +220,6 @@ resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== -"@babel/helper-validator-identifier@^7.14.0": - version "7.14.0" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" - integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== - "@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": version "7.12.11" resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" @@ -265,15 +253,6 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.12.13": - version "7.14.0" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf" - integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg== - dependencies: - "@babel/helper-validator-identifier" "^7.14.0" - chalk "^2.0.0" - js-tokens "^4.0.0" - "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": version "7.12.11" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" @@ -942,29 +921,11 @@ dependencies: "@types/node" "*" -"@types/glob@^7.1.3": - version "7.1.3" - resolved "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" - integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - -"@types/minimatch@*": - version "3.0.4" - resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21" - integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA== - "@types/node@*": version "14.14.20" resolved "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz#f7974863edd21d1f8a494a73e8e2b3658615c340" integrity sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A== -"@types/node@^15.6.1": - version "15.9.0" - resolved "https://registry.npmjs.org/@types/node/-/node-15.9.0.tgz#0b7f6c33ca5618fe329a9d832b478b4964d325a8" - integrity sha512-AR1Vq1Ei1GaA5FjKL5PBqblTZsL5M+monvGSZwe6sSIdGiuu7Xr/pNwWJY+0ZQuN8AapD/XMB5IzBAyYRFbocA== - "@types/q@^1.5.1": version "1.5.4" resolved "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" @@ -1449,11 +1410,6 @@ buffer@^5.2.1: base64-js "^1.3.1" ieee754 "^1.1.13" -builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= - bytes@1: version "1.0.0" resolved "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8" @@ -1567,7 +1523,7 @@ caw@^2.0.0, caw@^2.0.1: tunnel-agent "^0.6.0" url-to-options "^1.0.1" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1758,7 +1714,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.12.1, commander@^2.8.1: +commander@^2.8.1: version "2.20.3" resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -2230,11 +2186,6 @@ diacritics-map@^0.1.0: resolved "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz#6dfc0ff9d01000a2edf2865371cac316e94977af" integrity sha1-bfwP+dAQAKLt8oZTccrDFulJd68= -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - dir-glob@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" @@ -3091,19 +3042,7 @@ glob-to-regexp@^0.3.0: resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6, glob@~7.1.1: - version "7.1.6" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.1, glob@^7.1.7: +glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6, glob@^7.1.7, glob@~7.1.1: version "7.1.7" resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== @@ -3638,13 +3577,6 @@ is-core-module@^2.1.0: dependencies: has "^1.0.3" -is-core-module@^2.2.0: - version "2.4.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1" - integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A== - dependencies: - has "^1.0.3" - is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -4457,7 +4389,7 @@ mixin-deep@^1.1.3, mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: +mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -5681,14 +5613,6 @@ resolve@^1.1.6, resolve@^1.10.0: is-core-module "^2.1.0" path-parse "^1.0.6" -resolve@^1.3.2: - version "1.20.0" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - responselike@1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -6437,37 +6361,11 @@ truncate-html@^1.0.3: "@types/cheerio" "^0.22.8" cheerio "0.22.0" -tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslint@^6.1.3: - version "6.1.3" - resolved "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" - integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== - dependencies: - "@babel/code-frame" "^7.0.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^4.0.1" - glob "^7.1.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - mkdirp "^0.5.3" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.13.0" - tsutils "^2.29.0" - -tsutils@^2.29.0: - version "2.29.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== - dependencies: - tslib "^1.8.1" - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -6493,11 +6391,6 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.3.2: - version "4.3.2" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805" - integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw== - unbzip2-stream@^1.0.9: version "1.4.3" resolved "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" @@ -6767,18 +6660,14 @@ yargs@^2.3.0: dependencies: wordwrap "0.0.2" -yarn-lock-check@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/yarn-lock-check/-/yarn-lock-check-1.0.4.tgz#a0373de051be0c8442d8933070df7a45595263b4" - integrity sha512-Gj0wRN85c4OPZUlE7WsQ0a1COv38uyeWWR0YAvJr2Vxw1f32bwK19xySjUZlxt9o4QopJkd8g6x6CLv81OHwYg== +yarn-lock-check@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/yarn-lock-check/-/yarn-lock-check-1.0.5.tgz#69d9516385f3ff010d0e2b0e87fbbd9bb1ffecaf" + integrity sha512-dxmV4LpIBrRAPbPg+klyGvqdVo3Y6PgJs6ERJYXf0HSEst7klDmvKKqQUtk+wrIRCoMDIVIzSUTZsuC4zr/tFQ== dependencies: - "@types/glob" "^7.1.3" - "@types/node" "^15.6.1" "@yarnpkg/lockfile" "^1.1.0" glob "^7.1.7" ini "^2.0.0" - tslint "^6.1.3" - typescript "^4.3.2" yauzl@^2.4.2: version "2.10.0" diff --git a/package.json b/package.json index 6a663c877e..c0887d7f05 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "prettier": "^2.2.1", "recursive-readdir": "^2.2.2", "shx": "^0.3.2", - "yarn-lock-check": "^1.0.4" + "yarn-lock-check": "^1.0.5" }, "prettier": "@spotify/prettier-config", "lint-staged": { diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 7f9e9e554d..c200104775 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,35 @@ # example-app +## 0.2.32 + +### Patch Changes + +- Updated dependencies [9cd3c533c] +- Updated dependencies [db1c8f93b] +- Updated dependencies [9d906c7a1] +- Updated dependencies [9bdd2cca8] +- Updated dependencies [27a9b503a] +- Updated dependencies [f4e3ac5ce] +- Updated dependencies [9b4010965] +- Updated dependencies [7f7443308] +- Updated dependencies [7028ee1ca] +- Updated dependencies [70bc30c5b] +- Updated dependencies [db1c8f93b] +- Updated dependencies [5aff84759] +- Updated dependencies [21e8ebef5] +- Updated dependencies [4fbb00707] +- Updated dependencies [d5ad47bbb] + - @backstage/cli@0.7.0 + - @backstage/plugin-catalog@0.6.2 + - @backstage/plugin-cost-insights@0.10.2 + - @backstage/plugin-github-actions@0.4.9 + - @backstage/catalog-model@0.8.2 + - @backstage/plugin-scaffolder@0.9.8 + - @backstage/integration-react@0.1.3 + - @backstage/plugin-catalog-react@0.2.2 + - @backstage/plugin-catalog-import@0.5.9 + - @backstage/plugin-search@0.4.0 + ## 0.2.31 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 03d87dc243..1b0b3aa22c 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,25 +1,25 @@ { "name": "example-app", - "version": "0.2.31", + "version": "0.2.32", "private": true, "bundled": true, "dependencies": { - "@backstage/catalog-model": "^0.8.1", - "@backstage/cli": "^0.6.14", + "@backstage/catalog-model": "^0.8.2", + "@backstage/cli": "^0.7.0", "@backstage/core": "^0.7.12", - "@backstage/integration-react": "^0.1.2", + "@backstage/integration-react": "^0.1.3", "@backstage/plugin-api-docs": "^0.4.15", "@backstage/plugin-badges": "^0.2.2", - "@backstage/plugin-catalog": "^0.6.1", - "@backstage/plugin-catalog-import": "^0.5.8", - "@backstage/plugin-catalog-react": "^0.2.1", + "@backstage/plugin-catalog": "^0.6.2", + "@backstage/plugin-catalog-import": "^0.5.9", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/plugin-circleci": "^0.2.15", "@backstage/plugin-cloudbuild": "^0.2.16", "@backstage/plugin-code-coverage": "^0.1.4", - "@backstage/plugin-cost-insights": "^0.10.1", + "@backstage/plugin-cost-insights": "^0.10.2", "@backstage/plugin-explore": "^0.3.6", "@backstage/plugin-gcp-projects": "^0.2.6", - "@backstage/plugin-github-actions": "^0.4.8", + "@backstage/plugin-github-actions": "^0.4.9", "@backstage/plugin-graphiql": "^0.2.11", "@backstage/plugin-jenkins": "^0.4.4", "@backstage/plugin-kafka": "^0.2.8", @@ -29,8 +29,8 @@ "@backstage/plugin-org": "^0.3.14", "@backstage/plugin-pagerduty": "0.3.5", "@backstage/plugin-rollbar": "^0.3.6", - "@backstage/plugin-scaffolder": "^0.9.7", - "@backstage/plugin-search": "^0.3.7", + "@backstage/plugin-scaffolder": "^0.9.8", + "@backstage/plugin-search": "^0.4.0", "@backstage/plugin-sentry": "^0.3.11", "@backstage/plugin-shortcuts": "^0.1.2", "@backstage/plugin-tech-radar": "^0.4.0", diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 728d8fabcd..6256697036 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/backend-common +## 0.8.2 + +### Patch Changes + +- 92963779b: Omits the `upgrade-insecure-requests` Content-Security-Policy directive by default, to prevent automatic HTTPS request upgrading for HTTP-deployed Backstage sites. + + If you previously disabled this using `false` in your `app-config.yaml`, this line is no longer necessary: + + ```diff + backend: + csp: + - upgrade-insecure-requests: false + ``` + + To keep the existing behavior of `upgrade-insecure-requests` Content-Security-Policy being _enabled_, add the key with an empty array as the value in your `app-config.yaml`: + + ```diff + backend: + + csp: + + upgrade-insecure-requests: [] + ``` + + Read more on [upgrade-insecure-requests here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/upgrade-insecure-requests). + +- eda9dbd5f: Download archives as compressed tar files for Bitbucket to keep executable permissions. +- Updated dependencies [eda9dbd5f] + - @backstage/integration@0.5.6 + ## 0.8.1 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 4de9c36c8c..fc57ee59a8 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.8.1", + "version": "0.8.2", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -33,7 +33,7 @@ "@backstage/config": "^0.1.5", "@backstage/config-loader": "^0.6.2", "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.5.3", + "@backstage/integration": "^0.5.6", "@google-cloud/storage": "^5.8.0", "@octokit/rest": "^18.5.3", "@types/cors": "^2.8.6", @@ -76,7 +76,7 @@ } }, "devDependencies": { - "@backstage/cli": "^0.6.12", + "@backstage/cli": "^0.7.0", "@backstage/test-utils": "^0.1.12", "@types/archiver": "^5.1.0", "@types/compression": "^1.7.0", diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md new file mode 100644 index 0000000000..c2078fd0bc --- /dev/null +++ b/packages/backend-test-utils/CHANGELOG.md @@ -0,0 +1,14 @@ +# @backstage/backend-test-utils + +## 0.1.2 + +### Patch Changes + +- 0711954a9: Skip running docker tests unless in CI +- Updated dependencies [9cd3c533c] +- Updated dependencies [92963779b] +- Updated dependencies [7f7443308] +- Updated dependencies [21e8ebef5] +- Updated dependencies [eda9dbd5f] + - @backstage/cli@0.7.0 + - @backstage/backend-common@0.8.2 diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 95276651ca..c4ff5603f3 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.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", - "@backstage/cli": "^0.6.10", + "@backstage/backend-common": "^0.8.2", + "@backstage/cli": "^0.7.0", "@backstage/config": "^0.1.5", "knex": "^0.95.1", "mysql2": "^2.2.5", @@ -41,7 +41,7 @@ "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.10", + "@backstage/cli": "^0.7.0", "jest": "^26.0.1" }, "files": [ diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 4a8fd1b86f..65d28457d0 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,31 @@ # example-backend +## 0.2.32 + +### Patch Changes + +- Updated dependencies [9c63be545] +- Updated dependencies [92963779b] +- Updated dependencies [27a9b503a] +- Updated dependencies [66c6bfebd] +- Updated dependencies [55a253de2] +- Updated dependencies [70bc30c5b] +- Updated dependencies [db1c8f93b] +- Updated dependencies [5aff84759] +- Updated dependencies [f26e6008f] +- Updated dependencies [eda9dbd5f] +- Updated dependencies [4f8cf50fe] +- Updated dependencies [875809a59] + - @backstage/plugin-catalog-backend@0.10.2 + - @backstage/backend-common@0.8.2 + - @backstage/catalog-model@0.8.2 + - @backstage/plugin-scaffolder-backend@0.12.0 + - @backstage/catalog-client@0.3.13 + - @backstage/plugin-search-backend-node@0.2.0 + - @backstage/plugin-search-backend@0.2.0 + - @backstage/plugin-proxy-backend@0.2.9 + - example-app@0.2.32 + ## 0.2.30 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index be843e4d38..f4f304d714 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.30", + "version": "0.2.32", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,30 +27,30 @@ "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", - "@backstage/catalog-client": "^0.3.12", - "@backstage/catalog-model": "^0.8.0", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-client": "^0.3.13", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/plugin-app-backend": "^0.3.13", "@backstage/plugin-auth-backend": "^0.3.12", "@backstage/plugin-badges-backend": "^0.1.6", - "@backstage/plugin-catalog-backend": "^0.10.0", + "@backstage/plugin-catalog-backend": "^0.10.2", "@backstage/plugin-code-coverage-backend": "^0.1.6", "@backstage/plugin-graphql-backend": "^0.1.8", "@backstage/plugin-kubernetes-backend": "^0.3.8", "@backstage/plugin-kafka-backend": "^0.2.6", - "@backstage/plugin-proxy-backend": "^0.2.8", + "@backstage/plugin-proxy-backend": "^0.2.9", "@backstage/plugin-rollbar-backend": "^0.1.11", - "@backstage/plugin-scaffolder-backend": "^0.11.4", - "@backstage/plugin-search-backend": "^0.1.5", - "@backstage/plugin-search-backend-node": "^0.1.3", + "@backstage/plugin-scaffolder-backend": "^0.12.0", + "@backstage/plugin-search-backend": "^0.2.0", + "@backstage/plugin-search-backend-node": "^0.2.0", "@backstage/plugin-techdocs-backend": "^0.8.2", "@backstage/plugin-todo-backend": "^0.1.6", "@gitbeaker/node": "^30.2.0", "@octokit/rest": "^18.5.3", "azure-devops-node-api": "^10.1.1", "dockerode": "^3.2.1", - "example-app": "^0.2.30", + "example-app": "^0.2.32", "express": "^4.17.1", "express-promise-router": "^4.1.0", "knex": "^0.95.1", @@ -60,7 +60,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.6.13", + "@backstage/cli": "^0.7.0", "@types/dockerode": "^3.2.1", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5" diff --git a/packages/backend/src/plugins/catalog.ts b/packages/backend/src/plugins/catalog.ts index 63a3e53c81..57afe4fefd 100644 --- a/packages/backend/src/plugins/catalog.ts +++ b/packages/backend/src/plugins/catalog.ts @@ -14,13 +14,9 @@ * limitations under the License. */ -import { useHotCleanup } from '@backstage/backend-common'; import { CatalogBuilder, createRouter, - NextCatalogBuilder, - runPeriodically, - createNextRouter, } from '@backstage/plugin-catalog-backend'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; @@ -28,50 +24,20 @@ import { PluginEnvironment } from '../types'; export default async function createPlugin( env: PluginEnvironment, ): Promise { - /* - * ** WARNING ** - * DO NOT enable the experimental catalog, it will brick your database migrations. - * This is solely for internal backstage development. - */ - if (process.env.EXPERIMENTAL_CATALOG === '1') { - const builder = new NextCatalogBuilder(env); - const { - entitiesCatalog, - locationAnalyzer, - processingEngine, - locationService, - } = await builder.build(); - - // TODO(jhaals): run and manage in background. - await processingEngine.start(); - - return await createNextRouter({ - entitiesCatalog, - locationAnalyzer, - locationService, - logger: env.logger, - config: env.config, - }); - } - - const builder = new CatalogBuilder(env); + const builder = await CatalogBuilder.create(env); const { entitiesCatalog, - locationsCatalog, - higherOrderOperation, locationAnalyzer, + processingEngine, + locationService, } = await builder.build(); - useHotCleanup( - module, - runPeriodically(() => higherOrderOperation.refreshAllLocations(), 100000), - ); + await processingEngine.start(); return await createRouter({ entitiesCatalog, - locationsCatalog, - higherOrderOperation, locationAnalyzer, + locationService, logger: env.logger, config: env.config, }); diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index e1ef7b759b..847924b67b 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-client +## 0.3.13 + +### Patch Changes + +- 70bc30c5b: Display preview result final step. +- Updated dependencies [27a9b503a] + - @backstage/catalog-model@0.8.2 + ## 0.3.12 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 0cf8d7d1b8..c366374bf5 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-client", - "version": "0.3.12", + "version": "0.3.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,13 +29,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/errors": "^0.1.1", "cross-fetch": "^3.0.6" }, "devDependencies": { - "@backstage/cli": "^0.6.13", + "@backstage/cli": "^0.7.0", "@types/jest": "^26.0.7", "msw": "^0.21.2" }, diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 94b4662a97..df350ff288 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/catalog-model +## 0.8.2 + +### Patch Changes + +- 27a9b503a: Introduce conditional steps in scaffolder templates. + + A step can now include an `if` property that only executes a step if the + condition is truthy. The condition can include handlebar templates. + + ```yaml + - id: register + if: '{{ not parameters.dryRun }}' + name: Register + action: catalog:register + input: + repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}' + catalogInfoPath: '/catalog-info.yaml' + ``` + + Also introduces a `not` helper in handlebar templates that allows to negate + boolean expressions. + ## 0.8.1 ### Patch Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index edcffaa691..f9d7483dda 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-model", - "version": "0.8.1", + "version": "0.8.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,13 +35,12 @@ "@types/yup": "^0.29.8", "ajv": "^7.0.3", "json-schema": "^0.3.0", - "typescript-json-schema": "^0.49.0", "lodash": "^4.17.15", "uuid": "^8.0.0", "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@types/express": "^4.17.6", "@types/jest": "^26.0.7", "@types/lodash": "^4.14.151", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index da06bfea17..8eae37ef56 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,58 @@ # @backstage/cli +## 0.7.0 + +### Minor Changes + +- 9cd3c533c: Switch from `ts-jest` to `@sucrase/jest-plugin`, improving performance and aligning transpilation with bundling. + + In order to switch back to `ts-jest`, install `ts-jest@^26.4.3` as a dependency in the root of your repo and add the following in the root `package.json`: + + ```json + "jest": { + "globals": { + "ts-jest": { + "isolatedModules": true + } + }, + "transform": { + "\\.esm\\.js$": "@backstage/cli/config/jestEsmTransform.js", + "\\.(js|jsx|ts|tsx)$": "ts-jest", + "\\.(bmp|gif|jpg|jpeg|png|frag|xml|svg)$": "@backstage/cli/config/jestFileTransform.js", + "\\.(yaml)$": "yaml-jest" + } + } + ``` + + Note that this will override the default jest transforms included with the `@backstage/cli`. + + It is possible that some test code needs a small migration as a result of this change, which stems from a difference in how `sucrase` and `ts-jest` transform module re-exports. + + Consider the following code: + + ```ts + import * as utils from './utils'; + + jest.spyOn(utils, 'myUtility').mockReturnValue(3); + ``` + + If the `./utils` import for example refers to an index file that in turn re-exports from `./utils/myUtility`, you would have to change the code to the following to work around the fact that the exported object from `./utils` ends up not having configurable properties, thus breaking `jest.spyOn`. + + ```ts + import * as utils from './utils/myUtility'; + + jest.spyOn(utils, 'myUtility').mockReturnValue(3); + ``` + +### Patch Changes + +- 7f7443308: Updated dependencies +- 21e8ebef5: Fix error message formatting in the packaging process. + + error.errors can be undefined which will lead to a TypeError, swallowing the actual error message in the process. + + For instance, if you break your tsconfig.json with invalid syntax, backstage-cli will not be able to build anything and it will be very hard to find out why because the underlying error message is hidden behind a TypeError. + ## 0.6.14 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index a8df1014fb..f633e410ea 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.6.14", + "version": "0.7.0", "private": false, "publishConfig": { "access": "public" @@ -94,8 +94,8 @@ "react-hot-loader": "^4.12.21", "recursive-readdir": "^2.2.2", "replace-in-file": "^6.0.0", - "rollup": "2.33.x", - "rollup-plugin-dts": "^2.0.1", + "rollup": "2.44.x", + "rollup-plugin-dts": "^3.0.1", "rollup-plugin-esbuild": "2.6.x", "rollup-plugin-peer-deps-external": "^2.2.2", "rollup-plugin-postcss": "^4.0.0", @@ -118,7 +118,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.8.1", + "@backstage/backend-common": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/core": "^0.7.12", "@backstage/dev-utils": "^0.1.17", @@ -139,7 +139,7 @@ "@types/rollup-plugin-postcss": "^2.0.0", "@types/tar": "^4.0.3", "@types/webpack": "^4.41.7", - "@types/webpack-dev-server": "3.11.0", + "@types/webpack-dev-server": "^3.11.0", "@types/yarnpkg__lockfile": "^1.1.4", "del": "^5.1.0", "mock-fs": "^4.13.0", diff --git a/packages/cli/templates/default-backend-plugin/src/service/standaloneServer.ts.hbs b/packages/cli/templates/default-backend-plugin/src/service/standaloneServer.ts.hbs index 6e38965246..765b6aa0d0 100644 --- a/packages/cli/templates/default-backend-plugin/src/service/standaloneServer.ts.hbs +++ b/packages/cli/templates/default-backend-plugin/src/service/standaloneServer.ts.hbs @@ -34,9 +34,12 @@ export async function startStandaloneServer( logger, }); - const service = createServiceBuilder(module) - .enableCors({ origin: 'http://localhost:3000' }) + let service = createServiceBuilder(module) + .setPort(options.port) .addRouter('/{{id}}', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } return await service.start().catch(err => { logger.error(err); diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md new file mode 100644 index 0000000000..9f2ae5d214 --- /dev/null +++ b/packages/codemods/CHANGELOG.md @@ -0,0 +1,15 @@ +# @backstage/codemods + +## 0.1.1 + +### Patch Changes + +- Updated dependencies [9bca2a252] +- Updated dependencies [e47336ea4] +- Updated dependencies [75b8537ce] +- Updated dependencies [da8cba44f] +- Updated dependencies [da8cba44f] +- Updated dependencies [9bca2a252] + - @backstage/core-app-api@0.1.2 + - @backstage/core-components@0.1.2 + - @backstage/core-plugin-api@0.1.2 diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 16f2e522a7..2ce0172b75 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.0", + "version": "0.1.1", "private": true, "homepage": "https://backstage.io", "repository": { diff --git a/packages/codemods/src/action.ts b/packages/codemods/src/action.ts index 46e50ead77..c3eba8aecc 100644 --- a/packages/codemods/src/action.ts +++ b/packages/codemods/src/action.ts @@ -18,6 +18,7 @@ import { relative as relativePath } from 'path'; import { spawn } from 'child_process'; import { Command } from 'commander'; import { findPaths } from '@backstage/cli-common'; +import { platform } from 'os'; import { ExitCodeError } from './errors'; // eslint-disable-next-line no-restricted-syntax @@ -50,8 +51,18 @@ export function createCodemodAction(name: string) { console.log(`Running jscodeshift with these arguments: ${args.join(' ')}`); - const jscodeshiftScript = require.resolve('.bin/jscodeshift'); - const child = spawn(process.argv0, [jscodeshiftScript, ...args], { + let command; + if (platform() === 'win32') { + command = 'jscodeshift'; + } else { + // jscodeshift ships a slightly broken bin script with windows + // line endings so we need to execute it using node rather than + // letting the `#!/usr/bin/env node` take care of it + command = process.argv0; + args.unshift(require.resolve('.bin/jscodeshift')); + } + + const child = spawn(command, args, { stdio: 'inherit', shell: true, env: { diff --git a/packages/codemods/src/tests/core-imports.test.ts b/packages/codemods/src/tests/core-imports.test.ts index 90bc217d3e..e5924156b6 100644 --- a/packages/codemods/src/tests/core-imports.test.ts +++ b/packages/codemods/src/tests/core-imports.test.ts @@ -25,7 +25,8 @@ function runTransform(source: string) { stats: () => undefined, report: () => undefined, }; - return coreImportTransform({ source, file: 'test.ts' }, api); + const result = coreImportTransform({ source, file: 'test.ts' }, api); + return result?.split('\r\n').join('\n'); } describe('core-imports', () => { diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index de0adb4a4a..a9a309428a 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -37,7 +37,7 @@ "fs-extra": "^9.0.0", "json-schema": "^0.3.0", "json-schema-merge-allof": "^0.8.1", - "typescript-json-schema": "^0.49.0", + "typescript-json-schema": "^0.50.1", "yaml": "^1.9.2", "yup": "^0.29.3" }, diff --git a/packages/config-loader/src/lib/schema/collect.test.ts b/packages/config-loader/src/lib/schema/collect.test.ts index 94fe2154c1..488c8b5fc6 100644 --- a/packages/config-loader/src/lib/schema/collect.test.ts +++ b/packages/config-loader/src/lib/schema/collect.test.ts @@ -28,6 +28,15 @@ const mockSchema = { }, }; +// We need to load in actual TS libraries when using mock-fs. +// This lookup is to allow the `typescript` dependency to exist either +// at top level or inside node_modules of typescript-json-schema +const typescriptModuleDir = path.dirname( + require.resolve('typescript/package.json', { + paths: [require.resolve('typescript-json-schema')], + }), +); + describe('collectConfigSchemas', () => { afterEach(() => { mockFs.restore(); @@ -157,9 +166,7 @@ describe('collectConfigSchemas', () => { }, }, // TypeScript compilation needs to load some real files inside the typescript dir - '../../node_modules/typescript': (mockFs as any).load( - '../../node_modules/typescript', - ), + [typescriptModuleDir]: (mockFs as any).load(typescriptModuleDir), }); await expect(collectConfigSchemas(['a', 'b', 'c'])).resolves.toEqual([ @@ -218,9 +225,7 @@ describe('collectConfigSchemas', () => { }, }, // TypeScript compilation needs to load some real files inside the typescript dir - '../../node_modules/typescript': (mockFs as any).load( - '../../node_modules/typescript', - ), + [typescriptModuleDir]: (mockFs as any).load(typescriptModuleDir), }); await expect(collectConfigSchemas(['a'])).rejects.toThrow( diff --git a/packages/config-loader/src/lib/schema/collect.ts b/packages/config-loader/src/lib/schema/collect.ts index 5baada2d6f..e12a4c9309 100644 --- a/packages/config-loader/src/lib/schema/collect.ts +++ b/packages/config-loader/src/lib/schema/collect.ts @@ -168,23 +168,6 @@ function compileTsSchemas(paths: string[]) { }, [path.split(sep).join('/')], // Unix paths are expected for all OSes here ) as JsonObject | null; - - // This is a workaround for an API change in TypeScript 4.3 where doc comments no - // longer are represented by a single string, but instead an array of objects. - // This isn't handled by typescript-json-schema so we do the conversion here instead. - value = JSON.parse(JSON.stringify(value), (key, prop) => { - if (key === 'visibility' && Array.isArray(prop)) { - const text = prop[0]?.text; - if (!text) { - const propStr = JSON.stringify(prop); - throw new Error( - `Failed conversion of visibility schema, got ${propStr}`, - ); - } - return text; - } - return prop; - }); } catch (error) { if (error.message !== 'type Config not found') { throw error; diff --git a/packages/core-api/CHANGELOG.md b/packages/core-api/CHANGELOG.md index c06e2b6789..2282976d74 100644 --- a/packages/core-api/CHANGELOG.md +++ b/packages/core-api/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/core-api +## 0.2.22 + +### Patch Changes + +- 9bca2a252: Improve forwards compatibility with `@backstage/core-app-api` and `@backstage/core-plugin-api` by re-using route reference types and factory methods from `@backstage/core-plugin-api`. +- Updated dependencies [75b8537ce] +- Updated dependencies [da8cba44f] + - @backstage/core-plugin-api@0.1.2 + ## 0.2.21 ### Patch Changes diff --git a/packages/core-api/package.json b/packages/core-api/package.json index 1c3e707a29..1eaeeb24b1 100644 --- a/packages/core-api/package.json +++ b/packages/core-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-api", "description": "Internal Core API used by Backstage plugins and apps", - "version": "0.2.21", + "version": "0.2.22", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.4", - "@backstage/core-plugin-api": "^0.1.1", + "@backstage/core-plugin-api": "^0.1.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -43,7 +43,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/test-utils": "^0.1.13", "@backstage/test-utils-core": "^0.1.1", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index f98cf7eeb1..4d7b7541d0 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/core-app-api +## 0.1.2 + +### Patch Changes + +- 9bca2a252: Fixes a type bug where supplying all app icons to `createApp` was required, rather than just a partial list. +- 75b8537ce: This change adds automatic error boundaries around extensions. + + This means that all exposed parts of a plugin are wrapped in a general error boundary component, that is plugin aware. The default design for the error box is borrowed from `@backstage/errors`. To override the default "fallback", one must provide a component named `ErrorBoundaryFallback` to `createApp`, like so: + + ```ts + const app = createApp({ + components: { + ErrorBoundaryFallback: props => { + // a custom fallback component + return ( + <> +

Oops.

+

+ The plugin {props.plugin.getId()} failed with{' '} + {props.error.message} +

+ + + ); + }, + }, + }); + ``` + + The props here include: + + - `error`. An `Error` object or something that inherits it that represents the error that was thrown from any inner component. + - `resetError`. A callback that will simply attempt to mount the children of the error boundary again. + - `plugin`. A `BackstagePlugin` that can be used to look up info to be presented in the error message. For instance, you may want to keep a map of your internal plugins and team names or slack channels and present these when an error occurs. Typically, you'll do that by getting the plugin ID with `plugin.getId()`. + +- da8cba44f: Deprecate and disable the extension creation methods, which were added to this package by mistake and should only exist within `@backstage/core-plugin-api`. +- 9bca2a252: Update `createApp` options to allow plugins with unknown output types in order to improve forwards and backwards compatibility. +- Updated dependencies [e47336ea4] +- Updated dependencies [75b8537ce] +- Updated dependencies [da8cba44f] + - @backstage/core-components@0.1.2 + - @backstage/core-plugin-api@0.1.2 + ## 0.1.1 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index ddb598ce9b..9298a53ea4 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": "0.1.1", + "version": "0.1.2", "private": false, "publishConfig": { "access": "public", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.1.1", + "@backstage/core-components": "^0.1.2", "@backstage/config": "^0.1.3", - "@backstage/core-plugin-api": "^0.1.1", + "@backstage/core-plugin-api": "^0.1.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -44,7 +44,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/test-utils": "^0.1.13", "@backstage/test-utils-core": "^0.1.1", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 93941494c8..83e5bad9f5 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/core-components +## 0.1.2 + +### Patch Changes + +- e47336ea4: Use app.title for helmet in header +- 75b8537ce: This change adds automatic error boundaries around extensions. + + This means that all exposed parts of a plugin are wrapped in a general error boundary component, that is plugin aware. The default design for the error box is borrowed from `@backstage/errors`. To override the default "fallback", one must provide a component named `ErrorBoundaryFallback` to `createApp`, like so: + + ```ts + const app = createApp({ + components: { + ErrorBoundaryFallback: props => { + // a custom fallback component + return ( + <> +

Oops.

+

+ The plugin {props.plugin.getId()} failed with{' '} + {props.error.message} +

+ + + ); + }, + }, + }); + ``` + + The props here include: + + - `error`. An `Error` object or something that inherits it that represents the error that was thrown from any inner component. + - `resetError`. A callback that will simply attempt to mount the children of the error boundary again. + - `plugin`. A `BackstagePlugin` that can be used to look up info to be presented in the error message. For instance, you may want to keep a map of your internal plugins and team names or slack channels and present these when an error occurs. Typically, you'll do that by getting the plugin ID with `plugin.getId()`. + +- Updated dependencies [75b8537ce] +- Updated dependencies [da8cba44f] + - @backstage/core-plugin-api@0.1.2 + ## 0.1.1 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 1ce4adf2b7..42a98b859a 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.1.1", + "version": "0.1.2", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.5", - "@backstage/core-plugin-api": "^0.1.1", + "@backstage/core-plugin-api": "^0.1.2", "@backstage/errors": "^0.1.1", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", @@ -70,8 +70,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/core-app-api": "^0.1.1", - "@backstage/cli": "^0.6.14", + "@backstage/core-app-api": "^0.1.2", + "@backstage/cli": "^0.7.0", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", diff --git a/packages/core-components/src/components/Button/Button.tsx b/packages/core-components/src/components/Button/Button.tsx index ca45b3da7f..c678b9a9db 100644 --- a/packages/core-components/src/components/Button/Button.tsx +++ b/packages/core-components/src/components/Button/Button.tsx @@ -14,17 +14,19 @@ * limitations under the License. */ -import React, { ComponentProps } from 'react'; -import { Button as MaterialButton } from '@material-ui/core'; -import { Link as RouterLink } from 'react-router-dom'; +import { + Button as MaterialButton, + ButtonProps as MaterialButtonProps, +} from '@material-ui/core'; +import React from 'react'; +import { Link, LinkProps } from '../Link'; -type Props = ComponentProps & - ComponentProps; +type Props = MaterialButtonProps & Omit; /** * Thin wrapper on top of material-ui's Button component * Makes the Button to utilise react-router */ export const Button = React.forwardRef((props, ref) => ( - + )); diff --git a/packages/core-components/src/components/SupportButton/SupportButton.test.tsx b/packages/core-components/src/components/SupportButton/SupportButton.test.tsx index 6d6b9fd477..7c6cab99c1 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.test.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.test.tsx @@ -21,8 +21,9 @@ import { RenderResult, waitFor, fireEvent, + screen, } from '@testing-library/react'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { wrapInTestApp, renderInTestApp } from '@backstage/test-utils'; import { SupportButton } from './SupportButton'; const SUPPORT_BUTTON_ID = 'support-button'; @@ -41,6 +42,12 @@ describe('', () => { ); }); + it('supports passing a title', async () => { + await renderInTestApp(); + fireEvent.click(screen.getByTestId(SUPPORT_BUTTON_ID)); + expect(screen.getByText('Custom title')).toBeInTheDocument(); + }); + it('shows popover on click', async () => { let renderResult: RenderResult; diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index 6c6de8abe3..96cc308f74 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -24,19 +24,18 @@ import { ListItem, ListItemIcon, ListItemText, + Typography, makeStyles, Popover, } from '@material-ui/core'; -import React, { - Fragment, - MouseEventHandler, - PropsWithChildren, - useState, -} from 'react'; +import React, { Fragment, MouseEventHandler, useState } from 'react'; import { SupportItem, SupportItemLink, useSupportConfig } from '../../hooks'; import { Link } from '../Link'; -type Props = {}; +type SupportButtonProps = { + title?: string; + children?: React.ReactNode; +}; const useStyles = makeStyles({ popoverList: { @@ -78,7 +77,7 @@ const SupportListItem = ({ item }: { item: SupportItem }) => { ); }; -export const SupportButton = ({ children }: PropsWithChildren) => { +export const SupportButton = ({ title, children }: SupportButtonProps) => { const { items } = useSupportConfig(); const [popoverOpen, setPopoverOpen] = useState(false); @@ -121,13 +120,20 @@ export const SupportButton = ({ children }: PropsWithChildren) => { onClose={popoverCloseHandler} > + {title && ( + + {title} + + )} {React.Children.map(children, (child, i) => ( - + {child} ))} {items && - items.map((item, i) => )} + items.map((item, i) => ( + + ))} + + ); + }, + }, + }); + ``` + + The props here include: + + - `error`. An `Error` object or something that inherits it that represents the error that was thrown from any inner component. + - `resetError`. A callback that will simply attempt to mount the children of the error boundary again. + - `plugin`. A `BackstagePlugin` that can be used to look up info to be presented in the error message. For instance, you may want to keep a map of your internal plugins and team names or slack channels and present these when an error occurs. Typically, you'll do that by getting the plugin ID with `plugin.getId()`. + +- da8cba44f: Apply fixes to the extension creation API that were mistakenly applied to `@backstage/core-app-api` instead. + ## 0.1.1 ### Patch Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 64c2154ce9..816727ed9e 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "0.1.1", + "version": "0.1.2", "private": false, "publishConfig": { "access": "public", @@ -41,7 +41,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/test-utils": "^0.1.13", "@backstage/test-utils-core": "^0.1.1", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/core/package.json b/packages/core/package.json index ee7e56741d..4ecb3839aa 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.5", - "@backstage/core-api": "^0.2.21", + "@backstage/core-api": "^0.2.22", "@backstage/errors": "^0.1.1", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", @@ -71,7 +71,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", diff --git a/packages/core/src/components/Button/Button.tsx b/packages/core/src/components/Button/Button.tsx index ca45b3da7f..c678b9a9db 100644 --- a/packages/core/src/components/Button/Button.tsx +++ b/packages/core/src/components/Button/Button.tsx @@ -14,17 +14,19 @@ * limitations under the License. */ -import React, { ComponentProps } from 'react'; -import { Button as MaterialButton } from '@material-ui/core'; -import { Link as RouterLink } from 'react-router-dom'; +import { + Button as MaterialButton, + ButtonProps as MaterialButtonProps, +} from '@material-ui/core'; +import React from 'react'; +import { Link, LinkProps } from '../Link'; -type Props = ComponentProps & - ComponentProps; +type Props = MaterialButtonProps & Omit; /** * Thin wrapper on top of material-ui's Button component * Makes the Button to utilise react-router */ export const Button = React.forwardRef((props, ref) => ( - + )); diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 5d8e1c3d71..13f2bcb5ab 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,288 @@ # @backstage/create-app +## 0.3.25 + +### Patch Changes + +- 4f8cf50fe: Updated the `@gitbeaker/node` dependency past the broken one without a `dist` folder. + + See [this issue](https://github.com/jdalrymple/gitbeaker/issues/1861) for more details. + + If you get build errors that look like the following in your Backstage instance, you may want to also bump all of your `@gitbeaker/*` dependencies to at least `^30.2.0`. + + ``` + node:internal/modules/cjs/loader:356 + throw err; + ^ + + Error: Cannot find module '/path/to/project/node_modules/@gitbeaker/node/dist/index.js'. Please verify that the package.json has a valid "main" entry + at tryPackage (node:internal/modules/cjs/loader:348:19) + at Function.Module._findPath (node:internal/modules/cjs/loader:561:18) + at Function.Module._resolveFilename (node:internal/modules/cjs/loader:926:27) + at Function.Module._load (node:internal/modules/cjs/loader:773:27) + at Module.require (node:internal/modules/cjs/loader:1012:19) + at require (node:internal/modules/cjs/helpers:93:18) + at Object. (/path/to/project/test.js:4:18) + at Module._compile (node:internal/modules/cjs/loader:1108:14) + at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10) + at Module.load (node:internal/modules/cjs/loader:988:32) { + code: 'MODULE_NOT_FOUND', + path: '/path/to/project/node_modules/@gitbeaker/node/package.json', + requestPath: '@gitbeaker/node' + } + ``` + + you could also consider pinning the version to an older one in your `package.json` either root or `packages/backend/package.json`, before the breakage occurred. + + ```json + "resolutions": { + "**/@gitbeaker/node": "29.2.4", + "**/@gitbeaker/core": "29.2.4", + "**/@gitbeaker/requester-utils": "29.2.4" + } + ``` + + Be aware that this is only required short term until we can release our updated versions of `@backstage/plugin-scaffolder-backend`. + +- 55a253de2: Migrating old `backstage.io/v1alpha1` templates to `backstage.io/v1beta2` + + Deprecating the `create-react-app` Template. We're planning on removing the `create-react-app` templater, as it's been a little tricky to support and takes 15mins to run in a container. We've currently cached a copy of the output for `create-react-app` and ship that under our sample templates folder. If you want to continue using it, we suggest copying the template out of there and putting it in your own repository as it will be removed in upcoming releases. + + We also recommend removing this entry from your `app-config.yaml` if it exists: + + ```diff + - - type: url + - target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml + - rules: + - - allow: [Template] + ``` + +- 509b5638c: Added "out-of-the-box" alpha-milestone search features to scaffolded Backstage apps. + + To apply this change to an existing app, do the following... + + First, navigate to your backend package and install the two new search backend + packages: + + ```sh + cd packages/backend + yarn add @backstage/plugin-search-backend @backstage/plugin-search-backend-node + ``` + + Wire up these new packages into your app backend by first creating a new + `search.ts` file at `src/plugins/search.ts` with contents like the following: + + ```typescript + import { useHotCleanup } from '@backstage/backend-common'; + import { createRouter } from '@backstage/plugin-search-backend'; + import { + IndexBuilder, + LunrSearchEngine, + } from '@backstage/plugin-search-backend-node'; + import { PluginEnvironment } from '../types'; + import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend'; + + export default async function createPlugin({ + logger, + discovery, + }: PluginEnvironment) { + // Initialize a connection to a search engine. + const searchEngine = new LunrSearchEngine({ logger }); + const indexBuilder = new IndexBuilder({ logger, searchEngine }); + + // Collators are responsible for gathering documents known to plugins. This + // particular collator gathers entities from the software catalog. + indexBuilder.addCollator({ + defaultRefreshIntervalSeconds: 600, + collator: new DefaultCatalogCollator({ discovery }), + }); + + // The scheduler controls when documents are gathered from collators and sent + // to the search engine for indexing. + const { scheduler } = await indexBuilder.build(); + + // A 3 second delay gives the backend server a chance to initialize before + // any collators are executed, which may attempt requests against the API. + setTimeout(() => scheduler.start(), 3000); + useHotCleanup(module, () => scheduler.stop()); + + return await createRouter({ + engine: indexBuilder.getSearchEngine(), + logger, + }); + } + ``` + + Then, ensure the search plugin you configured above is initialized by modifying + your backend's `index.ts` file in the following ways: + + ```diff + +import search from './plugins/search'; + // ... + +const searchEnv = useHotMemoize(module, () => createEnv('search')); + // ... + +apiRouter.use('/search', await search(searchEnv)); + // ... + ``` + + In your frontend app package, create a new `searchPage` component at, for + example, `packages/app/src/components/search/SearchPage.tsx` with contents like + the following: + + ```tsx + import React from 'react'; + import { makeStyles, Theme, Grid, List, Paper } from '@material-ui/core'; + + import { Content, Header, Lifecycle, Page } from '@backstage/core'; + import { CatalogResultListItem } from '@backstage/plugin-catalog'; + import { + SearchBar, + SearchFilter, + SearchResult, + DefaultResultListItem, + } from '@backstage/plugin-search'; + + const useStyles = makeStyles((theme: Theme) => ({ + bar: { + padding: theme.spacing(1, 0), + }, + filters: { + padding: theme.spacing(2), + }, + filter: { + '& + &': { + marginTop: theme.spacing(2.5), + }, + }, + })); + + const SearchPage = () => { + const classes = useStyles(); + + return ( + +
} /> + + + + + + + + + + + + + + + + {({ results }) => ( + + {results.map(({ type, document }) => { + switch (type) { + case 'software-catalog': + return ( + + ); + default: + return ( + + ); + } + })} + + )} + + + + + + ); + }; + + export const searchPage = ; + ``` + + Then in `App.tsx`, import this new `searchPage` component, and set it as a + child of the existing `` route so that it looks like this: + + ```diff + +import { searchPage } from './components/search/SearchPage'; + // ... + -} /> + +}> + + {searchPage} + +; + ``` + +- Updated dependencies [9cd3c533c] +- Updated dependencies [db1c8f93b] +- Updated dependencies [9c63be545] +- Updated dependencies [9bdd2cca8] +- Updated dependencies [92963779b] +- Updated dependencies [27a9b503a] +- Updated dependencies [f4e3ac5ce] +- Updated dependencies [66c6bfebd] +- Updated dependencies [9b4010965] +- Updated dependencies [7f7443308] +- Updated dependencies [55a253de2] +- Updated dependencies [7028ee1ca] +- Updated dependencies [70bc30c5b] +- Updated dependencies [db1c8f93b] +- Updated dependencies [5aff84759] +- Updated dependencies [5aff84759] +- Updated dependencies [f26e6008f] +- Updated dependencies [21e8ebef5] +- Updated dependencies [4fbb00707] +- Updated dependencies [eda9dbd5f] +- Updated dependencies [4f8cf50fe] +- Updated dependencies [d5ad47bbb] +- Updated dependencies [875809a59] + - @backstage/cli@0.7.0 + - @backstage/plugin-catalog@0.6.2 + - @backstage/plugin-catalog-backend@0.10.2 + - @backstage/plugin-github-actions@0.4.9 + - @backstage/backend-common@0.8.2 + - @backstage/catalog-model@0.8.2 + - @backstage/plugin-scaffolder@0.9.8 + - @backstage/plugin-scaffolder-backend@0.12.0 + - @backstage/integration-react@0.1.3 + - @backstage/catalog-client@0.3.13 + - @backstage/plugin-catalog-import@0.5.9 + - @backstage/plugin-search-backend-node@0.2.0 + - @backstage/plugin-search@0.4.0 + - @backstage/plugin-search-backend@0.2.0 + - @backstage/plugin-proxy-backend@0.2.9 + - @backstage/core@0.7.12 + - @backstage/errors@0.1.1 + - @backstage/test-utils@0.1.13 + - @backstage/theme@0.2.8 + - @backstage/plugin-api-docs@0.4.15 + - @backstage/plugin-app-backend@0.3.13 + - @backstage/plugin-auth-backend@0.3.12 + - @backstage/plugin-explore@0.3.6 + - @backstage/plugin-lighthouse@0.2.17 + - @backstage/plugin-rollbar-backend@0.1.11 + - @backstage/plugin-tech-radar@0.4.0 + - @backstage/plugin-techdocs@0.9.5 + - @backstage/plugin-techdocs-backend@0.8.2 + - @backstage/plugin-user-settings@0.2.10 + ## 0.3.24 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index a0fb9e6d4a..d5adcba510 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "Create app package for Backstage", - "version": "0.3.24", + "version": "0.3.25", "private": false, "publishConfig": { "access": "public" @@ -64,6 +64,8 @@ "@backstage/plugin-rollbar-backend": "*", "@backstage/plugin-scaffolder": "*", "@backstage/plugin-search": "*", + "@backstage/plugin-search-backend": "*", + "@backstage/plugin-search-backend-node": "*", "@backstage/plugin-scaffolder-backend": "*", "@backstage/plugin-tech-radar": "*", "@backstage/plugin-techdocs": "*", diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index 2a133b4bf8..a0f646747b 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -58,6 +58,8 @@ import { version as pluginRollbarBackend } from '../../../../plugins/rollbar-bac import { version as pluginScaffolder } from '../../../../plugins/scaffolder/package.json'; import { version as pluginScaffolderBackend } from '../../../../plugins/scaffolder-backend/package.json'; import { version as pluginSearch } from '../../../../plugins/search/package.json'; +import { version as pluginSearchBackend } from '../../../../plugins/search-backend/package.json'; +import { version as pluginSearchBackendNode } from '../../../../plugins/search-backend-node/package.json'; import { version as pluginTechRadar } from '../../../../plugins/tech-radar/package.json'; import { version as pluginTechdocs } from '../../../../plugins/techdocs/package.json'; import { version as pluginTechdocsBackend } from '../../../../plugins/techdocs-backend/package.json'; @@ -89,6 +91,8 @@ export const packageVersions = { '@backstage/plugin-scaffolder': pluginScaffolder, '@backstage/plugin-scaffolder-backend': pluginScaffolderBackend, '@backstage/plugin-search': pluginSearch, + '@backstage/plugin-search-backend': pluginSearchBackend, + '@backstage/plugin-search-backend-node': pluginSearchBackendNode, '@backstage/plugin-tech-radar': pluginTechRadar, '@backstage/plugin-techdocs': pluginTechdocs, '@backstage/plugin-techdocs-backend': pluginTechdocsBackend, diff --git a/packages/create-app/templates/default-app/.gitignore.hbs b/packages/create-app/templates/default-app/.gitignore.hbs index 4adebc5adc..d16a8d3fba 100644 --- a/packages/create-app/templates/default-app/.gitignore.hbs +++ b/packages/create-app/templates/default-app/.gitignore.hbs @@ -1,3 +1,6 @@ +# macOS +.DS_Store + # Logs logs *.log diff --git a/.changeset/search-whole-new-world.md b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx similarity index 64% rename from .changeset/search-whole-new-world.md rename to packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx index 3dee24a371..f525be80a2 100644 --- a/.changeset/search-whole-new-world.md +++ b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx @@ -1,24 +1,7 @@ ---- -'@backstage/plugin-search': minor ---- - -This release represents a move out of a pre-alpha phase of the Backstage Search -plugin, into an alpha phase. With this release, you gain more control over the -layout of your search page on the frontend, as well as the ability to extend -search on the backend to encompass everything Backstage users may want to find. - -If you are updating to this version of `@backstage/plugin-search` from a prior -release, you will need to make the following modifications to your App: - -In your app package, create a new `searchPage` component at, for example, -`packages/app/src/components/search/SearchPage.tsx` with contents like the -following: - -```tsx import React from 'react'; import { makeStyles, Theme, Grid, List, Paper } from '@material-ui/core'; -import { Content, Header, Lifecycle, Page } from '@backstage/core'; +import { Content, Header, Page } from '@backstage/core'; import { CatalogResultListItem } from '@backstage/plugin-catalog'; import { SearchBar, @@ -46,7 +29,7 @@ const SearchPage = () => { return ( -
} /> +
@@ -101,18 +84,3 @@ const SearchPage = () => { }; export const searchPage = ; -``` - -Then in `App.tsx`, import this new `searchPage` component, and set it as a -child of the existing `` route so that it looks like this: - -```tsx -import { searchPage } from './components/search/SearchPage'; -// ... -}> - {searchPage} -; -``` - -You will also need to update your backend. For details, check the changeset for -`v0.2.0` of `@backstage/plugin-search-backend`. diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs index 4b493a32c3..8f5a116de4 100644 --- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs @@ -27,6 +27,8 @@ "@backstage/plugin-catalog-backend": "^{{version '@backstage/plugin-catalog-backend'}}", "@backstage/plugin-proxy-backend": "^{{version '@backstage/plugin-proxy-backend'}}", "@backstage/plugin-scaffolder-backend": "^{{version '@backstage/plugin-scaffolder-backend'}}", + "@backstage/plugin-search-backend": "^{{version '@backstage/plugin-search-backend'}}", + "@backstage/plugin-search-backend-node": "^{{version '@backstage/plugin-search-backend-node'}}", "@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}", "@gitbeaker/node": "^30.2.0", "@octokit/rest": "^18.5.3", diff --git a/packages/create-app/templates/default-app/packages/backend/src/index.ts b/packages/create-app/templates/default-app/packages/backend/src/index.ts index 70f4fb676e..f2b14b23f9 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/index.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/index.ts @@ -25,6 +25,7 @@ import catalog from './plugins/catalog'; import scaffolder from './plugins/scaffolder'; import proxy from './plugins/proxy'; import techdocs from './plugins/techdocs'; +import search from './plugins/search'; import { PluginEnvironment } from './types'; function makeCreateEnv(config: Config) { @@ -57,6 +58,7 @@ async function main() { const authEnv = useHotMemoize(module, () => createEnv('auth')); const proxyEnv = useHotMemoize(module, () => createEnv('proxy')); const techdocsEnv = useHotMemoize(module, () => createEnv('techdocs')); + const searchEnv = useHotMemoize(module, () => createEnv('search')); const appEnv = useHotMemoize(module, () => createEnv('app')); const apiRouter = Router(); @@ -65,6 +67,7 @@ async function main() { apiRouter.use('/auth', await auth(authEnv)); apiRouter.use('/techdocs', await techdocs(techdocsEnv)); apiRouter.use('/proxy', await proxy(proxyEnv)); + apiRouter.use('/search', await search(searchEnv)); apiRouter.use(notFoundHandler()); const service = createServiceBuilder(module) diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts index 838228cdb4..a132f0a8ae 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts @@ -1,30 +1,26 @@ -import { useHotCleanup } from '@backstage/backend-common'; import { CatalogBuilder, - createRouter, - runPeriodically + createRouter } from '@backstage/plugin-catalog-backend'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; export default async function createPlugin(env: PluginEnvironment): Promise { - const builder = new CatalogBuilder(env); + const builder = await CatalogBuilder.create(env); const { entitiesCatalog, locationsCatalog, - higherOrderOperation, + locationService, + processingEngine, locationAnalyzer, } = await builder.build(); - useHotCleanup( - module, - runPeriodically(() => higherOrderOperation.refreshAllLocations(), 100000), - ); + await processingEngine.start(); return await createRouter({ entitiesCatalog, locationsCatalog, - higherOrderOperation, + locationService, locationAnalyzer, logger: env.logger, config: env.config, diff --git a/.changeset/search-new-fantastic-pov.md b/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts similarity index 52% rename from .changeset/search-new-fantastic-pov.md rename to packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts index 0baba045b7..248ed37ea8 100644 --- a/.changeset/search-new-fantastic-pov.md +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts @@ -1,28 +1,3 @@ ---- -'@backstage/plugin-search-backend': minor -'@backstage/plugin-search-backend-node': minor ---- - -This release represents a move out of a pre-alpha phase of the Backstage Search -plugin, into an alpha phase. With this release, you gain more control over the -layout of your search page on the frontend, as well as the ability to extend -search on the backend to encompass everything Backstage users may want to find. - -If you are updating to version `v0.4.0` of `@backstage/plugin-search` from a -prior release, you will need to make modifications to your app backend. - -First, navigate to your backend package and install the two related search -backend packages: - -```sh -cd packages/backend -yarn add @backstage/plugin-search-backend @backstage/plugin-search-backend-node -``` - -Wire up these new packages into your app backend by first creating a new -`search.ts` file at `src/plugins/search.ts` with contents like the following: - -```typescript import { useHotCleanup } from '@backstage/backend-common'; import { createRouter } from '@backstage/plugin-search-backend'; import { @@ -61,16 +36,3 @@ export default async function createPlugin({ logger, }); } -``` - -Then, ensure the search plugin you configured above is initialized by modifying -your backend's `index.ts` file in the following ways: - -```diff -+import search from './plugins/search'; -// ... -+const searchEnv = useHotMemoize(module, () => createEnv('search')); -// ... -+apiRouter.use('/search', await search(searchEnv)); -// ... -``` diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 91c34c8ef2..100d06b1a0 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -30,9 +30,9 @@ }, "dependencies": { "@backstage/core": "^0.7.12", - "@backstage/catalog-model": "^0.8.1", - "@backstage/integration-react": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.2.1", + "@backstage/catalog-model": "^0.8.2", + "@backstage/integration-react": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/test-utils": "^0.1.13", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", @@ -48,7 +48,7 @@ "react-router-dom": "6.0.0-beta.0" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/errors/package.json b/packages/errors/package.json index 508cf4fab0..8fa76d8bfc 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -34,7 +34,7 @@ "serialize-error": "^8.0.1" }, "devDependencies": { - "@backstage/cli": "^0.6.1", + "@backstage/cli": "^0.7.0", "@types/jest": "^26.0.7" }, "files": [ diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 54aa3b3ab1..711d6d8203 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/integration-react +## 0.1.3 + +### Patch Changes + +- f4e3ac5ce: Move `ScmIntegrationIcon` from `@backstage/plugin-catalog` to + `@backstage/integration-react` and make it customizable using + `app.getSystemIcon()`. +- Updated dependencies [eda9dbd5f] + - @backstage/integration@0.5.6 + ## 0.1.2 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index fe831ca24f..313e5b8783 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration-react", - "version": "0.1.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,7 +22,7 @@ "dependencies": { "@backstage/config": "^0.1.2", "@backstage/core": "^0.7.9", - "@backstage/integration": "^0.5.0", + "@backstage/integration": "^0.5.6", "@backstage/theme": "^0.2.3", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -32,7 +32,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.11", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.14", "@backstage/test-utils": "^0.1.11", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 14b1d75441..3044922a00 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/integration +## 0.5.6 + +### Patch Changes + +- eda9dbd5f: Download archives as compressed tar files for Bitbucket to keep executable permissions. + ## 0.5.5 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index 1220493eea..bd557d7ec8 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration", - "version": "0.5.5", + "version": "0.5.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -37,7 +37,7 @@ "luxon": "^1.25.0" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/config-loader": "^0.6.3", "@backstage/test-utils": "^0.1.13", "@types/jest": "^26.0.7", diff --git a/packages/search-common/CHANGELOG.md b/packages/search-common/CHANGELOG.md new file mode 100644 index 0000000000..f4c0e4e6f1 --- /dev/null +++ b/packages/search-common/CHANGELOG.md @@ -0,0 +1,9 @@ +# @backstage/search-common + +## 0.1.2 + +### Patch Changes + +- db1c8f93b: The ` set of components exported by the Search Plugin are now updated to use the Search Backend API. These will be made available as the default non-"next" versions in a follow-up release. + + The interfaces for decorators and collators in the Search Backend have also seen minor, breaking revisions ahead of a general release. If you happen to be building on top of these interfaces, check and update your implementations accordingly. The APIs will be considered more stable in a follow-up release. diff --git a/packages/search-common/package.json b/packages/search-common/package.json index 18e3557a49..5415adbf0d 100644 --- a/packages/search-common/package.json +++ b/packages/search-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/search-common", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -39,7 +39,7 @@ "@backstage/config": "^0.1.3" }, "devDependencies": { - "@backstage/cli": "^0.6.2" + "@backstage/cli": "^0.7.0" }, "jest": { "roots": [ diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index d1ec21060b..ad9d2c6ac2 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -38,11 +38,11 @@ "dependencies": { "@azure/identity": "^1.2.2", "@azure/storage-blob": "^12.4.0", - "@backstage/backend-common": "^0.8.1", - "@backstage/catalog-model": "^0.8.1", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.5.5", + "@backstage/integration": "^0.5.6", "@google-cloud/storage": "^5.6.0", "@types/express": "^4.17.6", "aws-sdk": "^2.840.0", @@ -60,7 +60,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@types/fs-extra": "^9.0.5", "@types/git-url-parse": "^9.0.0", "@types/js-yaml": "^4.0.0", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 8f906965b4..cb6e13d7df 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-api": "^0.2.21", + "@backstage/core-api": "^0.2.22", "@backstage/test-utils-core": "^0.1.1", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", @@ -45,7 +45,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/theme/package.json b/packages/theme/package.json index 2575af6c97..d433be4648 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -31,7 +31,7 @@ "@material-ui/core": "^4.11.0" }, "devDependencies": { - "@backstage/cli": "^0.6.14" + "@backstage/cli": "^0.7.0" }, "files": [ "dist" diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 54588303e1..fd3bc353e9 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -30,9 +30,9 @@ }, "dependencies": { "@asyncapi/react-component": "^0.23.0", - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-icons/font": "^1.0.2", "@material-ui/core": "^4.11.0", @@ -49,7 +49,7 @@ "swagger-ui-react": "^3.37.2" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 60fa678dd0..4d101e7ca5 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", + "@backstage/backend-common": "^0.8.2", "@backstage/config-loader": "^0.6.1", "@backstage/config": "^0.1.5", "@types/express": "^4.17.6", @@ -40,7 +40,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.11", + "@backstage/cli": "^0.7.0", "@types/supertest": "^2.0.8", "msw": "^0.20.5", "supertest": "^6.1.3" diff --git a/plugins/app-backend/src/service/standaloneServer.ts b/plugins/app-backend/src/service/standaloneServer.ts index 005d80027b..58267f227d 100644 --- a/plugins/app-backend/src/service/standaloneServer.ts +++ b/plugins/app-backend/src/service/standaloneServer.ts @@ -38,7 +38,9 @@ export async function startStandaloneServer( appPackageName: 'example-app', }); - const service = createServiceBuilder(module).addRouter('', router); + const service = createServiceBuilder(module) + .setPort(options.port) + .addRouter('', router); return await service.start().catch(err => { logger.error(err); diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index dac1c0268a..ab5e252fed 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.1", - "@backstage/catalog-client": "^0.3.12", - "@backstage/catalog-model": "^0.8.0", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-client": "^0.3.13", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/errors": "^0.1.1", "@backstage/test-utils": "^0.1.12", @@ -68,7 +68,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.13", + "@backstage/cli": "^0.7.0", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 8a38cbaa3b..28adf1399b 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.1", - "@backstage/catalog-client": "^0.3.12", - "@backstage/catalog-model": "^0.8.0", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-client": "^0.3.13", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/errors": "^0.1.1", "@types/express": "^4.17.6", @@ -45,7 +45,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.13", + "@backstage/cli": "^0.7.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/badges-backend/src/service/standaloneServer.ts b/plugins/badges-backend/src/service/standaloneServer.ts index c210efa249..65a78d08e8 100644 --- a/plugins/badges-backend/src/service/standaloneServer.ts +++ b/plugins/badges-backend/src/service/standaloneServer.ts @@ -40,9 +40,12 @@ export async function startStandaloneServer( const router = await createRouter({ config, discovery }); - const service = createServiceBuilder(module) - .enableCors({ origin: 'http://localhost:3000' }) + let service = createServiceBuilder(module) + .setPort(options.port) .addRouter('/badges', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } return await service.start().catch(err => { logger.error(err); diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 23c914c9ab..99f78f3bd5 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -20,10 +20,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", "@backstage/errors": "^0.1.1", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -34,7 +34,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 8f3fa016c6..ab43d75061 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -37,7 +37,7 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index fe0a72a902..c8ff84831a 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-backend +## 0.10.2 + +### Patch Changes + +- 9c63be545: Restructure the next catalog types and files a bit +- Updated dependencies [92963779b] +- Updated dependencies [27a9b503a] +- Updated dependencies [70bc30c5b] +- Updated dependencies [db1c8f93b] +- Updated dependencies [5aff84759] +- Updated dependencies [eda9dbd5f] + - @backstage/backend-common@0.8.2 + - @backstage/catalog-model@0.8.2 + - @backstage/catalog-client@0.3.13 + - @backstage/search-common@0.1.2 + - @backstage/plugin-search-backend-node@0.2.0 + - @backstage/integration@0.5.6 + ## 0.10.1 ### Patch Changes diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrations/20210302150147_refresh_state.js similarity index 100% rename from plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js rename to plugins/catalog-backend/migrations/20210302150147_refresh_state.js diff --git a/plugins/catalog-backend/migrationsv2/20200511113813_init.js b/plugins/catalog-backend/migrationsv2/20200511113813_init.js deleted file mode 100644 index 7f3d75e35c..0000000000 --- a/plugins/catalog-backend/migrationsv2/20200511113813_init.js +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - return ( - knex.schema - // - // locations - // - .createTable('locations', table => { - table.comment( - 'Registered locations that shall be contiuously scanned for catalog item updates', - ); - table - .uuid('id') - .primary() - .notNullable() - .comment('Auto-generated ID of the location'); - table.string('type').notNullable().comment('The type of location'); - table - .string('target') - .notNullable() - .comment('The actual target of the location'); - }) - // - // entities - // - .createTable('entities', table => { - table.comment('All entities currently stored in the catalog'); - table.uuid('id').primary().comment('Auto-generated ID of the entity'); - table - .uuid('location_id') - .references('id') - .inTable('locations') - .nullable() - .comment('The location that originated the entity'); - table - .string('etag') - .notNullable() - .comment( - 'An opaque string that changes for each update operation to any part of the entity, including metadata.', - ); - table - .string('generation') - .notNullable() - .unsigned() - .comment( - 'A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes.', - ); - table - .string('api_version') - .notNullable() - .comment('The apiVersion field of the entity'); - table - .string('kind') - .notNullable() - .comment('The kind field of the entity'); - table - .string('name') - .nullable() - .comment('The metadata.name field of the entity'); - table - .string('namespace') - .nullable() - .comment('The metadata.namespace field of the entity'); - table - .string('metadata') - .notNullable() - .comment('The entire metadata JSON blob of the entity'); - table - .string('spec') - .nullable() - .comment('The entire spec JSON blob of the entity'); - }) - .alterTable('entities', table => { - // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta - table.unique(['kind', 'name', 'namespace'], 'entities_unique_name'); - }) - // - // entities_search - // - .createTable('entities_search', table => { - table.comment( - 'Flattened key-values from the entities, used for quick filtering', - ); - table - .uuid('entity_id') - .references('id') - .inTable('entities') - .onDelete('CASCADE') - .comment('The entity that matches this key/value'); - table - .string('key') - .notNullable() - .comment('A key that occurs in the entity'); - table - .string('value') - .nullable() - .comment('The corresponding value to match on'); - }) - ); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - return knex.schema - .dropTable('entities_search') - .alterTable('entities', table => { - table.dropUnique([], 'entities_unique_name'); - }) - .dropTable('entities') - .dropTable('locations'); -}; diff --git a/plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js b/plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js deleted file mode 100644 index d8093fc9b4..0000000000 --- a/plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - return knex.schema.createTable('location_update_log', table => { - table.uuid('id').primary(); - table.enum('status', ['success', 'fail']).notNullable(); - table.dateTime('created_at').defaultTo(knex.fn.now()).notNullable(); - table.string('message'); - table - .uuid('location_id') - .references('id') - .inTable('locations') - .onUpdate('CASCADE') - .onDelete('CASCADE'); - table.string('entity_name').nullable(); - }); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - return knex.schema.dropTableIfExists('location_update_log'); -}; diff --git a/plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js b/plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js deleted file mode 100644 index a0f0f33a65..0000000000 --- a/plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - // Get list sorted by created_at timestamp in descending order - // Grouped by location_id - return knex.schema.raw(` - CREATE VIEW location_update_log_latest AS - SELECT t1.* FROM location_update_log t1 - JOIN - ( - SELECT location_id, MAX(created_at) AS MAXDATE - FROM location_update_log - GROUP BY location_id - ) t2 - ON t1.location_id = t2.location_id - AND t1.created_at = t2.MAXDATE - ORDER BY created_at DESC; - `); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - return knex.schema.raw(`DROP VIEW location_update_log_latest;`); -}; diff --git a/plugins/catalog-backend/migrationsv2/20200702153613_entities.js b/plugins/catalog-backend/migrationsv2/20200702153613_entities.js deleted file mode 100644 index 0f1c204f9b..0000000000 --- a/plugins/catalog-backend/migrationsv2/20200702153613_entities.js +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - // SQLite does not support FK and PK - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities_search', table => { - table.dropForeign(['entity_id']); - }); - await knex.schema.alterTable('entities', table => { - table.dropPrimary('entities_pkey'); - }); - } - await knex.schema.alterTable('entities', table => { - table.dropUnique([], 'entities_unique_name'); - }); - // Setup temporary tables - await knex.schema.renameTable('entities_search', 'tmp_entities_search'); - await knex.schema.renameTable('entities', 'tmp_entities'); - - // - // entities - // - await knex.schema - .createTable('entities', table => { - table.comment('All entities currently stored in the catalog'); - table.uuid('id').primary().comment('Auto-generated ID of the entity'); - table - .uuid('location_id') - .references('id') - .inTable('locations') - .nullable() - .comment('The location that originated the entity'); - table - .string('etag') - .notNullable() - .comment( - 'An opaque string that changes for each update operation to any part of the entity, including metadata.', - ); - table - .string('generation') - .notNullable() - .unsigned() - .comment( - 'A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes.', - ); - table - .string('api_version') - .notNullable() - .comment('The apiVersion field of the entity'); - table - .string('kind') - .notNullable() - .comment('The kind field of the entity'); - table - .string('name') - .nullable() - .comment('The metadata.name field of the entity'); - table - .string('namespace') - .nullable() - .comment('The metadata.namespace field of the entity'); - table - .text('metadata') - .notNullable() - .comment('The entire metadata JSON blob of the entity'); - table - .text('spec') - .nullable() - .comment('The entire spec JSON blob of the entity'); - }) - .alterTable('entities', table => { - // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta - table.unique(['kind', 'name', 'namespace'], 'entities_unique_name'); - }); - - await knex.schema.raw(`INSERT INTO entities SELECT * FROM tmp_entities`); - - // - // entities_search - // - await knex.schema.createTable('entities_search', table => { - table.comment( - 'Flattened key-values from the entities, used for quick filtering', - ); - table - .uuid('entity_id') - .references('id') - .inTable('entities') - .onDelete('CASCADE') - .comment('The entity that matches this key/value'); - table - .string('key') - .notNullable() - .comment('A key that occurs in the entity'); - table - .string('value') - .nullable() - .comment('The corresponding value to match on'); - }); - await knex.schema.raw( - `INSERT INTO entities_search SELECT * FROM tmp_entities_search`, - ); - - // Clean up - await knex.schema.dropTable('tmp_entities'); - return knex.schema.dropTable('tmp_entities_search'); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - // SQLite does not support FK and PK - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities_search', table => { - table.dropForeign(['entity_id']); - }); - await knex.schema.alterTable('entities', table => { - table.dropPrimary('entities_pkey'); - }); - } - await knex.schema.alterTable('entities', table => { - table.dropUnique([], 'entities_unique_name'); - }); - - // Setup temporary tables - await knex.schema.renameTable('entities_search', 'tmp_entities_search'); - await knex.schema.renameTable('entities', 'tmp_entities'); - - // - // entities - // - await knex.schema - .createTable('entities', table => { - table.comment('All entities currently stored in the catalog'); - table.uuid('id').primary().comment('Auto-generated ID of the entity'); - table - .uuid('location_id') - .references('id') - .inTable('locations') - .nullable() - .comment('The location that originated the entity'); - table - .string('etag') - .notNullable() - .comment( - 'An opaque string that changes for each update operation to any part of the entity, including metadata.', - ); - table - .string('generation') - .notNullable() - .unsigned() - .comment( - 'A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes.', - ); - table - .string('api_version') - .notNullable() - .comment('The apiVersion field of the entity'); - table - .string('kind') - .notNullable() - .comment('The kind field of the entity'); - table - .string('name') - .nullable() - .comment('The metadata.name field of the entity'); - table - .string('namespace') - .nullable() - .comment('The metadata.namespace field of the entity'); - table - .string('metadata') - .notNullable() - .comment('The entire metadata JSON blob of the entity'); - table - .string('spec') - .nullable() - .comment('The entire spec JSON blob of the entity'); - }) - .alterTable('entities', table => { - // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta - table.unique(['kind', 'name', 'namespace'], 'entities_unique_name'); - }); - - await knex.schema.raw(`INSERT INTO entities SELECT * FROM tmp_entities`); - - // - // entities_search - // - await knex.schema.createTable('entities_search', table => { - table.comment( - 'Flattened key-values from the entities, used for quick filtering', - ); - table - .uuid('entity_id') - .references('id') - .inTable('entities') - .onDelete('CASCADE') - .comment('The entity that matches this key/value'); - table - .string('key') - .notNullable() - .comment('A key that occurs in the entity'); - table - .string('value') - .nullable() - .comment('The corresponding value to match on'); - }); - await knex.schema.raw( - `INSERT INTO entities_search SELECT * FROM tmp_entities_search`, - ); - - // Clean up - await knex.schema.dropTable('tmp_entities'); - return knex.schema.dropTable('tmp_entities_search'); -}; diff --git a/plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js b/plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js deleted file mode 100644 index 87b41a80fc..0000000000 --- a/plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 = function up(knex) { - return knex.schema.raw(`DROP VIEW location_update_log_latest;`).raw(` - CREATE VIEW location_update_log_latest AS - SELECT t1.* FROM location_update_log t1 - JOIN - ( - SELECT location_id, MAX(created_at) AS MAXDATE - FROM location_update_log - GROUP BY location_id - ) t2 - ON t1.location_id = t2.location_id - AND t1.created_at = t2.MAXDATE - GROUP BY t1.location_id, t1.id - ORDER BY created_at DESC; -`); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = function down(knex) { - knex.schema.raw(`DROP VIEW location_update_log_latest;`); -}; diff --git a/plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js b/plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js deleted file mode 100644 index de2b194cff..0000000000 --- a/plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 = function up(knex) { - return knex.schema - .raw('DROP VIEW location_update_log_latest;') - .dropTable('location_update_log') - .createTable('location_update_log', table => { - table.bigIncrements('id').primary(); // instead of uuid, so we can MAX it - table.enum('status', ['success', 'fail']).notNullable(); - table.dateTime('created_at').defaultTo(knex.fn.now()).notNullable(); - table.string('message'); - table - .uuid('location_id') - .references('id') - .inTable('locations') - .onUpdate('CASCADE') - .onDelete('CASCADE'); - table.string('entity_name').nullable(); - }).raw(` - CREATE VIEW location_update_log_latest AS - SELECT t1.* FROM location_update_log t1 - JOIN - ( - SELECT location_id, MAX(id) AS MAXID - FROM location_update_log - GROUP BY location_id - ) t2 - ON t1.location_id = t2.location_id - AND t1.id = t2.MAXID - GROUP BY t1.location_id, t1.id - ORDER BY created_at DESC; - `); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = function down(knex) { - return knex.schema - .raw('DROP VIEW location_update_log_latest;') - .dropTable('location_update_log') - .createTable('location_update_log', table => { - table.uuid('id').primary(); - table.enum('status', ['success', 'fail']).notNullable(); - table.dateTime('created_at').defaultTo(knex.fn.now()).notNullable(); - table.string('message'); - table - .uuid('location_id') - .references('id') - .inTable('locations') - .onUpdate('CASCADE') - .onDelete('CASCADE'); - table.string('entity_name').nullable(); - }).raw(` - CREATE VIEW location_update_log_latest AS - SELECT t1.* FROM location_update_log t1 - JOIN - ( - SELECT location_id, MAX(created_at) AS MAXDATE - FROM location_update_log - GROUP BY location_id - ) t2 - ON t1.location_id = t2.location_id - AND t1.created_at = t2.MAXDATE - GROUP BY t1.location_id, t1.id - ORDER BY created_at DESC; - `); -}; diff --git a/plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js b/plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js deleted file mode 100644 index 45226e53b4..0000000000 --- a/plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - // Sqlite does not support alter column. - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities_search', table => { - table.text('value').nullable().alter(); - }); - } -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - // Sqlite does not support alter column. - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities_search', table => { - table.string('value').nullable().alter(); - }); - } -}; diff --git a/plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js b/plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js deleted file mode 100644 index a90813fe85..0000000000 --- a/plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - // Adds a single 'bootstrap' location that can be used to trigger work in processors. - // This is primarily here to fulfill foreign key constraints. - await knex('locations').insert({ - id: require('uuid').v4(), - type: 'bootstrap', - target: 'bootstrap', - }); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - await knex('locations') - .where({ - type: 'bootstrap', - target: 'bootstrap', - }) - .del(); -}; diff --git a/plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js b/plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js deleted file mode 100644 index ea5ba9e58d..0000000000 --- a/plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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('entities') - .where({ namespace: null }) - .update({ namespace: 'default' }); - await knex('entities_search').update({ - key: knex.raw('LOWER(key)'), - value: knex.raw('LOWER(value)'), - }); -}; - -exports.down = async function down() {}; diff --git a/plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js b/plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js deleted file mode 100644 index aae1861658..0000000000 --- a/plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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('entities', table => { - table.text('full_name').nullable(); - }); - - await knex('entities').update({ - full_name: knex.raw( - "LOWER(kind) || ':' || LOWER(COALESCE(namespace, 'default')) || '/' || LOWER(name)", - ), - }); - - // SQLite does not support alter column - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities', table => { - table.text('full_name').notNullable().alter(); - }); - } - - await knex.schema.alterTable('entities', table => { - // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta - table.unique(['full_name'], 'entities_unique_full_name'); - table.dropUnique([], 'entities_unique_name'); - }); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - await knex.schema.alterTable('entities', table => { - // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta - table.dropUnique([], 'entities_unique_full_name'); - table.unique(['kind', 'namespace', 'name'], 'entities_unique_name'); - }); - - await knex.schema.alterTable('entities_search', table => { - table.dropColumn('full_name'); - }); -}; diff --git a/plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js b/plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js deleted file mode 100644 index a8964efbf6..0000000000 --- a/plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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('entities', table => { - table - .text('data') - .nullable() - .comment('The entire JSON data blob of the entity'); - }); - - await knex('entities').update({ - // apiVersion and kind should not contain any JSON unsafe chars, and both - // metadata and spec are already valid serialized JSON - data: knex.raw( - `'{"apiVersion":"' || api_version || '","kind":"' || kind || '","metadata":' || metadata || COALESCE(',"spec":' || spec, '') || '}'`, - ), - }); - - await knex.schema.alterTable('entities', table => { - table.dropColumn('metadata'); - table.dropColumn('spec'); - }); - - // SQLite does not support ALTER COLUMN. - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities', table => { - table.text('data').notNullable().alter(); - }); - } -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - await knex.schema.alterTable('entities', table => { - table - .text('metadata') - .notNullable() - .comment('The entire metadata JSON blob of the entity'); - table - .text('spec') - .nullable() - .comment('The entire spec JSON blob of the entity'); - table.dropColumn('data'); - }); -}; diff --git a/plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js b/plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js deleted file mode 100644 index f40df5f73e..0000000000 --- a/plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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('entities', table => { - table.dropColumn('api_version'); - table.dropColumn('kind'); - table.dropColumn('name'); - table.dropColumn('namespace'); - }); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - await knex.schema.alterTable('entities', table => { - table - .string('api_version') - .notNullable() - .comment('The apiVersion field of the entity'); - table.string('kind').notNullable().comment('The kind field of the entity'); - table - .string('name') - .nullable() - .comment('The metadata.name field of the entity'); - table - .string('namespace') - .nullable() - .comment('The metadata.namespace field of the entity'); - }); -}; diff --git a/plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js b/plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js deleted file mode 100644 index 77bf0529eb..0000000000 --- a/plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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('entities_search', table => { - table.index(['key'], 'entities_search_key'); - table.index(['value'], 'entities_search_value'); - }); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - await knex.schema.alterTable('entities_search', table => { - table.dropIndex('', 'entities_search_key'); - table.dropIndex('', 'entities_search_value'); - }); -}; diff --git a/plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js b/plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js deleted file mode 100644 index 85e729f814..0000000000 --- a/plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.createTable('entities_relations', table => { - table.comment('All relations between entities in the catalog'); - table - .uuid('originating_entity_id') - .references('id') - .inTable('entities') - .onDelete('CASCADE') - .notNullable() - .comment('The entity that provided the relation'); - table - .string('source_full_name') - .notNullable() - .comment('The full name of the source entity of the relation'); - table - .string('type') - .notNullable() - .comment('The type of the relation between the entities'); - table - .string('target_full_name') - .notNullable() - .comment('The full name of the target entity of the relation'); - - table.primary(['source_full_name', 'type', 'target_full_name']); - }); -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - await knex.schema.dropTable('entities_relations'); -}; diff --git a/plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js b/plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js deleted file mode 100644 index 9e8198b5eb..0000000000 --- a/plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - if (knex.client.config.client === 'sqlite3') { - // sqlite doesn't support dropPrimary so we recreate it properly instead - await knex.schema.dropTable('entities_relations'); - await knex.schema.createTable('entities_relations', table => { - table.comment('All relations between entities in the catalog'); - table - .uuid('originating_entity_id') - .references('id') - .inTable('entities') - .onDelete('CASCADE') - .notNullable() - .comment('The entity that provided the relation'); - table - .string('source_full_name') - .notNullable() - .comment('The full name of the source entity of the relation'); - table - .string('type') - .notNullable() - .comment('The type of the relation between the entities'); - table - .string('target_full_name') - .notNullable() - .comment('The full name of the target entity of the relation'); - table.index('source_full_name', 'source_full_name_idx'); - }); - } else { - await knex.schema.alterTable('entities_relations', table => { - table.dropPrimary(); - table.index('source_full_name', 'source_full_name_idx'); - }); - } -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - if (knex.client.config.client === 'sqlite3') { - await knex.schema.dropTable('entities_relations'); - await knex.schema.createTable('entities_relations', table => { - table.comment('All relations between entities in the catalog'); - table - .uuid('originating_entity_id') - .references('id') - .inTable('entities') - .onDelete('CASCADE') - .notNullable() - .comment('The entity that provided the relation'); - table - .string('source_full_name') - .notNullable() - .comment('The full name of the source entity of the relation'); - table - .string('type') - .notNullable() - .comment('The type of the relation between the entities'); - table - .string('target_full_name') - .notNullable() - .comment('The full name of the target entity of the relation'); - - table.primary(['source_full_name', 'type', 'target_full_name']); - }); - } else { - await knex.schema.alterTable('entities_relations', table => { - table.dropIndex([], 'source_full_name_idx'); - table.primary(['source_full_name', 'type', 'target_full_name']); - }); - } -}; diff --git a/plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js b/plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js deleted file mode 100644 index abb26cd5fc..0000000000 --- a/plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities_relations', table => { - table.index('originating_entity_id', 'originating_entity_id_idx'); - }); - await knex.schema.alterTable('entities_search', table => { - table.index('entity_id', 'entity_id_idx'); - }); - } -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities_relations', table => { - table.dropIndex([], 'originating_entity_id_idx'); - }); - await knex.schema.alterTable('entities_relations', table => { - table.dropIndex([], 'entity_id_idx'); - }); - } -}; diff --git a/plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js b/plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js deleted file mode 100644 index d924b0414a..0000000000 --- a/plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - if (knex.client.config.client !== 'sqlite3') { - // We actually just want to widen columns, but can't do that while a - // view is dependent on them - so we just reconstruct it exactly as it was - await knex.schema - .raw('DROP VIEW location_update_log_latest;') - .alterTable('location_update_log', table => { - table.text('message').alter(); - table.text('entity_name').nullable().alter(); - }).raw(` - CREATE VIEW location_update_log_latest AS - SELECT t1.* FROM location_update_log t1 - JOIN - ( - SELECT location_id, MAX(id) AS MAXID - FROM location_update_log - GROUP BY location_id - ) t2 - ON t1.location_id = t2.location_id - AND t1.id = t2.MAXID - GROUP BY t1.location_id, t1.id - ORDER BY created_at DESC; - `); - } -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - if (knex.client.config.client !== 'sqlite3') { - await knex.schema - .raw('DROP VIEW location_update_log_latest;') - .alterTable('location_update_log', table => { - table.string('message').alter(); - table.string('entity_name').nullable().alter(); - }).raw(` - CREATE VIEW location_update_log_latest AS - SELECT t1.* FROM location_update_log t1 - JOIN - ( - SELECT location_id, MAX(id) AS MAXID - FROM location_update_log - GROUP BY location_id - ) t2 - ON t1.location_id = t2.location_id - AND t1.id = t2.MAXID - GROUP BY t1.location_id, t1.id - ORDER BY created_at DESC; - `); - } -}; diff --git a/plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js b/plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js deleted file mode 100644 index ccfb1faffb..0000000000 --- a/plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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) { - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities', table => { - table.index('location_id', 'entity_location_id_idx'); - }); - await knex.schema.alterTable('location_update_log', table => { - table.index('location_id', 'update_log_location_id_idx'); - }); - } -}; - -/** - * @param {import('knex').Knex} knex - */ -exports.down = async function down(knex) { - if (knex.client.config.client !== 'sqlite3') { - await knex.schema.alterTable('entities', table => { - table.dropIndex([], 'entity_location_id_idx'); - }); - await knex.schema.alterTable('location_update_log', table => { - table.dropIndex([], 'update_log_location_id_idx'); - }); - } -}; diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 6773917d91..a1238d25b6 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "0.10.1", + "version": "0.10.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,14 +30,14 @@ }, "dependencies": { "@azure/msal-node": "^1.0.0-beta.3", - "@backstage/backend-common": "^0.8.1", - "@backstage/catalog-client": "^0.3.12", - "@backstage/catalog-model": "^0.8.1", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-client": "^0.3.13", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.5.5", - "@backstage/plugin-search-backend-node": "^0.1.4", - "@backstage/search-common": "^0.1.1", + "@backstage/integration": "^0.5.6", + "@backstage/plugin-search-backend-node": "^0.2.0", + "@backstage/search-common": "^0.1.2", "@microsoft/microsoft-graph-types": "^1.25.0", "@octokit/graphql": "^4.5.8", "@types/express": "^4.17.6", @@ -65,8 +65,8 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.1", - "@backstage/cli": "^0.6.14", + "@backstage/backend-test-utils": "^0.1.2", + "@backstage/cli": "^0.7.0", "@backstage/test-utils": "^0.1.13", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 5de012e936..7b8cabcd84 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -21,9 +21,10 @@ import { } from '@backstage/catalog-model'; import { serializeError } from '@backstage/errors'; import { Logger } from 'winston'; -import { ProcessingDatabase } from './database/types'; +import { ProcessingDatabase, RefreshStateItem } from './database/types'; import { CatalogProcessingOrchestrator } from './processing/types'; import { Stitcher } from './stitching/Stitcher'; +import { startTaskPipeline } from './TaskPipeline'; import { CatalogProcessingEngine, EntityProvider, @@ -80,7 +81,7 @@ class Connection implements EntityProviderConnection { } export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { - private running = false; + private stopFunc?: () => void; constructor( private readonly logger: Logger, @@ -99,106 +100,98 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { }), ); } - this.running = true; - this.run(); - } - private async run() { - while (this.running) { - try { - // TODO: We want to disconnect the queue popping and message processing - // so that if the queue popping fails we exponentially back off in order to give the DB room to sort itself out. - await this.process(); - } catch (e) { - this.logger.warn('Processing failed with:', e); - // TODO: this can be a little smarter as mentioned in the above comment. - // But for now, if something fails, wait a brief time to pick up the next message. - await this.wait(); - } - } - } - - private async process() { - const { items } = await this.processingDatabase.transaction(async tx => { - return this.processingDatabase.getProcessableEntities(tx, { - processBatchSize: 1, - }); - }); - - if (!items.length) { - // No items to process, wait and try again. - await this.wait(); - return; + if (this.stopFunc) { + throw new Error('Processing engine is already started'); } - // TODO: replace Promise.all with something more sophisticated for parallel processing. - await Promise.all( - items.map(async item => { - const { id, state, unprocessedEntity, entityRef } = item; - const result = await this.orchestrator.process({ - entity: unprocessedEntity, - state, - }); - - for (const error of result.errors) { - // TODO(freben): Try to extract the location out of the unprocessed - // entity and add as meta to the log lines - this.logger.warn(error.message, { - entity: entityRef, - }); + this.stopFunc = startTaskPipeline({ + lowWatermark: 5, + highWatermark: 10, + loadTasks: async count => { + try { + const { items } = await this.processingDatabase.transaction( + async tx => { + return this.processingDatabase.getProcessableEntities(tx, { + processBatchSize: count, + }); + }, + ); + return items; + } catch (error) { + this.logger.warn('Failed to load processing items', error); + return []; } - const errorsString = JSON.stringify( - result.errors.map(e => serializeError(e)), - ); + }, + processTask: async item => { + try { + const { id, state, unprocessedEntity, entityRef } = item; + const result = await this.orchestrator.process({ + entity: unprocessedEntity, + state, + }); - // If the result was marked as not OK, it signals that some part of the - // processing pipeline threw an exception. This can happen both as part of - // non-catastrophic things such as due to validation errors, as well as if - // something fatal happens inside the processing for other reasons. In any - // case, this means we can't trust that anything in the output is okay. So - // just store the errors and trigger a stich so that they become visible to - // the outside. - if (!result.ok) { + for (const error of result.errors) { + // TODO(freben): Try to extract the location out of the unprocessed + // entity and add as meta to the log lines + this.logger.warn(error.message, { + entity: entityRef, + }); + } + const errorsString = JSON.stringify( + result.errors.map(e => serializeError(e)), + ); + + // If the result was marked as not OK, it signals that some part of the + // processing pipeline threw an exception. This can happen both as part of + // non-catastrophic things such as due to validation errors, as well as if + // something fatal happens inside the processing for other reasons. In any + // case, this means we can't trust that anything in the output is okay. So + // just store the errors and trigger a stich so that they become visible to + // the outside. + if (!result.ok) { + await this.processingDatabase.transaction(async tx => { + await this.processingDatabase.updateProcessedEntityErrors(tx, { + id, + errors: errorsString, + }); + }); + await this.stitcher.stitch( + new Set([stringifyEntityRef(unprocessedEntity)]), + ); + return; + } + + result.completedEntity.metadata.uid = id; await this.processingDatabase.transaction(async tx => { - await this.processingDatabase.updateProcessedEntityErrors(tx, { + await this.processingDatabase.updateProcessedEntity(tx, { id, + processedEntity: result.completedEntity, + state: result.state, errors: errorsString, + relations: result.relations, + deferredEntities: result.deferredEntities, }); }); - await this.stitcher.stitch( - new Set([stringifyEntityRef(unprocessedEntity)]), - ); - return; + + const setOfThingsToStitch = new Set([ + stringifyEntityRef(result.completedEntity), + ...result.relations.map(relation => + stringifyEntityRef(relation.source), + ), + ]); + await this.stitcher.stitch(setOfThingsToStitch); + } catch (error) { + this.logger.warn('Processing failed with:', error); } - - result.completedEntity.metadata.uid = id; - await this.processingDatabase.transaction(async tx => { - await this.processingDatabase.updateProcessedEntity(tx, { - id, - processedEntity: result.completedEntity, - state: result.state, - errors: errorsString, - relations: result.relations, - deferredEntities: result.deferredEntities, - }); - }); - - const setOfThingsToStitch = new Set([ - stringifyEntityRef(result.completedEntity), - ...result.relations.map(relation => - stringifyEntityRef(relation.source), - ), - ]); - await this.stitcher.stitch(setOfThingsToStitch); - }), - ); - } - - private async wait() { - await new Promise(resolve => setTimeout(resolve, 1000)); + }, + }); } async stop() { - this.running = false; + if (this.stopFunc) { + this.stopFunc(); + this.stopFunc = undefined; + } } } diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index 7a74576ea7..e859a225e5 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -108,6 +108,7 @@ export class NextCatalogBuilder { private processors: CatalogProcessor[]; private processorsReplace: boolean; private parser: CatalogProcessorParser | undefined; + private refreshIntervalSeconds = 100; constructor(env: CatalogEnvironment) { this.env = env; @@ -136,6 +137,16 @@ export class NextCatalogBuilder { return this; } + /** + * Refresh interval determines how often entities should be refreshed. + * The default refresh duration is 100, setting this too low will potentially + * deplete request quotas to upstream services. + */ + setRefreshIntervalSeconds(seconds: number): NextCatalogBuilder { + this.refreshIntervalSeconds = seconds; + return this; + } + /** * Sets what policies to use for validation of entities between the pre- * processing and post-processing stages. All such policies must pass for the @@ -246,13 +257,17 @@ export class NextCatalogBuilder { await dbClient.migrate.latest({ directory: resolvePackagePath( '@backstage/plugin-catalog-backend', - 'migrationsv2', + 'migrations', ), }); const db = new CommonDatabase(dbClient, logger); - const processingDatabase = new DefaultProcessingDatabase(dbClient, logger); + const processingDatabase = new DefaultProcessingDatabase({ + database: dbClient, + logger, + refreshIntervalSeconds: this.refreshIntervalSeconds, + }); const integrations = ScmIntegrations.fromConfig(config); const orchestrator = new DefaultCatalogProcessingOrchestrator({ processors, diff --git a/plugins/catalog-backend/src/next/TaskPipeline.test.ts b/plugins/catalog-backend/src/next/TaskPipeline.test.ts new file mode 100644 index 0000000000..ddf668767a --- /dev/null +++ b/plugins/catalog-backend/src/next/TaskPipeline.test.ts @@ -0,0 +1,121 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { startTaskPipeline } from './TaskPipeline'; + +function createLimitedLoader(count: number, loadDelay?: number) { + const items = new Array(count).fill(0).map((_, index) => index); + const loadCounts = new Array(); + const processedTasks = new Array(); + + let resolveDone: (_: { + loadCounts: number[]; + processedTasks: number[]; + }) => void; + const done = new Promise<{ loadCounts: number[]; processedTasks: number[] }>( + resolve => { + resolveDone = resolve; + }, + ); + + const loadTasks = async (loadCount: number) => { + if (loadCounts.length < (loadDelay || 0)) { + loadCounts.push(0); + return []; + } + const loadedItems = items.splice(0, loadCount); + loadCounts.push(loadedItems.length); + return loadedItems; + }; + const processTask = async (item: number) => { + processedTasks.push(item); + await new Promise(resolve => setTimeout(resolve)); // emulate a bit of work + if (processedTasks.length === count) { + resolveDone({ processedTasks, loadCounts }); + } + }; + + return { loadTasks, processTask, done }; +} + +describe('startTaskPipeline', () => { + it('should process some tasks', async () => { + const { loadTasks, processTask, done } = createLimitedLoader(6); + const stop = startTaskPipeline({ + loadTasks, + processTask, + lowWatermark: 1, + highWatermark: 3, + }); + + const { loadCounts, processedTasks } = await done; + stop(); + + expect(loadCounts).toEqual([3, 2, 1]); + expect(processedTasks).toEqual([0, 1, 2, 3, 4, 5]); + }); + + it('should pick up processing after it runs dry', async () => { + const { loadTasks, processTask, done } = createLimitedLoader(5, 2); + const stop = startTaskPipeline({ + loadTasks, + processTask, + lowWatermark: 2, + highWatermark: 3, + pollingIntervalMs: 1, + }); + + const { loadCounts, processedTasks } = await done; + stop(); + + expect(loadCounts).toEqual([0, 0, 3, 1, 1]); + expect(processedTasks).toEqual([0, 1, 2, 3, 4]); + }); + + it('should process in parallel', async () => { + const { loadTasks, processTask, done } = createLimitedLoader(13); + const stop1 = startTaskPipeline({ + loadTasks, + processTask, + lowWatermark: 2, + highWatermark: 4, + }); + const stop2 = startTaskPipeline({ + loadTasks, + processTask, + lowWatermark: 2, + highWatermark: 4, + }); + + const { loadCounts, processedTasks } = await done; + stop1(); + stop2(); + + expect(loadCounts).toEqual([4, 4, 2, 2, 1]); + expect(processedTasks).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); + }); + + it('should require lowWatermark to be lower than highWatermark', async () => { + expect(() => { + startTaskPipeline({ + loadTasks: async () => [], + processTask: async () => {}, + lowWatermark: 3, + highWatermark: 3, + }); + }).toThrow('must be lower'); + }); +}); diff --git a/plugins/catalog-backend/src/next/TaskPipeline.ts b/plugins/catalog-backend/src/next/TaskPipeline.ts new file mode 100644 index 0000000000..7021330626 --- /dev/null +++ b/plugins/catalog-backend/src/next/TaskPipeline.ts @@ -0,0 +1,121 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const DEFAULT_POLLING_INTERVAL_MS = 1000; + +type Options = { + /** + * The callback used to load in new tasks. The number of items returned + * in the array must be at most `count` number of items, but may be lower. + * + * Any error thrown from this method fill be treated as an unhandled rejection. + */ + loadTasks: (count: number) => Promise>; + + /** + * The callback used to process a single item. + * + * Any error thrown from this method fill be treated as an unhandled rejection. + */ + processTask: (item: T) => Promise; + + /** + * The target minimum number of items to process in parallel. Once the number + * of in-flight tasks reaches this count, more tasks will be loaded in. + */ + lowWatermark: number; + + /** + * The maximum number of items to process in parallel. + */ + highWatermark: number; + + /** + * The interval at which tasks are polled for in the background when + * there aren't enough tasks to load to satisfy the low watermark. + * + * @default 1000 + */ + pollingIntervalMs?: number; +}; + +/** + * Creates a task processing pipeline which continuously loads in tasks to + * keep the number of parallel in-flight tasks between a low and high watermark. + * + * @param options The options for the pipeline. + * @returns A stop function which when called halts all processing. + */ +export function startTaskPipeline(options: Options) { + const { + loadTasks, + processTask, + lowWatermark, + highWatermark, + pollingIntervalMs = DEFAULT_POLLING_INTERVAL_MS, + } = options; + + if (lowWatermark >= highWatermark) { + throw new Error('lowWatermark must be lower than highWatermark'); + } + + let loading = false; + let stopped = false; + let inFlightCount = 0; + + async function maybeLoadMore() { + if (stopped || loading || inFlightCount > lowWatermark) { + return; + } + + // Once we hit the low watermark we load in enough items to reach the high watermark + loading = true; + const loadCount = highWatermark - inFlightCount; + const loadedItems = await loadTasks(loadCount); + loading = false; + + // We might not reach the high watermark here, in case there weren't enough items to load + inFlightCount += loadedItems.length; + loadedItems.forEach(item => { + processTask(item).finally(() => { + if (stopped) { + return; + } + + // For each item we complete we check if it's time to load more + inFlightCount -= 1; + maybeLoadMore(); + }); + }); + + // We might have processed some tasks while we where loading, so check if we can load more + if (loadedItems.length > 1) { + maybeLoadMore(); + } + } + + // This interval makes sure that we load in new items if the loop runs + // dry because of the lack of available tasks. As long as there are + // enough items to process this will be a noop. + const intervalId = setInterval(() => { + maybeLoadMore(); + }, pollingIntervalMs); + + return () => { + stopped = true; + clearInterval(intervalId); + }; +} diff --git a/plugins/catalog-backend/src/next/database/DatabaseManager.ts b/plugins/catalog-backend/src/next/database/DatabaseManager.ts index 22ae4e782f..d501bc6c61 100644 --- a/plugins/catalog-backend/src/next/database/DatabaseManager.ts +++ b/plugins/catalog-backend/src/next/database/DatabaseManager.ts @@ -36,7 +36,7 @@ export class DatabaseManager { ): Promise { const migrationsDir = resolvePackagePath( '@backstage/plugin-catalog-backend', - 'migrationsv2', + 'migrations', ); await knex.migrate.latest({ diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index 7d98a32377..0f83311944 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -39,7 +39,11 @@ describe('Default Processing Database', () => { await DatabaseManager.createDatabase(knex); return { knex, - db: new DefaultProcessingDatabase(knex, logger), + db: new DefaultProcessingDatabase({ + database: knex, + logger, + refreshIntervalSeconds: 100, + }), }; } diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index 7eb2cd1a74..f4804f9118 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -44,8 +44,11 @@ const BATCH_SIZE = 50; export class DefaultProcessingDatabase implements ProcessingDatabase { constructor( - private readonly database: Knex, - private readonly logger: Logger, + private readonly options: { + database: Knex; + logger: Logger; + refreshIntervalSeconds: number; + }, ) {} async updateProcessedEntity( @@ -272,7 +275,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { .whereIn('target_entity_ref', toRemove) .delete(); - this.logger.debug( + this.options.logger.debug( `removed, ${removedCount} entities: ${JSON.stringify(toRemove)}`, ); } @@ -355,8 +358,16 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ): Promise { const tx = txOpaque as Knex.Transaction; - const items = await tx('refresh_state') - .select() + let itemsQuery = tx('refresh_state').select(); + + // This avoids duplication of work because of race conditions and is + // also fast because locked rows are ignored rather than blocking. + // It's only available in MySQL and PostgreSQL + if (['mysql', 'mysql2', 'pg'].includes(tx.client.config.client)) { + itemsQuery = itemsQuery.forUpdate().skipLocked(); + } + + const items = await itemsQuery .where('next_update_at', '<=', tx.fn.now()) .limit(request.processBatchSize) .orderBy('next_update_at', 'asc'); @@ -369,8 +380,14 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { .update({ next_update_at: tx.client.config.client === 'sqlite3' - ? tx.raw(`datetime('now', ?)`, [`100 seconds`]) - : tx.raw(`now() + interval '100 seconds'`), + ? tx.raw(`datetime('now', ?)`, [ + `${this.options.refreshIntervalSeconds} seconds`, + ]) + : tx.raw( + `now() + interval '${Number( + this.options.refreshIntervalSeconds, + )} seconds'`, + ), }); return { @@ -398,7 +415,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { try { let result: T | undefined = undefined; - await this.database.transaction( + await this.options.database.transaction( async tx => { // We can't return here, as knex swallows the return type in case the transaction is rolled back: // https://github.com/knex/knex/blob/e37aeaa31c8ef9c1b07d2e4d3ec6607e557d800d/lib/transaction.js#L136 @@ -412,7 +429,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { return result!; } catch (e) { - this.logger.debug(`Error during transaction, ${e}`); + this.options.logger.debug(`Error during transaction, ${e}`); if ( /SQLITE_CONSTRAINT: UNIQUE/.test(e.message) || diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index f742e3c0db..9bec4442d7 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -66,6 +66,7 @@ import { } from '../ingestion/processors/PlaceholderProcessor'; import { defaultEntityDataParser } from '../ingestion/processors/util/parse'; import { LocationAnalyzer } from '../ingestion/types'; +import { NextCatalogBuilder } from '../next'; export type CatalogEnvironment = { logger: Logger; @@ -103,6 +104,10 @@ export class CatalogBuilder { private processorsReplace: boolean; private parser: CatalogProcessorParser | undefined; + static async create(env: CatalogEnvironment): Promise { + return new NextCatalogBuilder(env); + } + constructor(env: CatalogEnvironment) { this.env = env; this.entityPolicies = []; @@ -112,6 +117,10 @@ export class CatalogBuilder { this.processors = []; this.processorsReplace = false; this.parser = undefined; + + env.logger.warn( + "Creating the catalog with 'new CatalogBuilder(env)' is deprecated! Use CatalogBuilder.create(env) instead", + ); } /** diff --git a/plugins/catalog-backend/src/service/router.ts b/plugins/catalog-backend/src/service/router.ts index ae58255a4e..525ba76c0c 100644 --- a/plugins/catalog-backend/src/service/router.ts +++ b/plugins/catalog-backend/src/service/router.ts @@ -28,6 +28,7 @@ import { Logger } from 'winston'; import yn from 'yn'; import { EntitiesCatalog, LocationsCatalog } from '../catalog'; import { HigherOrderOperation, LocationAnalyzer } from '../ingestion/types'; +import { LocationService } from '../next/types'; import { basicEntityFilter, parseEntityFilterParams, @@ -45,6 +46,7 @@ export interface RouterOptions { locationsCatalog?: LocationsCatalog; higherOrderOperation?: HigherOrderOperation; locationAnalyzer?: LocationAnalyzer; + locationService?: LocationService; logger: Logger; config: Config; } @@ -57,6 +59,7 @@ export async function createRouter( locationsCatalog, higherOrderOperation, locationAnalyzer, + locationService, config, logger, } = options; @@ -145,6 +148,40 @@ export async function createRouter( }); } + if (locationService) { + router + .post('/locations', async (req, res) => { + const input = await validateRequestBody(req, locationSpecSchema); + const dryRun = yn(req.query.dryRun, { default: false }); + + // when in dryRun addLocation is effectively a read operation so we don't + // need to disallow readonly + if (!dryRun) { + disallowReadonlyMode(readonlyEnabled); + } + + const output = await locationService.createLocation(input, dryRun); + res.status(201).json(output); + }) + .get('/locations', async (_req, res) => { + const locations = await locationService.listLocations(); + res.status(200).json(locations.map(l => ({ data: l }))); + }) + + .get('/locations/:id', async (req, res) => { + const { id } = req.params; + const output = await locationService.getLocation(id); + res.status(200).json(output); + }) + .delete('/locations/:id', async (req, res) => { + disallowReadonlyMode(readonlyEnabled); + + const { id } = req.params; + await locationService.deleteLocation(id); + res.status(204).end(); + }); + } + if (higherOrderOperation) { router.post('/locations', async (req, res) => { const input = await validateRequestBody(req, locationSpecSchema); diff --git a/plugins/catalog-backend/src/service/standaloneServer.ts b/plugins/catalog-backend/src/service/standaloneServer.ts index 44a5c0f84d..24a1a9e4cd 100644 --- a/plugins/catalog-backend/src/service/standaloneServer.ts +++ b/plugins/catalog-backend/src/service/standaloneServer.ts @@ -63,9 +63,12 @@ export async function startStandaloneServer( logger, config, }); - const service = createServiceBuilder(module) - .enableCors({ origin: 'http://localhost:3000' }) + let service = createServiceBuilder(module) + .setPort(options.port) .addRouter('/catalog', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } return await service.start().catch(err => { logger.error(err); process.exit(1); diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index e8820ee070..40eb6d3382 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", - "@backstage/catalog-model": "^0.8.0", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@graphql-modules/core": "^0.7.17", "apollo-server": "^2.16.1", @@ -42,7 +42,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.6.13", + "@backstage/cli": "^0.7.0", "@backstage/test-utils": "^0.1.11", "@graphql-codegen/cli": "^1.21.3", "@graphql-codegen/typescript": "^1.17.7", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 18c514f847..9b6e1c4487 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-import +## 0.5.9 + +### Patch Changes + +- 70bc30c5b: Display preview result final step. +- Updated dependencies [27a9b503a] +- Updated dependencies [f4e3ac5ce] +- Updated dependencies [7028ee1ca] +- Updated dependencies [70bc30c5b] +- Updated dependencies [eda9dbd5f] + - @backstage/catalog-model@0.8.2 + - @backstage/integration-react@0.1.3 + - @backstage/plugin-catalog-react@0.2.2 + - @backstage/catalog-client@0.3.13 + - @backstage/integration@0.5.6 + ## 0.5.8 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index e2db1968d8..c017c3d08a 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.5.8", + "version": "0.5.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", - "@backstage/catalog-client": "^0.3.12", + "@backstage/catalog-model": "^0.8.2", + "@backstage/catalog-client": "^0.3.13", "@backstage/core": "^0.7.11", - "@backstage/integration": "^0.5.4", - "@backstage/integration-react": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/integration": "^0.5.6", + "@backstage/integration-react": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -53,7 +53,7 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog-import/src/components/EntityListComponent/EntityListComponent.tsx b/plugins/catalog-import/src/components/EntityListComponent/EntityListComponent.tsx index bdeb483df4..64290d223e 100644 --- a/plugins/catalog-import/src/components/EntityListComponent/EntityListComponent.tsx +++ b/plugins/catalog-import/src/components/EntityListComponent/EntityListComponent.tsx @@ -146,11 +146,15 @@ export const EntityListComponent = ({ {sortEntities(r.entities).map(entity => ( {getEntityIcon(entity)} diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 16f2d3e1b1..88d7a04a78 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-react +## 0.2.2 + +### Patch Changes + +- 7028ee1ca: Expose `getEntitySourceLocation`, `getEntityMetadataViewUrl`, and + `getEntityMetadataEditUrl` from `@backstage/plugin-catalog-react`. +- Updated dependencies [75b8537ce] +- Updated dependencies [27a9b503a] +- Updated dependencies [da8cba44f] +- Updated dependencies [70bc30c5b] +- Updated dependencies [eda9dbd5f] + - @backstage/core-plugin-api@0.1.2 + - @backstage/catalog-model@0.8.2 + - @backstage/catalog-client@0.3.13 + - @backstage/integration@0.5.6 + ## 0.2.1 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 8d7bc1f5d1..bb814d7d4f 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-react", - "version": "0.2.1", + "version": "0.2.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,11 +28,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.3.12", - "@backstage/catalog-model": "^0.8.1", + "@backstage/catalog-client": "^0.3.13", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.12", - "@backstage/core-plugin-api": "^0.1.1", - "@backstage/integration": "^0.5.0", + "@backstage/core-plugin-api": "^0.1.2", + "@backstage/integration": "^0.5.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -44,7 +44,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/core": "^0.7.12", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index c04e205715..53df1b37f8 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-catalog +## 0.6.2 + +### Patch Changes + +- db1c8f93b: A `` component is now available for use in custom Search Experiences. +- f4e3ac5ce: Move `ScmIntegrationIcon` from `@backstage/plugin-catalog` to + `@backstage/integration-react` and make it customizable using + `app.getSystemIcon()`. +- 7028ee1ca: Expose `getEntitySourceLocation`, `getEntityMetadataViewUrl`, and + `getEntityMetadataEditUrl` from `@backstage/plugin-catalog-react`. +- 4fbb00707: A new card that shows components that depend on the active component +- d5ad47bbb: Exported AboutCard contents and utility functions +- Updated dependencies [27a9b503a] +- Updated dependencies [f4e3ac5ce] +- Updated dependencies [7028ee1ca] +- Updated dependencies [70bc30c5b] +- Updated dependencies [eda9dbd5f] + - @backstage/catalog-model@0.8.2 + - @backstage/integration-react@0.1.3 + - @backstage/plugin-catalog-react@0.2.2 + - @backstage/catalog-client@0.3.13 + - @backstage/integration@0.5.6 + ## 0.6.1 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 0133ae3bbb..ce72d95103 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "0.6.1", + "version": "0.6.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,13 +30,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.3.12", - "@backstage/catalog-model": "^0.8.1", + "@backstage/catalog-client": "^0.3.13", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.12", "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.5.5", - "@backstage/integration-react": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.2.1", + "@backstage/integration": "^0.5.6", + "@backstage/integration-react": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -53,7 +53,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx b/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx index a57b223afe..a604166688 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx @@ -21,7 +21,7 @@ type Props = { children?: React.ReactNode; }; -const CatalogLayout = ({ children }: Props) => { +export const CatalogLayout = ({ children }: Props) => { const orgName = useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; diff --git a/plugins/catalog/src/components/CatalogPage/index.ts b/plugins/catalog/src/components/CatalogPage/index.ts index 1adb8866c8..1e5d9d88c1 100644 --- a/plugins/catalog/src/components/CatalogPage/index.ts +++ b/plugins/catalog/src/components/CatalogPage/index.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export { CatalogLayout } from './CatalogLayout'; export { CatalogPage } from './CatalogPage'; diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 0958503077..1596de0e8d 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -15,8 +15,10 @@ */ export * from './components/AboutCard'; +export { CatalogLayout } from './components/CatalogPage'; export { CatalogResultListItem } from './components/CatalogResultListItem'; export { CatalogTable } from './components/CatalogTable'; +export { CreateComponentButton } from './components/CreateComponentButton'; export { EntityLayout } from './components/EntityLayout'; export * from './components/EntityOrphanWarning'; export { EntityPageLayout } from './components/EntityPageLayout'; diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 20cac43ac9..3091996034 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -31,9 +31,9 @@ "postpack": "backstage-cli postpack" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -50,7 +50,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 03408ac6c1..29cc77d7e9 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/catalog-model": "^0.8.2", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/core": "^0.7.11", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", @@ -47,7 +47,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 1306fa093a..7def52f498 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -19,12 +19,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", - "@backstage/catalog-client": "^0.3.12", - "@backstage/catalog-model": "^0.8.0", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-client": "^0.3.13", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.5.4", + "@backstage/integration": "^0.5.6", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", "express": "^4.17.1", @@ -36,7 +36,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.13", + "@backstage/cli": "^0.7.0", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", "msw": "^0.21.2", diff --git a/plugins/code-coverage-backend/src/service/standaloneServer.ts b/plugins/code-coverage-backend/src/service/standaloneServer.ts index 2fb9627936..1e9e5131d1 100644 --- a/plugins/code-coverage-backend/src/service/standaloneServer.ts +++ b/plugins/code-coverage-backend/src/service/standaloneServer.ts @@ -61,9 +61,12 @@ export async function startStandaloneServer( logger, }); - const service = createServiceBuilder(module) - .enableCors({ origin: 'http://localhost:3000' }) + let service = createServiceBuilder(module) + .setPort(options.port) .addRouter('/code-coverage', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } return await service.start().catch(err => { logger.error(err); diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index a7d7126646..51626acef0 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -20,11 +20,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.4", "@backstage/core": "^0.7.11", "@backstage/errors": "^0.1.1", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -39,7 +39,7 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 12e1c65664..427de0967b 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -34,7 +34,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 922ab04eb1..f1d0b9b7c8 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-cost-insights +## 0.10.2 + +### Patch Changes + +- 9d906c7a1: Move `canvas` package to `devDependencies`. + ## 0.10.1 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index bb7e9b6984..32c985be24 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cost-insights", - "version": "0.10.1", + "version": "0.10.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -54,7 +54,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 5a8d082abe..cb178e9ae6 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -31,7 +31,7 @@ "@backstage/core": "^0.7.9" }, "devDependencies": { - "@backstage/cli": "^0.6.11", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.14", "@backstage/test-utils": "^0.1.11", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/explore/package.json b/plugins/explore/package.json index a05ed2185d..fd6ff19a93 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -30,9 +30,9 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/plugin-explore-react": "^0.0.5", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", @@ -45,7 +45,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index fe0057b200..9f00172358 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -31,10 +31,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", "@backstage/errors": "^0.1.1", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -47,7 +47,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index affb0bf0c6..3be5ae031b 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -41,7 +41,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 1c075c420c..e90905a767 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/core": "^0.7.11", - "@backstage/integration": "^0.5.3", + "@backstage/integration": "^0.5.6", "@backstage/theme": "^0.2.8", "recharts": "^1.8.5", "@material-ui/core": "^4.11.0", @@ -36,7 +36,7 @@ "react": "^16.13.1" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 2f9580b3ca..c404501902 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-actions +## 0.4.9 + +### Patch Changes + +- 9bdd2cca8: Add missing token on job list call to GitHub API +- Updated dependencies [27a9b503a] +- Updated dependencies [7028ee1ca] +- Updated dependencies [eda9dbd5f] + - @backstage/catalog-model@0.8.2 + - @backstage/plugin-catalog-react@0.2.2 + - @backstage/integration@0.5.6 + ## 0.4.8 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 51678940bf..9e651194db 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-actions", - "version": "0.4.8", + "version": "0.4.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/catalog-model": "^0.8.2", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/core": "^0.7.11", - "@backstage/integration": "^0.5.4", + "@backstage/integration": "^0.5.6", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -50,7 +50,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 3f8a4f51ed..4a2dab8798 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-deployments +## 0.1.8 + +### Patch Changes + +- ef2f928f4: Add deployment statuses to the GithubDeployments plugin +- Updated dependencies [27a9b503a] +- Updated dependencies [f4e3ac5ce] +- Updated dependencies [7028ee1ca] +- Updated dependencies [eda9dbd5f] + - @backstage/catalog-model@0.8.2 + - @backstage/integration-react@0.1.3 + - @backstage/plugin-catalog-react@0.2.2 + - @backstage/integration@0.5.6 + ## 0.1.7 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index aba58f4410..af49b876d3 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-deployments", - "version": "0.1.7", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,12 +20,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.5.4", - "@backstage/integration-react": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/integration": "^0.5.6", + "@backstage/integration-react": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -37,7 +37,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 5116c797b8..66d136b6f8 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -42,7 +42,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index c6929fe208..209d105b4c 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/core": "^0.7.11", - "@backstage/core-plugin-api": "^0.1.0", + "@backstage/core-plugin-api": "^0.1.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -44,7 +44,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/graphql/package.json b/plugins/graphql/package.json index 619df1d33b..9d278bceb6 100644 --- a/plugins/graphql/package.json +++ b/plugins/graphql/package.json @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", + "@backstage/backend-common": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/plugin-catalog-graphql": "^0.2.9", "@graphql-modules/core": "^0.7.17", @@ -45,7 +45,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.11", + "@backstage/cli": "^0.7.0", "@types/supertest": "^2.0.8", "eslint-plugin-graphql": "^4.0.0", "msw": "^0.20.5", diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index cc3a212c42..84ebdb096e 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -20,10 +20,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", "@backstage/errors": "^0.1.1", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@date-io/luxon": "1.x", "@material-ui/core": "^4.11.0", @@ -37,7 +37,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index ada9815baf..a2204ac704 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -47,7 +47,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index fbcd1d1e68..617dd2d3cb 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", - "@backstage/catalog-model": "^0.8.0", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -42,7 +42,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.6.13", + "@backstage/cli": "^0.7.0", "@types/jest-when": "^2.7.2", "@types/lodash": "^4.14.151", "jest-when": "^3.1.0", diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index ce8bc35bd9..01e9408633 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -33,7 +33,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 06de05fad8..39297dd109 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", - "@backstage/catalog-model": "^0.8.0", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/plugin-kubernetes-common": "^0.1.1", "@google-cloud/container": "^2.2.0", @@ -53,7 +53,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.13", + "@backstage/cli": "^0.7.0", "@types/aws4": "^1.5.1", "supertest": "^6.1.3" }, diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index a9e5be0b4e..30bf5794bf 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -35,11 +35,11 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@kubernetes/client-node": "^0.14.0" }, "devDependencies": { - "@backstage/cli": "^0.6.13" + "@backstage/cli": "^0.7.0" }, "jest": { "roots": [ diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 5f3ca01e37..96820e2a4f 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -30,10 +30,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/plugin-kubernetes-common": "^0.1.1", "@backstage/theme": "^0.2.8", "@kubernetes/client-node": "^0.14.0", @@ -49,7 +49,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index ead00d9d7d..f053479f6d 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -31,10 +31,10 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.4", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -46,7 +46,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index e5fa8d2e88..c3abf86f6b 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -41,7 +41,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/org/package.json b/plugins/org/package.json index c9195d5709..2266eab7fb 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -20,10 +20,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/core-api": "^0.2.20", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/core-api": "^0.2.22", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -35,7 +35,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 81ac6e23fc..790866aa23 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -46,7 +46,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 2890039b96..2147e0682a 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-proxy-backend +## 0.2.9 + +### Patch Changes + +- 875809a59: Fixed proxy requests to the base URL of routes without a trailing slash redirecting to the `target` with the full path appended. +- Updated dependencies [92963779b] +- Updated dependencies [eda9dbd5f] + - @backstage/backend-common@0.8.2 + ## 0.2.8 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index d2b0d64678..5e8549f6c7 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-proxy-backend", - "version": "0.2.8", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,12 +28,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", + "@backstage/backend-common": "^0.8.2", "@backstage/config": "^0.1.5", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "http-proxy-middleware": "^0.19.1", + "http-proxy-middleware": "^2.0.0", "morgan": "^1.10.0", "uuid": "^8.0.0", "winston": "^3.2.1", @@ -42,7 +42,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.6.11", + "@backstage/cli": "^0.7.0", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/proxy-backend/src/service/router.test.ts b/plugins/proxy-backend/src/service/router.test.ts index 57b87754e2..8b88e45cc5 100644 --- a/plugins/proxy-backend/src/service/router.test.ts +++ b/plugins/proxy-backend/src/service/router.test.ts @@ -14,25 +14,19 @@ * limitations under the License. */ -import { buildMiddleware, createRouter } from './router'; import { getVoidLogger, loadBackendConfig, SingleHostDiscovery, } from '@backstage/backend-common'; -import createProxyMiddleware, { - Config as ProxyMiddlewareConfig, - Proxy, -} from 'http-proxy-middleware'; +import { Request, Response } from 'express'; import * as http from 'http'; +import { createProxyMiddleware, Options } from 'http-proxy-middleware'; +import { buildMiddleware, createRouter } from './router'; -jest.mock('http-proxy-middleware', () => { - return jest.fn().mockImplementation( - (): Proxy => { - return () => undefined; - }, - ); -}); +jest.mock('http-proxy-middleware', () => ({ + createProxyMiddleware: jest.fn(() => () => undefined), +})); const mockCreateProxyMiddleware = createProxyMiddleware as jest.MockedFunction< typeof createProxyMiddleware @@ -66,7 +60,7 @@ describe('buildMiddleware', () => { const [filter, fullConfig] = mockCreateProxyMiddleware.mock.calls[0] as [ (pathname: string, req: Partial) => boolean, - ProxyMiddlewareConfig, + Options, ]; expect(filter('', { method: 'GET', headers: {} })).toBe(true); expect(filter('', { method: 'POST', headers: {} })).toBe(true); @@ -86,7 +80,7 @@ describe('buildMiddleware', () => { const [filter, fullConfig] = mockCreateProxyMiddleware.mock.calls[0] as [ (pathname: string, req: Partial) => boolean, - ProxyMiddlewareConfig, + Options, ]; expect(filter('', { method: 'GET', headers: {} })).toBe(true); expect(filter('', { method: 'POST', headers: {} })).toBe(true); @@ -106,7 +100,7 @@ describe('buildMiddleware', () => { const [filter, fullConfig] = mockCreateProxyMiddleware.mock.calls[0] as [ (pathname: string, req: Partial) => boolean, - ProxyMiddlewareConfig, + Options, ]; expect(filter('', { method: 'GET', headers: {} })).toBe(true); expect(filter('', { method: 'POST', headers: {} })).toBe(true); @@ -129,7 +123,7 @@ describe('buildMiddleware', () => { const [filter, fullConfig] = mockCreateProxyMiddleware.mock.calls[0] as [ (pathname: string, req: Partial) => boolean, - ProxyMiddlewareConfig, + Options, ]; expect(filter('', { method: 'GET', headers: {} })).toBe(true); expect(filter('', { method: 'POST', headers: {} })).toBe(false); @@ -254,8 +248,7 @@ describe('buildMiddleware', () => { expect(createProxyMiddleware).toHaveBeenCalledTimes(1); - const config = mockCreateProxyMiddleware.mock - .calls[0][1] as ProxyMiddlewareConfig; + const config = mockCreateProxyMiddleware.mock.calls[0][1] as Options; const testClientResponse = { headers: { @@ -275,8 +268,8 @@ describe('buildMiddleware', () => { config.onProxyRes!( testClientResponse as http.IncomingMessage, - {} as http.IncomingMessage, - {} as http.ServerResponse, + {} as Request, + {} as Response, ); expect(Object.keys(testClientResponse.headers!)).toEqual([ @@ -298,8 +291,7 @@ describe('buildMiddleware', () => { expect(createProxyMiddleware).toHaveBeenCalledTimes(1); - const config = mockCreateProxyMiddleware.mock - .calls[0][1] as ProxyMiddlewareConfig; + const config = mockCreateProxyMiddleware.mock.calls[0][1] as Options; const testClientResponse = { headers: { @@ -313,8 +305,8 @@ describe('buildMiddleware', () => { config.onProxyRes!( testClientResponse as http.IncomingMessage, - {} as http.IncomingMessage, - {} as http.ServerResponse, + {} as Request, + {} as Response, ); expect(Object.keys(testClientResponse.headers!)).toEqual(['set-cookie']); diff --git a/plugins/proxy-backend/src/service/router.ts b/plugins/proxy-backend/src/service/router.ts index c3b1d056db..8957d4e8ce 100644 --- a/plugins/proxy-backend/src/service/router.ts +++ b/plugins/proxy-backend/src/service/router.ts @@ -17,9 +17,10 @@ import { Config } from '@backstage/config'; import express from 'express'; import Router from 'express-promise-router'; -import createProxyMiddleware, { - Config as ProxyMiddlewareConfig, - Proxy, +import { + createProxyMiddleware, + Options, + RequestHandler, } from 'http-proxy-middleware'; import { Logger } from 'winston'; import http from 'http'; @@ -52,7 +53,7 @@ export interface RouterOptions { discovery: PluginEndpointDiscovery; } -export interface ProxyConfig extends ProxyMiddlewareConfig { +export interface ProxyConfig extends Options { allowedMethods?: string[]; allowedHeaders?: string[]; } @@ -64,14 +65,17 @@ export function buildMiddleware( logger: Logger, route: string, config: string | ProxyConfig, -): Proxy { +): RequestHandler { const fullConfig = typeof config === 'string' ? { target: config } : { ...config }; // Validate that target is a valid URL. + if (typeof fullConfig.target !== 'string') { + throw new Error(`Proxy target must be a string`); + } try { // eslint-disable-next-line no-new - new URL(fullConfig.target!); + new URL(fullConfig.target! as string); } catch { throw new Error( `Proxy target is not a valid URL: ${fullConfig.target ?? ''}`, @@ -131,7 +135,7 @@ export function buildMiddleware( // 2. Only permit the allowed HTTP methods if configured // // We are filtering the proxy request headers here rather than in - // `onProxyReq` becuase when global-agent is enabled then `onProxyReq` + // `onProxyReq` because when global-agent is enabled then `onProxyReq` // fires _after_ the agent has already sent the headers to the proxy // target, causing a ERR_HTTP_HEADERS_SENT crash const filter = (_pathname: string, req: http.IncomingMessage): boolean => { diff --git a/plugins/proxy-backend/src/service/standaloneServer.ts b/plugins/proxy-backend/src/service/standaloneServer.ts index c64d69e2a4..bd681948bc 100644 --- a/plugins/proxy-backend/src/service/standaloneServer.ts +++ b/plugins/proxy-backend/src/service/standaloneServer.ts @@ -43,9 +43,12 @@ export async function startStandaloneServer( logger, discovery, }); - const service = createServiceBuilder(module) - .enableCors({ origin: 'http://localhost:3000' }) + let service = createServiceBuilder(module) + .setPort(options.port) .addRouter('/proxy', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } logger.debug('Starting application server...'); diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json index 80b0e96a50..a162c650b3 100644 --- a/plugins/register-component/package.json +++ b/plugins/register-component/package.json @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -45,7 +45,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 03be93dbfa..ca81bc27f2 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", + "@backstage/backend-common": "^0.8.2", "@backstage/config": "^0.1.5", "@types/express": "^4.17.6", "axios": "^0.21.1", @@ -47,7 +47,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.11", + "@backstage/cli": "^0.7.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/rollbar-backend/src/service/standaloneServer.ts b/plugins/rollbar-backend/src/service/standaloneServer.ts index b30bf6fc6b..aef9741475 100644 --- a/plugins/rollbar-backend/src/service/standaloneServer.ts +++ b/plugins/rollbar-backend/src/service/standaloneServer.ts @@ -38,9 +38,12 @@ export async function startStandaloneServer( const router = await createRouter({ logger, config }); - const service = createServiceBuilder(module) - .enableCors({ origin: 'http://localhost:3000' }) + let service = createServiceBuilder(module) + .setPort(options.port) .addRouter('/catalog', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } return await service.start().catch(err => { logger.error(err); diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 06ce51eada..4f55abda2b 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -47,7 +47,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 4d48ea5713..c0cfe8dc58 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,55 @@ # @backstage/plugin-scaffolder-backend +## 0.12.0 + +### Minor Changes + +- 66c6bfebd: Scaffolding a repository in Bitbucket will now use the apiBaseUrl if it is provided instead of only the host parameter + +### Patch Changes + +- 27a9b503a: Introduce conditional steps in scaffolder templates. + + A step can now include an `if` property that only executes a step if the + condition is truthy. The condition can include handlebar templates. + + ```yaml + - id: register + if: '{{ not parameters.dryRun }}' + name: Register + action: catalog:register + input: + repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}' + catalogInfoPath: '/catalog-info.yaml' + ``` + + Also introduces a `not` helper in handlebar templates that allows to negate + boolean expressions. + +- 55a253de2: Migrating old `backstage.io/v1alpha1` templates to `backstage.io/v1beta2` + + Deprecating the `create-react-app` Template. We're planning on removing the `create-react-app` templater, as it's been a little tricky to support and takes 15mins to run in a container. We've currently cached a copy of the output for `create-react-app` and ship that under our sample templates folder. If you want to continue using it, we suggest copying the template out of there and putting it in your own repository as it will be removed in upcoming releases. + + We also recommend removing this entry from your `app-config.yaml` if it exists: + + ```diff + - - type: url + - target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml + - rules: + - - allow: [Template] + ``` + +- f26e6008f: Add `debug:log` action for debugging. +- 4f8cf50fe: Update gitbeaker past the broken version without a dist folder +- Updated dependencies [92963779b] +- Updated dependencies [27a9b503a] +- Updated dependencies [70bc30c5b] +- Updated dependencies [eda9dbd5f] + - @backstage/backend-common@0.8.2 + - @backstage/catalog-model@0.8.2 + - @backstage/catalog-client@0.3.13 + - @backstage/integration@0.5.6 + ## 0.11.5 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index ecb914c9de..9c782d7053 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "0.11.5", + "version": "0.12.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,19 +29,19 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.1", - "@backstage/catalog-client": "^0.3.12", - "@backstage/catalog-model": "^0.8.1", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-client": "^0.3.13", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.5.5", + "@backstage/integration": "^0.5.6", "@gitbeaker/core": "^30.2.0", "@gitbeaker/node": "^30.2.0", "@octokit/rest": "^18.5.3", "@types/express": "^4.17.6", "@types/git-url-parse": "^9.0.0", "azure-devops-node-api": "^10.1.1", - "command-exists-promise": "^2.0.2", + "command-exists": "^1.2.9", "compression": "^1.7.4", "cors": "^2.8.5", "cross-fetch": "^3.0.6", @@ -64,8 +64,9 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/test-utils": "^0.1.13", + "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", "@types/supertest": "^2.0.8", diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts index 2df8a4415d..4a7cb13525 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts @@ -140,7 +140,7 @@ describe('publish:bitbucket', () => { 'https://hosted.bitbucket.com/rest/api/1.0/projects/owner/repos', (req, res, ctx) => { expect(req.headers.get('Authorization')).toBe('Bearer thing'); - expect(req.body).toEqual({ is_private: true, name: 'repo' }); + expect(req.body).toEqual({ public: false, name: 'repo' }); return res( ctx.status(201), ctx.set('Content-Type', 'application/json'), @@ -174,6 +174,88 @@ describe('publish:bitbucket', () => { }); }); + describe('LFS for hosted bitbucket', () => { + const repoCreationResponse = { + links: { + self: [ + { + href: 'https://bitbucket.mycompany.com/projects/project/repos/repo', + }, + ], + clone: [ + { + name: 'http', + href: 'https://bitbucket.mycompany.com/scm/project/repo', + }, + ], + }, + }; + + it('should call the correct APIs to enable LFS if requested and the host is hosted bitbucket', async () => { + expect.assertions(1); + server.use( + rest.post( + 'https://hosted.bitbucket.com/rest/api/1.0/projects/owner/repos', + (_, res, ctx) => { + return res( + ctx.status(201), + ctx.set('Content-Type', 'application/json'), + ctx.json(repoCreationResponse), + ); + }, + ), + rest.put( + 'https://hosted.bitbucket.com/rest/git-lfs/admin/projects/owner/repos/repo/enabled', + (req, res, ctx) => { + expect(req.headers.get('Authorization')).toBe('Bearer thing'); + return res(ctx.status(204)); + }, + ), + ); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + repoUrl: 'hosted.bitbucket.com?owner=owner&repo=repo', + enableLFS: true, + }, + }); + }); + + it('should report an error if enabling LFS fails', async () => { + server.use( + rest.post( + 'https://hosted.bitbucket.com/rest/api/1.0/projects/owner/repos', + (_, res, ctx) => { + return res( + ctx.status(201), + ctx.set('Content-Type', 'application/json'), + ctx.json(repoCreationResponse), + ); + }, + ), + rest.put( + 'https://hosted.bitbucket.com/rest/git-lfs/admin/projects/owner/repos/repo/enabled', + (_, res, ctx) => { + return res(ctx.status(500)); + }, + ), + ); + + await expect( + action.handler({ + ...mockContext, + input: { + ...mockContext.input, + repoUrl: 'hosted.bitbucket.com?owner=owner&repo=repo', + enableLFS: true, + }, + }), + ).rejects.toThrow(/Failed to enable LFS/); + }); + }); + it('should call initAndPush with the correct values', async () => { server.use( rest.post( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts index cd3453adfd..b1b4f96807 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -19,10 +19,10 @@ import { BitbucketIntegrationConfig, ScmIntegrationRegistry, } from '@backstage/integration'; -import { initRepoAndPush } from '../../../stages/publish/helpers'; -import { getRepoSourceDirectory, parseRepoUrl } from './util'; import fetch from 'cross-fetch'; +import { initRepoAndPush } from '../../../stages/publish/helpers'; import { createTemplateAction } from '../../createTemplateAction'; +import { getRepoSourceDirectory, parseRepoUrl } from './util'; const createBitbucketCloudRepository = async (opts: { owner: string; @@ -102,7 +102,7 @@ const createBitbucketServerRepository = async (opts: { body: JSON.stringify({ name: repo, description: description, - is_private: repoVisibility === 'private', + public: repoVisibility === 'public', }), headers: { Authorization: authorization, @@ -156,6 +156,32 @@ const getAuthorizationHeader = (config: BitbucketIntegrationConfig) => { ); }; +const performEnableLFS = async (opts: { + authorization: string; + host: string; + owner: string; + repo: string; +}) => { + const { authorization, host, owner, repo } = opts; + + const options: RequestInit = { + method: 'PUT', + headers: { + Authorization: authorization, + }, + }; + + const { ok, status, statusText } = await fetch( + `https://${host}/rest/git-lfs/admin/projects/${owner}/repos/${repo}/enabled`, + options, + ); + + if (!ok) + throw new Error( + `Failed to enable LFS in the repository, ${status}: ${statusText}`, + ); +}; + export function createPublishBitbucketAction(options: { integrations: ScmIntegrationRegistry; }) { @@ -166,6 +192,7 @@ export function createPublishBitbucketAction(options: { description: string; repoVisibility: 'private' | 'public'; sourcePath?: string; + enableLFS: boolean; }>({ id: 'publish:bitbucket', description: @@ -193,6 +220,11 @@ export function createPublishBitbucketAction(options: { 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', type: 'string', }, + enableLFS: { + title: + 'Enable LFS for the repository. Only available for hosted Bitbucket.', + type: 'boolean', + }, }, }, output: { @@ -210,7 +242,12 @@ export function createPublishBitbucketAction(options: { }, }, async handler(ctx) { - const { repoUrl, description, repoVisibility = 'private' } = ctx.input; + const { + repoUrl, + description, + repoVisibility = 'private', + enableLFS = false, + } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl); @@ -254,6 +291,10 @@ export function createPublishBitbucketAction(options: { logger: ctx.logger, }); + if (enableLFS && host !== 'bitbucket.org') { + await performEnableLFS({ authorization, host, owner, repo }); + } + ctx.output('remoteUrl', remoteUrl); ctx.output('repoContentsUrl', repoContentsUrl); }, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts index 922662ebe3..2d370ed80a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts @@ -174,7 +174,7 @@ export class BitbucketPublisher implements PublisherBase { body: JSON.stringify({ name: name, description: description, - is_private: this.config.repoVisibility === 'private', + public: this.config.repoVisibility === 'public', }), headers: { Authorization: this.getAuthorizationHeader(), diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts index 59fb72d515..a9227c742e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts @@ -18,7 +18,7 @@ const runCommand = jest.fn(); const commandExists = jest.fn(); jest.mock('./helpers', () => ({ runCommand })); -jest.mock('command-exists-promise', () => commandExists); +jest.mock('command-exists', () => commandExists); jest.mock('fs-extra'); import { ContainerRunner } from '@backstage/backend-common'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts index 8819a90d63..c0abc44521 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts @@ -16,13 +16,12 @@ import { ContainerRunner } from '@backstage/backend-common'; import { JsonValue } from '@backstage/config'; +import commandExists from 'command-exists'; import fs from 'fs-extra'; import path from 'path'; import { runCommand } from './helpers'; import { TemplaterBase, TemplaterRunOptions } from './types'; -const commandExists = require('command-exists-promise'); - export class CookieCutter implements TemplaterBase { private readonly containerRunner: ContainerRunner; diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 25f27aac81..41603dbafa 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-scaffolder +## 0.9.8 + +### Patch Changes + +- 27a9b503a: Introduce conditional steps in scaffolder templates. + + A step can now include an `if` property that only executes a step if the + condition is truthy. The condition can include handlebar templates. + + ```yaml + - id: register + if: '{{ not parameters.dryRun }}' + name: Register + action: catalog:register + input: + repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}' + catalogInfoPath: '/catalog-info.yaml' + ``` + + Also introduces a `not` helper in handlebar templates that allows to negate + boolean expressions. + +- 9b4010965: Provide a link to the template source on the `TemplateCard`. +- Updated dependencies [27a9b503a] +- Updated dependencies [f4e3ac5ce] +- Updated dependencies [7028ee1ca] +- Updated dependencies [70bc30c5b] +- Updated dependencies [eda9dbd5f] + - @backstage/catalog-model@0.8.2 + - @backstage/integration-react@0.1.3 + - @backstage/plugin-catalog-react@0.2.2 + - @backstage/catalog-client@0.3.13 + - @backstage/integration@0.5.6 + ## 0.9.7 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index dceb207ed1..a7541a5ddc 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "0.9.7", + "version": "0.9.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,14 +30,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.3.12", - "@backstage/catalog-model": "^0.8.1", + "@backstage/catalog-client": "^0.3.13", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/errors": "^0.1.1", "@backstage/core": "^0.7.12", - "@backstage/integration": "^0.5.5", - "@backstage/integration-react": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.2.1", + "@backstage/integration": "^0.5.6", + "@backstage/integration-react": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -61,7 +61,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index da49bd0726..395074f659 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,90 @@ # @backstage/plugin-search-backend-node +## 0.2.0 + +### Minor Changes + +- 5aff84759: This release represents a move out of a pre-alpha phase of the Backstage Search + plugin, into an alpha phase. With this release, you gain more control over the + layout of your search page on the frontend, as well as the ability to extend + search on the backend to encompass everything Backstage users may want to find. + + If you are updating to version `v0.4.0` of `@backstage/plugin-search` from a + prior release, you will need to make modifications to your app backend. + + First, navigate to your backend package and install the two related search + backend packages: + + ```sh + cd packages/backend + yarn add @backstage/plugin-search-backend @backstage/plugin-search-backend-node + ``` + + Wire up these new packages into your app backend by first creating a new + `search.ts` file at `src/plugins/search.ts` with contents like the following: + + ```typescript + import { useHotCleanup } from '@backstage/backend-common'; + import { createRouter } from '@backstage/plugin-search-backend'; + import { + IndexBuilder, + LunrSearchEngine, + } from '@backstage/plugin-search-backend-node'; + import { PluginEnvironment } from '../types'; + import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend'; + + export default async function createPlugin({ + logger, + discovery, + }: PluginEnvironment) { + // Initialize a connection to a search engine. + const searchEngine = new LunrSearchEngine({ logger }); + const indexBuilder = new IndexBuilder({ logger, searchEngine }); + + // Collators are responsible for gathering documents known to plugins. This + // particular collator gathers entities from the software catalog. + indexBuilder.addCollator({ + defaultRefreshIntervalSeconds: 600, + collator: new DefaultCatalogCollator({ discovery }), + }); + + // The scheduler controls when documents are gathered from collators and sent + // to the search engine for indexing. + const { scheduler } = await indexBuilder.build(); + + // A 3 second delay gives the backend server a chance to initialize before + // any collators are executed, which may attempt requests against the API. + setTimeout(() => scheduler.start(), 3000); + useHotCleanup(module, () => scheduler.stop()); + + return await createRouter({ + engine: indexBuilder.getSearchEngine(), + logger, + }); + } + ``` + + Then, ensure the search plugin you configured above is initialized by modifying + your backend's `index.ts` file in the following ways: + + ```diff + +import search from './plugins/search'; + // ... + +const searchEnv = useHotMemoize(module, () => createEnv('search')); + // ... + +apiRouter.use('/search', await search(searchEnv)); + // ... + ``` + +### Patch Changes + +- db1c8f93b: The ` set of components exported by the Search Plugin are now updated to use the Search Backend API. These will be made available as the default non-"next" versions in a follow-up release. + + The interfaces for decorators and collators in the Search Backend have also seen minor, breaking revisions ahead of a general release. If you happen to be building on top of these interfaces, check and update your implementations accordingly. The APIs will be considered more stable in a follow-up release. + +- Updated dependencies [db1c8f93b] + - @backstage/search-common@0.1.2 + ## 0.1.4 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 23234aca2f..3f0cf13f8f 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-node", - "version": "0.1.4", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -19,14 +19,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/search-common": "^0.1.1", + "@backstage/search-common": "^0.1.2", "winston": "^3.2.1", "lunr": "^2.3.9", "@types/lunr": "^2.3.3" }, "devDependencies": { - "@backstage/backend-common": "^0.8.0", - "@backstage/cli": "^0.6.11" + "@backstage/backend-common": "^0.8.2", + "@backstage/cli": "^0.7.0" }, "files": [ "dist" diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 9d34d92575..491a1da774 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,91 @@ # @backstage/plugin-search-backend +## 0.2.0 + +### Minor Changes + +- 5aff84759: This release represents a move out of a pre-alpha phase of the Backstage Search + plugin, into an alpha phase. With this release, you gain more control over the + layout of your search page on the frontend, as well as the ability to extend + search on the backend to encompass everything Backstage users may want to find. + + If you are updating to version `v0.4.0` of `@backstage/plugin-search` from a + prior release, you will need to make modifications to your app backend. + + First, navigate to your backend package and install the two related search + backend packages: + + ```sh + cd packages/backend + yarn add @backstage/plugin-search-backend @backstage/plugin-search-backend-node + ``` + + Wire up these new packages into your app backend by first creating a new + `search.ts` file at `src/plugins/search.ts` with contents like the following: + + ```typescript + import { useHotCleanup } from '@backstage/backend-common'; + import { createRouter } from '@backstage/plugin-search-backend'; + import { + IndexBuilder, + LunrSearchEngine, + } from '@backstage/plugin-search-backend-node'; + import { PluginEnvironment } from '../types'; + import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend'; + + export default async function createPlugin({ + logger, + discovery, + }: PluginEnvironment) { + // Initialize a connection to a search engine. + const searchEngine = new LunrSearchEngine({ logger }); + const indexBuilder = new IndexBuilder({ logger, searchEngine }); + + // Collators are responsible for gathering documents known to plugins. This + // particular collator gathers entities from the software catalog. + indexBuilder.addCollator({ + defaultRefreshIntervalSeconds: 600, + collator: new DefaultCatalogCollator({ discovery }), + }); + + // The scheduler controls when documents are gathered from collators and sent + // to the search engine for indexing. + const { scheduler } = await indexBuilder.build(); + + // A 3 second delay gives the backend server a chance to initialize before + // any collators are executed, which may attempt requests against the API. + setTimeout(() => scheduler.start(), 3000); + useHotCleanup(module, () => scheduler.stop()); + + return await createRouter({ + engine: indexBuilder.getSearchEngine(), + logger, + }); + } + ``` + + Then, ensure the search plugin you configured above is initialized by modifying + your backend's `index.ts` file in the following ways: + + ```diff + +import search from './plugins/search'; + // ... + +const searchEnv = useHotMemoize(module, () => createEnv('search')); + // ... + +apiRouter.use('/search', await search(searchEnv)); + // ... + ``` + +### Patch Changes + +- Updated dependencies [92963779b] +- Updated dependencies [db1c8f93b] +- Updated dependencies [5aff84759] +- Updated dependencies [eda9dbd5f] + - @backstage/backend-common@0.8.2 + - @backstage/search-common@0.1.2 + - @backstage/plugin-search-backend-node@0.2.0 + ## 0.1.5 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index c06f54a266..8b906ea9c2 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend", - "version": "0.1.5", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -19,9 +19,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", - "@backstage/search-common": "^0.1.1", - "@backstage/plugin-search-backend-node": "^0.1.3", + "@backstage/backend-common": "^0.8.2", + "@backstage/search-common": "^0.1.2", + "@backstage/plugin-search-backend-node": "^0.2.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -29,7 +29,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.11", + "@backstage/cli": "^0.7.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/search-backend/src/service/standaloneServer.ts b/plugins/search-backend/src/service/standaloneServer.ts index df42e3dda2..19ea40ccf7 100644 --- a/plugins/search-backend/src/service/standaloneServer.ts +++ b/plugins/search-backend/src/service/standaloneServer.ts @@ -44,9 +44,12 @@ export async function startStandaloneServer( logger, }); - const service = createServiceBuilder(module) - .enableCors({ origin: 'http://localhost:3000' }) + let service = createServiceBuilder(module) + .setPort(options.port) .addRouter('/search', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } return await service.start().catch(err => { logger.error(err); diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index c7a70d39a2..29320a1c79 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,137 @@ # @backstage/plugin-search +## 0.4.0 + +### Minor Changes + +- 5aff84759: This release represents a move out of a pre-alpha phase of the Backstage Search + plugin, into an alpha phase. With this release, you gain more control over the + layout of your search page on the frontend, as well as the ability to extend + search on the backend to encompass everything Backstage users may want to find. + + If you are updating to this version of `@backstage/plugin-search` from a prior + release, you will need to make the following modifications to your App: + + In your app package, create a new `searchPage` component at, for example, + `packages/app/src/components/search/SearchPage.tsx` with contents like the + following: + + ```tsx + import React from 'react'; + import { makeStyles, Theme, Grid, List, Paper } from '@material-ui/core'; + + import { Content, Header, Lifecycle, Page } from '@backstage/core'; + import { CatalogResultListItem } from '@backstage/plugin-catalog'; + import { + SearchBar, + SearchFilter, + SearchResult, + DefaultResultListItem, + } from '@backstage/plugin-search'; + + const useStyles = makeStyles((theme: Theme) => ({ + bar: { + padding: theme.spacing(1, 0), + }, + filters: { + padding: theme.spacing(2), + }, + filter: { + '& + &': { + marginTop: theme.spacing(2.5), + }, + }, + })); + + const SearchPage = () => { + const classes = useStyles(); + + return ( + +
} /> + + + + + + + + + + + + + + + + {({ results }) => ( + + {results.map(({ type, document }) => { + switch (type) { + case 'software-catalog': + return ( + + ); + default: + return ( + + ); + } + })} + + )} + + + + + + ); + }; + + export const searchPage = ; + ``` + + Then in `App.tsx`, import this new `searchPage` component, and set it as a + child of the existing `` route so that it looks like this: + + ```tsx + import { searchPage } from './components/search/SearchPage'; + // ... + }> + {searchPage} + ; + ``` + + You will also need to update your backend. For details, check the changeset for + `v0.2.0` of `@backstage/plugin-search-backend`. + +### Patch Changes + +- db1c8f93b: The ` set of components exported by the Search Plugin are now updated to use the Search Backend API. These will be made available as the default non-"next" versions in a follow-up release. + + The interfaces for decorators and collators in the Search Backend have also seen minor, breaking revisions ahead of a general release. If you happen to be building on top of these interfaces, check and update your implementations accordingly. The APIs will be considered more stable in a follow-up release. + +- Updated dependencies [27a9b503a] +- Updated dependencies [7028ee1ca] +- Updated dependencies [db1c8f93b] + - @backstage/catalog-model@0.8.2 + - @backstage/plugin-catalog-react@0.2.2 + - @backstage/search-common@0.1.2 + ## 0.3.7 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index a74091e497..9d6c81272c 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search", - "version": "0.3.7", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ }, "dependencies": { "@backstage/core": "^0.7.11", - "@backstage/catalog-model": "^0.8.0", - "@backstage/plugin-catalog-react": "^0.2.0", - "@backstage/search-common": "^0.1.1", + "@backstage/catalog-model": "^0.8.2", + "@backstage/plugin-catalog-react": "^0.2.2", + "@backstage/search-common": "^0.1.2", "@backstage/config": "^0.1.5", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", @@ -47,7 +47,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index b028963bc3..efaac81188 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -46,7 +46,7 @@ "timeago.js": "^4.0.2" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index c778cad93a..7614c2aedb 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -35,7 +35,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 0f4f800d57..2f986f7e53 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -32,8 +32,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/catalog-model": "^0.8.2", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/core": "^0.7.11", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", @@ -47,7 +47,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/techdocs/src/home/hooks/index.ts b/plugins/splunk-on-call/config.d.ts similarity index 72% rename from plugins/techdocs/src/home/hooks/index.ts rename to plugins/splunk-on-call/config.d.ts index 96419f5e7b..f2c0508f76 100644 --- a/plugins/techdocs/src/home/hooks/index.ts +++ b/plugins/splunk-on-call/config.d.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,5 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -export { useOwnUser } from './useOwnUser'; +export interface Config { + /** + * Splunk On Call Plugin specific configs + */ + splunkOnCall?: { + /** + * @visibility frontend + */ + eventsRestEndpoint?: string; + }; +} diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 22e4811f8b..740418e258 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.8.0", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.11", - "@backstage/plugin-catalog-react": "^0.2.0", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -45,7 +45,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", @@ -58,7 +58,9 @@ "msw": "^0.21.2", "node-fetch": "^2.6.1" }, + "configSchema": "config.d.ts", "files": [ - "dist" + "dist", + "config.d.ts" ] } diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 73134fb45d..82f749a03e 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -43,7 +43,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index a26af556f9..e6f7e00109 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.8.0", - "@backstage/catalog-model": "^0.8.0", + "@backstage/backend-common": "^0.8.2", + "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", "@backstage/errors": "^0.1.1", "@backstage/techdocs-common": "^0.6.3", @@ -45,7 +45,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.6.13", + "@backstage/cli": "^0.7.0", "@types/dockerode": "^3.2.1", "supertest": "^6.1.3" }, diff --git a/plugins/techdocs-backend/src/service/standaloneServer.ts b/plugins/techdocs-backend/src/service/standaloneServer.ts index af03987870..09379f4296 100644 --- a/plugins/techdocs-backend/src/service/standaloneServer.ts +++ b/plugins/techdocs-backend/src/service/standaloneServer.ts @@ -88,9 +88,12 @@ export async function startStandaloneServer( config, discovery, }); - const service = createServiceBuilder(module) - .enableCors({ origin: 'http://localhost:3000' }) + let service = createServiceBuilder(module) + .setPort(options.port) .addRouter('/techdocs', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } return await service.start().catch(err => { logger.error(err); process.exit(1); diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 747c44488d..76bcfd8b0d 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -32,11 +32,11 @@ }, "dependencies": { "@backstage/config": "^0.1.5", - "@backstage/catalog-model": "^0.8.1", + "@backstage/catalog-model": "^0.8.2", "@backstage/core": "^0.7.12", - "@backstage/integration": "^0.5.5", - "@backstage/integration-react": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.2.1", + "@backstage/integration": "^0.5.6", + "@backstage/integration-react": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.2.2", "@backstage/theme": "^0.2.8", "@backstage/errors": "^0.1.1", "@material-ui/core": "^4.11.0", @@ -51,7 +51,7 @@ "sanitize-html": "^2.3.2" }, "devDependencies": { - "@backstage/cli": "^0.6.14", + "@backstage/cli": "^0.7.0", "@backstage/dev-utils": "^0.1.17", "@backstage/test-utils": "^0.1.13", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/techdocs/src/home/components/DocsTable.tsx b/plugins/techdocs/src/home/components/DocsTable.tsx index e62435fbe9..e964a9cf00 100644 --- a/plugins/techdocs/src/home/components/DocsTable.tsx +++ b/plugins/techdocs/src/home/components/DocsTable.tsx @@ -111,7 +111,6 @@ export const DocsTable = ({ action={