diff --git a/.changeset/1724.md b/.changeset/1724.md deleted file mode 100644 index 2ac03f94e9..0000000000 --- a/.changeset/1724.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -'@backstage/cli': minor -'@backstage/plugin-api-docs': minor -'@backstage/plugin-app-backend': minor -'@backstage/plugin-auth-backend': minor -'@backstage/plugin-catalog-graphql': minor -'@backstage/plugin-catalog': minor -'@backstage/plugin-circleci': minor -'@backstage/plugin-explore': minor -'@backstage/plugin-gcp-projects': minor -'@backstage/plugin-github-actions': minor -'@backstage/plugin-gitops-profiles': minor -'@backstage/plugin-graphiql': minor -'@backstage/plugin-jenkins': minor -'@backstage/plugin-kubernetes': minor -'@backstage/plugin-lighthouse': minor -'@backstage/plugin-newrelic': minor -'@backstage/plugin-register-component': minor -'@backstage/plugin-rollbar': minor -'@backstage/plugin-scaffolder': minor -'@backstage/plugin-sentry': minor -'@backstage/plugin-tech-radar': minor -'@backstage/plugin-techdocs': minor -'@backstage/plugin-welcome': minor ---- - -Create backend plugin through CLI diff --git a/.changeset/2284.md b/.changeset/2284.md deleted file mode 100644 index 655cc5a3e8..0000000000 --- a/.changeset/2284.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/core-api': minor -'@backstage/core': minor -'@backstage/plugin-auth-backend': minor ---- - -Add SAML login to backstage - -![](https://user-images.githubusercontent.com/872486/92251660-bb9e3400-eeff-11ea-86fe-1f2a0262cd31.png) - -![](https://user-images.githubusercontent.com/872486/93851658-1a76f200-fce3-11ea-990b-26ca1a327a15.png) diff --git a/.changeset/2515.md b/.changeset/2515.md deleted file mode 100644 index 32f5edd6b7..0000000000 --- a/.changeset/2515.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cloudbuild': minor ---- - -Releasing Google Cloud Build Plugin diff --git a/.changeset/2532.md b/.changeset/2532.md deleted file mode 100644 index 14307f6c08..0000000000 --- a/.changeset/2532.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': minor ---- - -Add handling and docs for entity references diff --git a/.changeset/2535.md b/.changeset/2535.md deleted file mode 100644 index bd28f3ce03..0000000000 --- a/.changeset/2535.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@backstage/core': patch -'@backstage/theme': patch ---- - -Fix banner position and color - -This PR closes: #2245 - -The "fixed" props added to control the position of the banner. When it is set to true the banner will be shown in bottom of that page and the width will be based on the content of the message. - -![](https://user-images.githubusercontent.com/15106494/93765685-999df480-fc15-11ea-8fa5-11cac5836cf1.png) - -![](https://user-images.githubusercontent.com/15106494/93765697-9e62a880-fc15-11ea-92af-b6a7fee4bb21.png) diff --git a/.changeset/2541.md b/.changeset/2541.md deleted file mode 100644 index 1ba29da040..0000000000 --- a/.changeset/2541.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/theme': minor ---- - -Tweak dark mode colors diff --git a/.changeset/2543.md b/.changeset/2543.md deleted file mode 100644 index 00311ade45..0000000000 --- a/.changeset/2543.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': minor ---- - -Add Azure DevOps support to the scaffolder backend - -This adds support for Azure DevOps to the scaffolder (preparer & publisher). I thought I should get this in there now since #2426 has been merged. I had a previous PR with only the preparer but I closed that in favor of this one. - -I stayed with the 'azure/api' structure but I guess we should try and go the same way as with GitHub here #2501 diff --git a/.changeset/2562.md b/.changeset/2562.md deleted file mode 100644 index 716f370ad9..0000000000 --- a/.changeset/2562.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/create-app': minor -'@backstage/plugin-auth-backend': minor -'@backstage/plugin-techdocs-backend': minor ---- - -Change the default backend plugin mount point to /api diff --git a/.changeset/2563.md b/.changeset/2563.md deleted file mode 100644 index 318d5cf5ef..0000000000 --- a/.changeset/2563.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-actions': minor ---- - -Adds a widget to show recent git workflow runs to the github actions plugin. The default setting is the last 5 runs across all branches but both branch and the number of runs are configurable. diff --git a/.changeset/2565.md b/.changeset/2565.md deleted file mode 100644 index 92253101ee..0000000000 --- a/.changeset/2565.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -'@backstage/core-api': patch ---- - -Add initial RouteRefRegistry - -Starting out some work to bring routing back and working as part of the work towards finalizing #1536 - -This is some of the groundwork of an experiment we're working on to enable routing via RouteRefs, while letting the app itself look something like this: - -```jsx -const App = () => ( - - - - {' '} - // catalogRouteRef - - - - - - - // statusRouteRef - - - - - - - - - - // sentryRouteRef - - - - - - - - - - - - - - - -); -``` - -As part of inverting the composition of the app, route refs and routing in general was somewhat broken, intentionally. Right now it's not really possible to easily route to different parts of the app from a plugin, or even different parts of the plugin that are not within the same router. - -The core part of the experiment is to construct a map of ApiRef[] -> path overrides. Each key in the map is the list of route refs to traversed to reach a leaf in the routing tree, and the value is the path override at that point. For example, the above tree would add entries like [techDocsRouteRef] -> '/docs', and [entityRouteRef, apiDocsRouteRef] -> '/api'. By mapping out the entire app in this structure, the idea is that we can navigate to any point in the app using RouteRefs. - -The RouteRefRegistry is an implementation of such a map, and the idea is to add it in master to make it a bit easier to experiment and iterate. This is not an exposed API at this point. - -We've explored a couple of alternatives for how to enable routing, but it's boiled down to either a solution centred around the route map mentioned above, or treating all routes as static and globally unique, with no room for flexibility, customization or conflicts between different plugins. We're starting out pursuing this options 😁. We also expect that a the app-wide routing table will make things like dynamic loading a lot cleaner, as there would be a much more clear handoff between the main chunk and dynamic chunks. diff --git a/.changeset/2575.md b/.changeset/2575.md deleted file mode 100644 index b08f50ed13..0000000000 --- a/.changeset/2575.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': minor ---- - -Fix dense in Structured Metadata Table diff --git a/.changeset/2586.md b/.changeset/2586.md deleted file mode 100644 index 568adb8a3e..0000000000 --- a/.changeset/2586.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/catalog-model': minor -'@backstage/plugin-catalog-backend': minor ---- - -Entirely case insensitive read path of entities diff --git a/.changeset/2587.md b/.changeset/2587.md deleted file mode 100644 index 910de1ca04..0000000000 --- a/.changeset/2587.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/catalog-model': minor ---- - -Add the User & Group entities - -A user describes a person, such as an employee, a contractor, or similar. Users belong to Group entities in the catalog. - -A group describes an organizational entity, such as for example a team, a business unit, or a loose collection of people in an interest group. Members of these groups are modeled in the catalog as kind User. diff --git a/.changeset/2597.md b/.changeset/2597.md deleted file mode 100644 index 9db25e8d0e..0000000000 --- a/.changeset/2597.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/catalog-model': minor -'@backstage/plugin-catalog-backend': minor ---- - -Add ApiDefinitionAtLocationProcessor that allows to load a API definition from another location diff --git a/.changeset/2598.md b/.changeset/2598.md deleted file mode 100644 index 03e10e7db8..0000000000 --- a/.changeset/2598.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/plugin-techdocs': minor ---- - -Add a message if techdocs takes long time to load - -Fixes #2416. - -The UI after the change should look like this: - -![techdocs-progress-bar](https://user-images.githubusercontent.com/33940798/94189286-296ac980-fec8-11ea-9051-1b3db938d12f.gif) diff --git a/.changeset/2600.md b/.changeset/2600.md deleted file mode 100644 index 6fc9775fa1..0000000000 --- a/.changeset/2600.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': minor -'@backstage/plugin-proxy-backend': minor -'@backstage/plugin-auth-backend': minor -'@backstage/create-app': minor -'@backstage/backend-common': minor ---- - -Add service discovery interface and implement for single host deployments - -Fixes #1847, #2596 - -Went with an interface similar to the frontend DiscoveryApi, since it's dead simple but still provides a lot of flexibility in the implementation. - -Also ended up with two different methods, one for internal endpoint discovery and one for external. The two use-cases are explained a bit more in the docs, but basically it's service-to-service vs callback URLs. - -This did get me thinking about uniqueness and that we're heading towards a global namespace for backend plugin IDs. That's probably fine, but if we're happy with that we should leverage it a bit more to simplify the backend setup. For example we'd have each plugin provide its own ID and not manually mount on paths in the backend. - -Draft until we're happy with the implementation, then I can add more docs and changelog entry. Also didn't go on a thorough hunt for places where discovery can be used, but I don't think there are many since it's been pretty awkward to do service-to-service communication. diff --git a/.changeset/2603.md b/.changeset/2603.md deleted file mode 100644 index c24d2ea033..0000000000 --- a/.changeset/2603.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/backend-common': minor -'@backstage/create-app': minor ---- - -Make CSP configurable to fix app-backend served app not being able to fetch - -See discussion [here on discord](https://discordapp.com/channels/687207715902193673/687235481154617364/758721460163575850) diff --git a/.changeset/2606.md b/.changeset/2606.md deleted file mode 100644 index f6059e7705..0000000000 --- a/.changeset/2606.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -Move auth provider router creation to router diff --git a/.changeset/2609.md b/.changeset/2609.md deleted file mode 100644 index 6bb8ab7a40..0000000000 --- a/.changeset/2609.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Sync scaffolded backend with example diff --git a/.changeset/2610.md b/.changeset/2610.md deleted file mode 100644 index 92ec8dcc0c..0000000000 --- a/.changeset/2610.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-circleci': minor ---- - -Refactor to use DiscoveryApi diff --git a/.changeset/2611.md b/.changeset/2611.md deleted file mode 100644 index cbf3129038..0000000000 --- a/.changeset/2611.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Remove discovery api override diff --git a/.changeset/2612.md b/.changeset/2612.md deleted file mode 100644 index bf093d8f77..0000000000 --- a/.changeset/2612.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-jenkins': patch ---- - -Refactor to use DiscoveryApi diff --git a/.changeset/2613.md b/.changeset/2613.md deleted file mode 100644 index cf8c1a155a..0000000000 --- a/.changeset/2613.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/plugin-auth-backend': minor ---- - -Initial implementation of catalog user lookup - -This adds a basic catalog client + method for the Google provider to look up users in the catalog. It expects to find a single user entity in the catalog with a google.com/email annotation that matches the email of the Google profile. - -Right now it falls back to the old behavior of splitting the email, since I don't wanna break the sign-in flow for existing apps, not yet anyway x). - -- Added "@backstage/catalog-model@^0.1.1-alpha.23" as a dependency -- Added "node-fetch@^2.6.1" as a dependency diff --git a/.changeset/2614.md b/.changeset/2614.md deleted file mode 100644 index 7e2660bc80..0000000000 --- a/.changeset/2614.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': minor ---- - -Default to using internal scope for new plugins diff --git a/.changeset/2615.md b/.changeset/2615.md deleted file mode 100644 index 412b8127c4..0000000000 --- a/.changeset/2615.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': minor ---- - -Use localhost to fall back to IPv4 if IPv6 isn't available diff --git a/.changeset/2616.md b/.changeset/2616.md deleted file mode 100644 index 9a70c0e79f..0000000000 --- a/.changeset/2616.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/create-app': minor ---- - -Remove identity-backend - -Not used, and we're heading down the route of identities in the catalog diff --git a/.changeset/2623.md b/.changeset/2623.md deleted file mode 100644 index abd5ce7a4c..0000000000 --- a/.changeset/2623.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-catalog': minor ---- - -Created EntityNotFound component for catalog which displays the 404 page when entity is not found. - -Fixes #2266 diff --git a/.changeset/2624.md b/.changeset/2624.md deleted file mode 100644 index dcfc800713..0000000000 --- a/.changeset/2624.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Make title meaningful after component creation - -Fixes #2458. - -After the change, the UX should look like this: - -### If the component creation was successful: - -![successfully-created-component](https://user-images.githubusercontent.com/33940798/94339294-8bd1e000-0016-11eb-885b-7936fcc23b63.gif) - -### If the component creation failed: - -![failed-to-create-component](https://user-images.githubusercontent.com/33940798/94339296-90969400-0016-11eb-9a74-ce16b3dd8d88.gif) diff --git a/.changeset/2625-catalog-backend.md b/.changeset/2625-catalog-backend.md deleted file mode 100644 index bcd49dddb2..0000000000 --- a/.changeset/2625-catalog-backend.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Add codeowners processor - -- Add `codeowners-utils@^1.0.2` as a dependency -- Add `core-js@^3.6.5` as a dependency -- Added new CodeOwnersProcessor diff --git a/.changeset/2625-cli.md b/.changeset/2625-cli.md deleted file mode 100644 index c5a5437b69..0000000000 --- a/.changeset/2625-cli.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Add codeowners processor - -- Include ESNext.Promise in TypeScript compilation diff --git a/.changeset/2628.md b/.changeset/2628.md deleted file mode 100644 index 0ac36d456a..0000000000 --- a/.changeset/2628.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -This feature works the same as \$secret does in config - it allows programmatic substitution of values into a document. - -This is particularly useful e.g. for API type entities where you do not want to repeat your entire API spec document inside the catalog-info.yaml file. For those cases, you can instead do something like - -``` -apiVersion: backstage.io/v1alpha1 -kind: API -metadata: - name: my-federated-service -spec: - type: graphql - definition: - $text: ./schema.graphql -``` - -The textual content of that file will be injected as the value of definition, during each refresh loop. Both relative and absolute paths are supported, as well as any HTTP/HTTPS URL pointing to a service that returns the relevant data. - -The initial version supports injection of text file data, and structured data from JSON and YAML files. You can add any handler of your own in addition to these. diff --git a/.changeset/2630.md b/.changeset/2630.md deleted file mode 100644 index 933204e292..0000000000 --- a/.changeset/2630.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/create-app': minor -'@backstage/plugin-catalog-backend': minor ---- - -Allow node v14 and add to master build matrix - -- Upgrade sqlite3@^5.0.0 in @backstage/plugin-catalog-backend -- Add Node 14 to engines in @backstage/create-app diff --git a/.changeset/2637.md b/.changeset/2637.md deleted file mode 100644 index 9d368634b6..0000000000 --- a/.changeset/2637.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@backstage/plugin-cost-insights': minor -'@backstage/plugin-explore': minor ---- - -This PR adds Spotify's Cost Insights Tool. Cost Insights explains costs from cloud services in an understandable way, using software terms familiar to your engineers. This tool helps you and your team make trade-offs between cost optimization efforts and your other priorities. - -Cost Insights features: - -Daily cost graph by team or billing account -Cost comparison against configurable business metrics -Insights panels for configurable cloud products your company uses -Cost alerts and recommendations -Selectable time periods for month over month, or quarter over quarter cost comparison -Conversion of cost growth into average engineer cost (configurable) to help optimization trade-off decisions - -![plugin-cost-insights](https://user-images.githubusercontent.com/3030003/94430416-e166d380-0161-11eb-891c-9ce10187683e.gif) - -This PR adds the Cost Insights frontend React plugin with a defined CostInsightsApi. We include an example client with static data in the expected format. This API should talk with a cloud billing backend that aggregates billing data from your cloud provider. - -Fixes #688 💵 diff --git a/.changeset/2639.md b/.changeset/2639.md deleted file mode 100644 index e6a623088e..0000000000 --- a/.changeset/2639.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': minor ---- - -Upgrade dependency `esbuild@0.7.7` diff --git a/.changeset/2641.md b/.changeset/2641.md deleted file mode 100644 index 3b06358e81..0000000000 --- a/.changeset/2641.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Simplify the read function in processors diff --git a/.changeset/2656.md b/.changeset/2656.md deleted file mode 100644 index e253b6b1f6..0000000000 --- a/.changeset/2656.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': minor ---- - -Lookup user in Google Auth Provider diff --git a/.changeset/2657.md b/.changeset/2657.md deleted file mode 100644 index 9aa645d65f..0000000000 --- a/.changeset/2657.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': minor ---- - -Added EmptyState component diff --git a/.changeset/2660.md b/.changeset/2660.md deleted file mode 100644 index 758d523f07..0000000000 --- a/.changeset/2660.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Resolve some dark mode styling issues in asyncAPI specs diff --git a/.changeset/2661.md b/.changeset/2661.md deleted file mode 100644 index e73b0abf26..0000000000 --- a/.changeset/2661.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Fixed banner component position in DismissableBanner component diff --git a/.changeset/2669-catalog-backend.md b/.changeset/2669-catalog-backend.md deleted file mode 100644 index 32ee5c0f4d..0000000000 --- a/.changeset/2669-catalog-backend.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Add the ability to import users from GitHub Organization into the catalog. - -The token needs to have the scopes `user:email`, `read:user`, and `read:org`. diff --git a/.changeset/2669-catalog-model.md b/.changeset/2669-catalog-model.md deleted file mode 100644 index b9a2841a1b..0000000000 --- a/.changeset/2669-catalog-model.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': minor ---- - -Add the ability to import users from GitHub Organization into the catalog. diff --git a/.changeset/2669-create-app.md b/.changeset/2669-create-app.md deleted file mode 100644 index e7075ffeb8..0000000000 --- a/.changeset/2669-create-app.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/create-app': minor ---- - -Add the ability to import users from GitHub Organization into the catalog. - -The token needs to have the scopes `user:email`, `read:user`, and `read:org`. diff --git a/.changeset/2674.md b/.changeset/2674.md deleted file mode 100644 index 15a7a0e849..0000000000 --- a/.changeset/2674.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/backend-common': minor -'@backstage/create-app': minor ---- - -Auto-create plugin databases - -Relates to #1598. - -This creates databases for plugins before handing off control to plugins. - -The list of plugins currently need to be hard-coded depending on the installed plugins. A later PR will properly refactor the code to provide a factory pattern where plugins specify what they need, and Knex instances will be provided based on the input. diff --git a/.changeset/2686.md b/.changeset/2686.md deleted file mode 100644 index 8831c1309b..0000000000 --- a/.changeset/2686.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Update SSR template to pass CI diff --git a/.changeset/2689.md b/.changeset/2689.md deleted file mode 100644 index be75dd261b..0000000000 --- a/.changeset/2689.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Upgrade dependency rollup-plugin-typescript2 to ^0.27.3 diff --git a/.changeset/2722.md b/.changeset/2722.md deleted file mode 100644 index 69642b5797..0000000000 --- a/.changeset/2722.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/plugin-api-docs': minor ---- - -There were some missing features and markdown was not rendered properly, but this is fixed now. - -Details: - -- [`asyncapi/asyncapi-react#149`](https://github.com/asyncapi/asyncapi-react/pull/149) - fix: improve markdown rendering of nested fields -- [`asyncapi/asyncapi-react#150`](https://github.com/asyncapi/asyncapi-react/pull/150) - feat: display the description of channels and operations -- [`asyncapi/asyncapi-react#153`](https://github.com/asyncapi/asyncapi-react/pull/153) - fix: let the list of `enums` break into multiple lines diff --git a/.changeset/2798.md b/.changeset/2798.md deleted file mode 100644 index 2b202142ef..0000000000 --- a/.changeset/2798.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Use the new `UrlReader` in `PlaceholderProcessor`. -This allows to use the placeholder processor to include API definitions in API entities. -Previously it was only possible to do this if the definition comes from the same location type as the entity itself. diff --git a/.changeset/2800.md b/.changeset/2800.md deleted file mode 100644 index 0e051b0557..0000000000 --- a/.changeset/2800.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@backstage/core': minor -'@backstage/core-api': minor ---- - -Updated the `GithubAuth.create` method to configure the default scope of the Github Auth Api. As a result the -default scope is configurable when overwriting the Core Api in the app. - -``` -GithubAuth.create({ - discoveryApi, - oauthRequestApi, - defaultScopes: ['read:user', 'repo'], -}), -``` diff --git a/.changeset/2803.md b/.changeset/2803.md deleted file mode 100644 index 3a4773757f..0000000000 --- a/.changeset/2803.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Remove the backstage.io/definition-at-location annotation. -The annotation was superseded by the placeholder processor. - -```yaml -apiVersion: backstage.io/v1alpha1 -kind: API -metadata: - name: spotify - description: The Spotify web API - tags: - - spotify - - rest - annotations: - # Don't use this annotation, but the placeholder $text instead (see below). - backstage.io/definition-at-location: 'url:https://raw.githubusercontent.com/APIs-guru/openapi-directory/master/APIs/spotify.com/v1/swagger.yaml' -spec: - type: openapi - lifecycle: production - owner: spotify@example.com - definition: - $text: https://raw.githubusercontent.com/APIs-guru/openapi-directory/master/APIs/spotify.com/v1/swagger.yaml -``` diff --git a/.changeset/2804.md b/.changeset/2804.md deleted file mode 100644 index 5223a24791..0000000000 --- a/.changeset/2804.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@backstage/plugin-proxy-backend': minor ---- - -Limit the http headers that are forwarded from the request to a safe set of defaults. -A user can configure additional headers that should be forwarded if the specific applications needs that. - -```yaml -proxy: - '/my-api': - target: 'https://my-api.com/get' - allowedHeaders: - # We need to forward the Authorization header that was provided by the caller - - Authorization -``` diff --git a/.changeset/2826.md b/.changeset/2826.md deleted file mode 100644 index fb2dbb6877..0000000000 --- a/.changeset/2826.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'example-app': minor -'@backstage/core': minor -'@backstage/create-app': minor -'@backstage/plugin-catalog': minor -'@backstage/plugin-github-actions': minor -'@backstage/plugin-jenkins': minor -'@backstage/plugin-lighthouse': minor ---- - -The InfoCard variant `'height100'` is deprecated. Use variant `'gridItem'` instead. - -When the InfoCard is displayed as a grid item within a grid, you may want items to have the same height for all items. -Set to the `'gridItem'` variant to display the InfoCard with full height suitable for Grid: -`...` - -Changed the InfoCards in '@backstage/plugin-github-actions', '@backstage/plugin-jenkins', '@backstage/plugin-lighthouse' -to pass an optional variant to the corresponding card of the plugin. - -As a result the overview content of the EntityPage shows cards with full height suitable for Grid. diff --git a/.changeset/2863.md b/.changeset/2863.md new file mode 100644 index 0000000000..729e3aab7b --- /dev/null +++ b/.changeset/2863.md @@ -0,0 +1,29 @@ +--- +'@backstage/core-api': patch +--- + +Updated the AuthApi `.create` methods to configure the default scope of the corresponding Auth Api. As a result the +default scope is configurable when overwriting the Core Api in the app. + +``` +GithubAuth.create({ + discoveryApi, + oauthRequestApi, + defaultScopes: ['read:user', 'repo'], +}), +``` + +Replaced redundant CreateOptions of each Auth Api with the OAuthApiCreateOptions type. + +``` +export type OAuthApiCreateOptions = AuthApiCreateOptions & { + oauthRequestApi: OAuthRequestApi; + defaultScopes?: string[]; +}; + +export type AuthApiCreateOptions = { + discoveryApi: DiscoveryApi; + environment?: string; + provider?: AuthProvider & { id: string }; +}; +``` diff --git a/.changeset/2874.md b/.changeset/2874.md deleted file mode 100644 index 693962314f..0000000000 --- a/.changeset/2874.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -The way that wiring together a catalog happens, has changed drastically. Now -there is a new class `CatalogBuilder` that does almost all of the heavy lifting -of how to augment/replace pieces of catalog functionality, such as adding -support for custom entities or adding additional processors. - -As the builder was added, a lot of the static methods and builders for default -setups have been removed from classes deep in the hierarchy. Instead, the -builder contains the knowledge of what the defaults are. diff --git a/.changeset/3030.md b/.changeset/3030.md deleted file mode 100644 index 89730dc14c..0000000000 --- a/.changeset/3030.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': minor ---- - -Add the ability to import components from Bitbucket Server to the service catalog diff --git a/.changeset/3066.md b/.changeset/3066.md deleted file mode 100644 index 7bb67e70d1..0000000000 --- a/.changeset/3066.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Filters passed to the `/entities` endpoint of the catalog has changed format. - -The old way was to pass things on the form `?a=b&c=d`; the new way is to pass -things on the form `?filter=a=b,c=d`. See discussion in -[#2910](https://github.com/spotify/backstage/issues/2910) for details. - -The comma separated items within a single filter have an AND between them. If -multiple such filters are passed, they have an OR between those item groups. diff --git a/.changeset/3113.md b/.changeset/3113.md deleted file mode 100644 index 7c53d01c16..0000000000 --- a/.changeset/3113.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/catalog-model': minor -'@backstage/plugin-catalog-backend': minor ---- - -Changes the various kind policies into a new type `KindValidator`. - -Adds `CatalogProcessor#validateEntityKind` that makes use of the above -validators. This moves entity schema validity checking away from entity -policies and into processors, centralizing the extension points into the -processor chain. diff --git a/.changeset/3130.md b/.changeset/3130.md deleted file mode 100644 index 6edac9372b..0000000000 --- a/.changeset/3130.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Fix `CatalogBuilder#addProcessor`. diff --git a/.changeset/3157.md b/.changeset/3157.md new file mode 100644 index 0000000000..f15d05c46a --- /dev/null +++ b/.changeset/3157.md @@ -0,0 +1,16 @@ +--- +'@backstage/core': patch +--- + +Adds the MarkdownContent component to render and display Markdown content with the default +[GFM](https://github.github.com/gfm/) (Github flavored Markdown) dialect. + +``` + +``` + +To render the Markdown content with plain [CommonMark](https://commonmark.org/), set the dialect to `common-mark` + +``` +` flags, only those files will be loaded, **NOT** the default `app-config.yaml` one. - -The old behaviour of for example `APP_ENV=development` can be replicated using the following flags: - -```bash ---config ../../app-config.yaml --config ../../app-config.development.yaml -``` diff --git a/.changeset/eighty-lamps-smell.md b/.changeset/eighty-lamps-smell.md deleted file mode 100644 index 85dfba4f82..0000000000 --- a/.changeset/eighty-lamps-smell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -handle the case where no entities are available to show diff --git a/.changeset/eighty-stingrays-type.md b/.changeset/eighty-stingrays-type.md deleted file mode 100644 index 731c401b77..0000000000 --- a/.changeset/eighty-stingrays-type.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Add forwardRef to the SidebarItem diff --git a/.changeset/flat-bugs-do.md b/.changeset/flat-bugs-do.md deleted file mode 100644 index 672daf657d..0000000000 --- a/.changeset/flat-bugs-do.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/core': patch -'@backstage/plugin-graphiql': patch -'@backstage/plugin-tech-radar': patch -'@backstage/plugin-techdocs': patch ---- - -add test case for Progress component diff --git a/.changeset/flat-yaks-march.md b/.changeset/flat-yaks-march.md deleted file mode 100644 index 6b26206eb8..0000000000 --- a/.changeset/flat-yaks-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -fix the accordion details design when job stage fail diff --git a/.changeset/fresh-maps-complain.md b/.changeset/fresh-maps-complain.md deleted file mode 100644 index ef2021df37..0000000000 --- a/.changeset/fresh-maps-complain.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-catalog': minor -'@backstage/plugin-register-component': patch ---- - -Locations registered through the catalog client now default to the 'url' type. The type selection dropdown in the register-component form has been removed. diff --git a/.changeset/funny-readers-breathe.md b/.changeset/funny-readers-breathe.md deleted file mode 100644 index 8897b24cf6..0000000000 --- a/.changeset/funny-readers-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -fix the warning of all the core components test cases diff --git a/.changeset/fuzzy-falcons-happen.md b/.changeset/fuzzy-falcons-happen.md deleted file mode 100644 index 461ac195d9..0000000000 --- a/.changeset/fuzzy-falcons-happen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'e2e-test': minor ---- - -Converted into a CLI, use `yarn e2e-test run` to run diff --git a/.changeset/good-islands-cheer.md b/.changeset/good-islands-cheer.md deleted file mode 100644 index 2e7109b312..0000000000 --- a/.changeset/good-islands-cheer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': minor ---- - -Enable custom alert types in Cost Insights diff --git a/.changeset/great-apples-flash.md b/.changeset/great-apples-flash.md deleted file mode 100644 index 78ad89dee0..0000000000 --- a/.changeset/great-apples-flash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Fix CodeOwnersProcessor to handle non team users diff --git a/.changeset/happy-ads-behave.md b/.changeset/happy-ads-behave.md deleted file mode 100644 index f8b889f85c..0000000000 --- a/.changeset/happy-ads-behave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Allow templates to be located on non-default branch diff --git a/.changeset/heavy-berries-hear.md b/.changeset/heavy-berries-hear.md deleted file mode 100644 index 66aa6d93e1..0000000000 --- a/.changeset/heavy-berries-hear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Update ItemCard headers to pass color contrast standards. diff --git a/.changeset/hungry-parrots-work.md b/.changeset/hungry-parrots-work.md deleted file mode 100644 index a18218b542..0000000000 --- a/.changeset/hungry-parrots-work.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -rename stories folder top Chip diff --git a/.changeset/little-wasps-pull.md b/.changeset/little-wasps-pull.md deleted file mode 100644 index 732c7506b0..0000000000 --- a/.changeset/little-wasps-pull.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Remove "in default" in component name diff --git a/.changeset/long-ways-count.md b/.changeset/long-ways-count.md deleted file mode 100644 index e04c1225cc..0000000000 --- a/.changeset/long-ways-count.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': minor -'@backstage/create-app': patch ---- - -Updated naming of environment variables. New pattern [NAME]\_TOKEN for Github, Gitlab, Azure & Github enterprise access tokens. - -### Detail: - -- Previously we have to export same token for both, catalog & scaffolder - -```bash -export GITHUB_ACCESS_TOKEN=foo -export GITHUB_PRIVATE_TOKEN=foo -``` - -with latest changes, only single export is sufficient. - -```bash -export GITHUB_TOKEN=foo -export GITLAB_TOKEN=foo -export GHE_TOKEN=foo -export AZURE_TOKEN=foo -``` - -### list: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Old nameNew name
GITHUB_ACCESS_TOKENGITHUB_TOKEN
GITHUB_PRIVATE_TOKENGITHUB_TOKEN
GITLAB_ACCESS_TOKENGITLAB_TOKEN
GITLAB_PRIVATE_TOKENGITLAB_TOKEN
AZURE_PRIVATE_TOKENAZURE_TOKEN
GHE_PRIVATE_TOKENGHE_TOKEN
diff --git a/.changeset/loud-lamps-visit.md b/.changeset/loud-lamps-visit.md deleted file mode 100644 index 9023061643..0000000000 --- a/.changeset/loud-lamps-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Including source maps with all packages diff --git a/.changeset/lovely-suits-flash.md b/.changeset/lovely-suits-flash.md deleted file mode 100644 index f093290c85..0000000000 --- a/.changeset/lovely-suits-flash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -update the test cases of CodeSnippet component diff --git a/.changeset/lucky-lemons-return.md b/.changeset/lucky-lemons-return.md new file mode 100644 index 0000000000..49125d31d4 --- /dev/null +++ b/.changeset/lucky-lemons-return.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Fix missing api-docs plugin registration in app template diff --git a/.changeset/metal-fishes-learn.md b/.changeset/metal-fishes-learn.md deleted file mode 100644 index d22af83ca0..0000000000 --- a/.changeset/metal-fishes-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': minor ---- - -The default mount point for backend plugins have been changed to /api. These changes are done in the backend package itself, so it is recommended that you sync up existing backend packages with this new pattern. diff --git a/.changeset/mighty-starfishes-taste.md b/.changeset/mighty-starfishes-taste.md deleted file mode 100644 index eb43ce69b8..0000000000 --- a/.changeset/mighty-starfishes-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Removed the parseData step from catalog processors. Locations readers should emit full entities instead. diff --git a/.changeset/moody-pugs-smoke.md b/.changeset/moody-pugs-smoke.md new file mode 100644 index 0000000000..3092ec4bfe --- /dev/null +++ b/.changeset/moody-pugs-smoke.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings': patch +--- + +Export `AuthProviders`, `DefaultProviderSettings` and `ProviderSettingsItem`. diff --git a/.changeset/nervous-drinks-notice.md b/.changeset/nervous-drinks-notice.md deleted file mode 100644 index 7c6af21f64..0000000000 --- a/.changeset/nervous-drinks-notice.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-catalog': minor -'@backstage/plugin-register-component': minor ---- - -Add a validate button to the register-component page - -This allows the user to validate his location before adding it. diff --git a/.changeset/new-url-reader.md b/.changeset/new-url-reader.md deleted file mode 100644 index 94758c5bc1..0000000000 --- a/.changeset/new-url-reader.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Added new UrlReader interface for reading opaque data from URLs with different providers. - -This new URL reading system is intended as a replacement for the various integrations towards -external systems in the catalog, scaffolder, and techdocs. It is configured via a new top-level -config section called 'integrations'. - -Along with the UrlReader interface is a new UrlReaders class, which exposes static factory -methods for instantiating readers that can read from many different integrations simultaneously. diff --git a/.changeset/nice-candles-argue.md b/.changeset/nice-candles-argue.md deleted file mode 100644 index 971000410a..0000000000 --- a/.changeset/nice-candles-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-user-settings': minor ---- - -Add settings button to sidebar diff --git a/.changeset/ninety-ads-dance.md b/.changeset/ninety-ads-dance.md deleted file mode 100644 index a03298fd7f..0000000000 --- a/.changeset/ninety-ads-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': patch ---- - -Fix documentation and validation message for tags diff --git a/.changeset/ninety-pens-poke.md b/.changeset/ninety-pens-poke.md deleted file mode 100644 index 94bcb06749..0000000000 --- a/.changeset/ninety-pens-poke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Fix for configured templates using 'url' locations even though it's not supported yet diff --git a/.changeset/old-eagles-admire.md b/.changeset/old-eagles-admire.md deleted file mode 100644 index 0729b6439d..0000000000 --- a/.changeset/old-eagles-admire.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-common': minor -'@backstage/cli': minor ---- - -Use APP_ENV before NODE_ENV for determining what config to load diff --git a/.changeset/old-falcons-jump.md b/.changeset/old-falcons-jump.md deleted file mode 100644 index 107d75ff88..0000000000 --- a/.changeset/old-falcons-jump.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -'@backstage/plugin-newrelic': minor ---- - -The New Relic plugin now uses the Backstage proxy to communicate with New Relic's API. - -Please update your `app-config.yaml` as follows: - -```yaml -# Old Config -newrelic: - api: - baseUrl: 'https://api.newrelic.com/v2' - key: NEW_RELIC_REST_API_KEY -``` - -```yaml -# New Config -proxy: - '/newrelic/apm/api': - target: https://api.newrelic.com/v2 - headers: - X-Api-Key: - $env: NEW_RELIC_REST_API_KEY -``` diff --git a/.changeset/old-jeans-dance.md b/.changeset/old-jeans-dance.md deleted file mode 100644 index 1bd4a3136a..0000000000 --- a/.changeset/old-jeans-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -The CodeOwnersProcessor now handles 'url' locations diff --git a/.changeset/olive-bikes-jog.md b/.changeset/olive-bikes-jog.md deleted file mode 100644 index fdbf1e0d9f..0000000000 --- a/.changeset/olive-bikes-jog.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -add test cases for Status components diff --git a/.changeset/pink-spies-rule.md b/.changeset/pink-spies-rule.md deleted file mode 100644 index 71653a1841..0000000000 --- a/.changeset/pink-spies-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': patch ---- - -Replacing the hard coded `baseApiUrl` by reading the value from configuration to enable private GitHub setup for TechDocs. diff --git a/.changeset/polite-laws-think.md b/.changeset/polite-laws-think.md deleted file mode 100644 index a5eb7f9883..0000000000 --- a/.changeset/polite-laws-think.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Removed support for deprecated `catalog.providers` config that have been moved to `integrations` diff --git a/.changeset/polite-moose-cough.md b/.changeset/polite-moose-cough.md deleted file mode 100644 index b66227bb24..0000000000 --- a/.changeset/polite-moose-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -update ItemCard component and it's story diff --git a/.changeset/popular-ghosts-remain.md b/.changeset/popular-ghosts-remain.md deleted file mode 100644 index 4a170c7618..0000000000 --- a/.changeset/popular-ghosts-remain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Proper render boolean values on StructuredMetadataTable component diff --git a/.changeset/popular-jars-serve.md b/.changeset/popular-jars-serve.md deleted file mode 100644 index 6ee40195fc..0000000000 --- a/.changeset/popular-jars-serve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': minor ---- - -Enable adding locations for config files that does not yet exist by adding a flag to api request diff --git a/.changeset/pretty-cups-joke.md b/.changeset/pretty-cups-joke.md deleted file mode 100644 index 49a1db2a75..0000000000 --- a/.changeset/pretty-cups-joke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Add authentication token to Scaffolder GitHub Preparer diff --git a/.changeset/proud-eagles-grow.md b/.changeset/proud-eagles-grow.md deleted file mode 100644 index ef83a4ad26..0000000000 --- a/.changeset/proud-eagles-grow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fixed duplicate help output, and print help on invalid command diff --git a/.changeset/raghu-is-great.md b/.changeset/raghu-is-great.md deleted file mode 100644 index 805e49f3e8..0000000000 --- a/.changeset/raghu-is-great.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Renamed the `LocationProcessor` class to `CatalogProcessor`. - -Likewise, renamed `LocationProcessorResult`, `LocationProcessorLocationResult`, -`LocationProcessorDataResult`, `LocationProcessorEntityResult`, -`LocationProcessorErrorResult`, and `LocationProcessorEmit` to their `Catalog*` -counterparts. diff --git a/.changeset/red-games-float.md b/.changeset/red-games-float.md deleted file mode 100644 index 6eabba26a4..0000000000 --- a/.changeset/red-games-float.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-cost-insights': minor ---- - -- getProjectDailyCost and getGroupDailyCost no longer accept a metric as a parameter -- getDailyMetricData added to API for fetching daily metric data for given interval -- dailyCost removed as configurable metric -- default field added to metric configuration for displaying comparison metric data in top panel -- Metric.kind can no longer be null -- MetricData type added diff --git a/.changeset/remove-location-processor-read.md b/.changeset/remove-location-processor-read.md deleted file mode 100644 index 78aea6d820..0000000000 --- a/.changeset/remove-location-processor-read.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Remove the `read` argument of `LocationProcessor.processEntity`. -Instead, pass the `UrlReader` into the constructor of your `LocationProcessor`. diff --git a/.changeset/rocket-lizards-congregate.md b/.changeset/rocket-lizards-congregate.md deleted file mode 100644 index f4cd50aa36..0000000000 --- a/.changeset/rocket-lizards-congregate.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-catalog': minor ---- - -The URL path for a catalog entity has changed, - -- from: `/catalog/:kind/:optionalNamespaceAndName` -- to: `/catalog/:namespace/:kind/:name` - -Redirects are in place, so disruptions for users should not happen. diff --git a/.changeset/selfish-bats-perform.md b/.changeset/selfish-bats-perform.md deleted file mode 100644 index e4d05c088c..0000000000 --- a/.changeset/selfish-bats-perform.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-scaffolder-backend': patch ---- - -The new `scaffolder.github.baseUrl` config property allows to specify a custom base url for GitHub enterprise instances diff --git a/.changeset/selfish-mugs-itch.md b/.changeset/selfish-mugs-itch.md deleted file mode 100644 index 39ed236352..0000000000 --- a/.changeset/selfish-mugs-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': minor ---- - -Remove product filters from query parameters diff --git a/.changeset/seven-humans-check.md b/.changeset/seven-humans-check.md deleted file mode 100644 index f2fb784cc0..0000000000 --- a/.changeset/seven-humans-check.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'example-app': patch -'@backstage/core-api': patch -'@backstage/plugin-cost-insights': patch ---- - -Remove cost insights example client from demo app and export from plugin -Create cost insights dev plugin using example client -Make PluginConfig and dependent types public diff --git a/.changeset/shaggy-bobcats-warn.md b/.changeset/shaggy-bobcats-warn.md new file mode 100644 index 0000000000..048e1a0ff6 --- /dev/null +++ b/.changeset/shaggy-bobcats-warn.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': minor +--- + +New DependencyGraph component added to core package. diff --git a/.changeset/short-secrets.md b/.changeset/short-secrets.md deleted file mode 100644 index 72cb059979..0000000000 --- a/.changeset/short-secrets.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/config-loader': minor ---- - -Added support for new shorthand when defining secrets, where `$env: ENV` can be used instead of `$secret: { env: ENV }` etc. diff --git a/.changeset/silent-dodos-repeat.md b/.changeset/silent-dodos-repeat.md new file mode 100644 index 0000000000..04978406f3 --- /dev/null +++ b/.changeset/silent-dodos-repeat.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Fix divider prop not respected on InfoCard diff --git a/.changeset/slimy-garlics-eat.md b/.changeset/slimy-garlics-eat.md deleted file mode 100644 index 3ecc0ce495..0000000000 --- a/.changeset/slimy-garlics-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -update the EntityNotFound component diff --git a/.changeset/slow-experts-peel.md b/.changeset/slow-experts-peel.md deleted file mode 100644 index ed9c7af21e..0000000000 --- a/.changeset/slow-experts-peel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-radar': patch ---- - -fix the horizontal scrolling issue in the RadarPage component diff --git a/.changeset/smooth-hairs-breathe.md b/.changeset/smooth-hairs-breathe.md new file mode 100644 index 0000000000..2849a1d4b7 --- /dev/null +++ b/.changeset/smooth-hairs-breathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-radar': patch +--- + +Make the footer color of the tech-radar work in both light and dark theme. diff --git a/.changeset/spicy-bananas-help.md b/.changeset/spicy-bananas-help.md new file mode 100644 index 0000000000..6d847f4bc3 --- /dev/null +++ b/.changeset/spicy-bananas-help.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Upgrade @kyma-project/asyncapi-react to 0.14.2 diff --git a/.changeset/spicy-moles-yell.md b/.changeset/spicy-moles-yell.md deleted file mode 100644 index 72b648b30b..0000000000 --- a/.changeset/spicy-moles-yell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -make ErrorPage responsive + fix the test case diff --git a/.changeset/spicy-rockets-ring.md b/.changeset/spicy-rockets-ring.md deleted file mode 100644 index b39b433c1b..0000000000 --- a/.changeset/spicy-rockets-ring.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Added support for configuring the working directory of the Scaffolder: - -```yaml -backend: - workingDirectory: /some-dir # Use this to configure a working directory for the scaffolder, defaults to the OS temp-dir -``` diff --git a/.changeset/spotty-apples-visit.md b/.changeset/spotty-apples-visit.md deleted file mode 100644 index ba481fa052..0000000000 --- a/.changeset/spotty-apples-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -Better presentation of authentication errors diff --git a/.changeset/strong-moose-cough.md b/.changeset/strong-moose-cough.md new file mode 100644 index 0000000000..41a0da7cca --- /dev/null +++ b/.changeset/strong-moose-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': patch +--- + +Improve styling of outlined chips in dark mode. diff --git a/.changeset/sweet-bikes-battle.md b/.changeset/sweet-bikes-battle.md deleted file mode 100644 index 68ed8caeeb..0000000000 --- a/.changeset/sweet-bikes-battle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'example-app': patch ---- - -cleaning up because external plugins have already implemented new api for creating diff --git a/.changeset/swift-emus-mate.md b/.changeset/swift-emus-mate.md deleted file mode 100644 index 1903742115..0000000000 --- a/.changeset/swift-emus-mate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-api': minor ---- - -Refactored the FeatureFlagsApi to make it easier to re-implement. Existing usage of particularly getUserFlags can be replaced with isActive() or save(). diff --git a/.changeset/swift-peas-argue.md b/.changeset/swift-peas-argue.md deleted file mode 100644 index d78d844d45..0000000000 --- a/.changeset/swift-peas-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -give aria-label attribute to Status Ok, Warning and Error diff --git a/.changeset/ten-bees-wash.md b/.changeset/ten-bees-wash.md deleted file mode 100644 index 179dbf87f4..0000000000 --- a/.changeset/ten-bees-wash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -While techdocs fetches site name and metadata for the component, the page title was displayed as '[object Object] | Backstage'. This has now been fixed to display the component ID if site name is not present or being fetched. diff --git a/.changeset/three-horses-juggle.md b/.changeset/three-horses-juggle.md deleted file mode 100644 index bebcf77e43..0000000000 --- a/.changeset/three-horses-juggle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Introduce PreparerOptions for PreparerBase diff --git a/.changeset/tough-weeks-pull.md b/.changeset/tough-weeks-pull.md deleted file mode 100644 index e79355de90..0000000000 --- a/.changeset/tough-weeks-pull.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -fix the responsive of page story diff --git a/.changeset/url-reader-processor.md b/.changeset/url-reader-processor.md deleted file mode 100644 index 40fef3c106..0000000000 --- a/.changeset/url-reader-processor.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -The catalog backend UrlReaderProcessor now uses a UrlReader from @backstage/backend-common, which must now be supplied to the constructor. diff --git a/.changeset/weak-ducks-tan.md b/.changeset/weak-ducks-tan.md deleted file mode 100644 index 64b1c3f117..0000000000 --- a/.changeset/weak-ducks-tan.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/backend-common': minor -'example-backend': patch -'@backstage/cli': patch -'@backstage/create-app': patch ---- - -Change loadBackendConfig to return the config directly diff --git a/.changeset/weak-otters-love.md b/.changeset/weak-otters-love.md new file mode 100644 index 0000000000..2c273e067b --- /dev/null +++ b/.changeset/weak-otters-love.md @@ -0,0 +1,16 @@ +--- +'@backstage/plugin-scaffolder': minor +'@backstage/plugin-scaffolder-backend': minor +--- + +`createRouter` of scaffolder backend will now require additional option as `entityClient` which could be generated by `CatalogEntityClient` in `plugin-scaffolder-backend` package. Here is example to generate `entityClient`. + +```js +import { CatalogEntityClient } from '@backstage/plugin-scaffolder-backend'; +import { SingleHostDiscovery } from '@backstage/backend-common'; + +const discovery = SingleHostDiscovery.fromConfig(config); +const entityClient = new CatalogEntityClient({ discovery }); +``` + +- Scaffolder's API `/v1/jobs` will accept `templateName` instead of `template` Entity. diff --git a/.changeset/weak-rice-beam.md b/.changeset/weak-rice-beam.md new file mode 100644 index 0000000000..c507e350a9 --- /dev/null +++ b/.changeset/weak-rice-beam.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Capture plugin name under the /api/ prefix for http metrics diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d161a8e1a9..d818c0d6b5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,14 +4,10 @@ # The last matching pattern takes precedence. # https://help.github.com/articles/about-codeowners/ -* @spotify/backstage-core -/docs/features/techdocs @spotify/techdocs-core -/plugins/cost-insights @spotify/silver-lining +* @backstage/maintainers +/docs/features/techdocs @backstage/techdocs-core +/plugins/cost-insights @backstage/silver-lining /plugins/cloudbuild @trivago/ebarrios -/plugins/techdocs @spotify/techdocs-core -/plugins/techdocs-backend @spotify/techdocs-core -/packages/techdocs-cli @spotify/techdocs-core -/packages/techdocs-container @spotify/techdocs-core -/.github/workflows/techdocs.yml @spotify/techdocs-core -/.github/workflows/techdocs-pypi.yml @spotify/techdocs-core -/.changeset/cost-insights-* @spotify/silver-lining +/plugins/techdocs @backstage/techdocs-core +/plugins/techdocs-backend @backstage/techdocs-core +/.changeset/cost-insights-* @backstage/silver-lining diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index de7ce773bb..d68af23491 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -7,7 +7,7 @@ -- [ ] A changeset describing the change and affected packages. ([more info](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md#creating-changesets)) +- [ ] A changeset describing the change and affected packages. ([more info](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#creating-changesets)) - [ ] Added or updated documentation - [ ] Tests for new functionality and regression tests for bug fixes - [ ] Screenshots attached (for UI changes) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 1f9e083b51..3c5fa34adc 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -62,6 +62,7 @@ Firekube Fredrik github Github +gitlab Gitlab graphql graphviz @@ -190,6 +191,7 @@ toc tolerations Tolerations toolsets +tooltip touchpoints ui upvote diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index ac7872ea93..a557b4921b 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -15,5 +15,8 @@ jobs: run: yarn --frozen-lockfile - name: Create Release Pull Request uses: changesets/action@master + with: + # Calls out to `changeset version`, but also runs prettier + version: yarn release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 335bd80109..3f59b815b3 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -6,6 +6,8 @@ on: jobs: build: + if: github.repository == 'backstage/backstage' # prevent running on forks + runs-on: ubuntu-latest strategy: diff --git a/.github/workflows/techdocs-project-board.yml b/.github/workflows/techdocs-project-board.yml index b389cf6bf5..a0691f2a79 100644 --- a/.github/workflows/techdocs-project-board.yml +++ b/.github/workflows/techdocs-project-board.yml @@ -1,5 +1,5 @@ name: Automatically add new TechDocs Issues and PRs to the GitHub project board -# Development of TechDocs in Backstage is managed by this Kanban board - https://github.com/spotify/backstage/projects/5 +# Development of TechDocs in Backstage is managed by this Kanban board - https://github.com/backstage/backstage/projects/5 # New issues with TechDocs in their title or docs-like-code label will be added to the board. on: @@ -23,7 +23,7 @@ jobs: contains(github.event.issue.title, 'techdocs') || contains(github.event.issue.title, 'Techdocs') with: - project: 'https://github.com/spotify/backstage/projects/5' + project: 'https://github.com/backstage/backstage/projects/5' column_name: 'Incoming' - name: Assign new issue to Incoming based on its label. @@ -31,7 +31,7 @@ jobs: if: | contains(github.event.issue.labels.*.name, 'docs-like-code') with: - project: 'https://github.com/spotify/backstage/projects/5' + project: 'https://github.com/backstage/backstage/projects/5' column_name: 'Incoming' - name: Assign new PR to Incoming based on its title. @@ -41,7 +41,7 @@ jobs: contains(github.event.pull_request.title, 'techdocs') || contains(github.event.pull_request.title, 'Techdocs') with: - project: 'https://github.com/spotify/backstage/projects/5' + project: 'https://github.com/backstage/backstage/projects/5' column_name: 'Incoming' - name: Assign new PR to Incoming based on its label. @@ -49,5 +49,5 @@ jobs: if: | contains(github.event.pull_request.labels.*.name, 'docs-like-code') with: - project: 'https://github.com/spotify/backstage/projects/5' + project: 'https://github.com/backstage/backstage/projects/5' column_name: 'Incoming' diff --git a/.github/workflows/techdocs-pypi.yml b/.github/workflows/techdocs-pypi.yml deleted file mode 100644 index 7680cb98b0..0000000000 --- a/.github/workflows/techdocs-pypi.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Master Build TechDocs PyPI Publish - -on: - push: - branches: [master] - paths: - - '.github/workflows/techdocs-pypi.yml' - - 'packages/techdocs-container/**' - -jobs: - build: - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: [ubuntu-latest] - python-version: [3.7] - - steps: - # Publish techdocs-core to PyPI - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@master - with: - python-version: 3.7 - - name: Build Python distribution - working-directory: ./packages/techdocs-container/techdocs-core - run: | - pip install wheel - rm -rf dist - python setup.py bdist_wheel sdist --formats gztar - - name: Publish a Python distribution to PyPI - uses: pypa/gh-action-pypi-publish@master - with: - user: __token__ - password: ${{ secrets.PYPI_API_KEY }} - packages_dir: ./packages/techdocs-container/techdocs-core/dist diff --git a/.github/workflows/techdocs.yml b/.github/workflows/techdocs.yml deleted file mode 100644 index 95b68c9376..0000000000 --- a/.github/workflows/techdocs.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: TechDocs - -on: - pull_request: - paths: - - '.github/workflows/techdocs.yml' - - 'packages/techdocs-container/**' - - 'packages/techdocs-cli/**' - - 'plugins/techdocs/**' - - 'plugins/techdocs-backend/**' - -jobs: - build: - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: [ubuntu-latest] - python-version: [3.7] - - env: - TECHDOCS_CORE_PATH: ./packages/techdocs-container/techdocs-core - - name: Python ${{ matrix.node-version }} on ${{ matrix.os }} - steps: - - uses: actions/checkout@v2 - - # Build Docker Image - - name: Build Docker image - uses: docker/build-push-action@v1.1.0 - with: - path: packages/techdocs-container - push: false - - # Lint Python code for techdocs-core package - - name: Prepare Python environment - run: | - python3 -m pip install --index-url https://pypi.org/simple/ setuptools - python3 -m pip install --upgrade pip - python3 -m pip install --index-url https://pypi.org/simple/ -r $TECHDOCS_CORE_PATH/requirements.txt - - - name: Lint techdocs-core package - run: | - python3 -m black --check $TECHDOCS_CORE_PATH/src diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ab3459628..1ac33ca7f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ This is a best-effort changelog where we manually collect breaking changes. It is not an exhaustive list of all changes or even features added. -If you encounter issues while upgrading to a newer version, don't hesitate to reach out on [Discord](https://discord.gg/EBHEGzX) or [open an issue](https://github.com/spotify/backstage/issues/new/choose)! +If you encounter issues while upgrading to a newer version, don't hesitate to reach out on [Discord](https://discord.gg/EBHEGzX) or [open an issue](https://github.com/backstage/backstage/issues/new/choose)! ## Next Release @@ -26,18 +26,18 @@ If you encounter issues while upgrading to a newer version, don't hesitate to re ### Backend (example-backend, or backends created with @backstage/create-app) -- A plugin database manager has been created, and plugins can now accept that interface as an argument during initialisation. Notably, the `auth` plugin has a [`createRouter` signature change](./plugins/auth-backend/src/service/router.ts). See [packages/backend/src/index.ts](./packages/backend/src/index.ts) on how to set it up. [#2697](https://github.com/spotify/backstage/pull/2697) +- A plugin database manager has been created, and plugins can now accept that interface as an argument during initialisation. Notably, the `auth` plugin has a [`createRouter` signature change](./plugins/auth-backend/src/service/router.ts). See [packages/backend/src/index.ts](./packages/backend/src/index.ts) on how to set it up. [#2697](https://github.com/backstage/backstage/pull/2697) ## v0.1.1-alpha.24 ### Backend (example-backend, or backends created with @backstage/create-app) -- The default mount point for backend plugins have been changed to `/api`. These changes are done in the backend package itself, so it is recommended that you sync up existing backend packages with this new pattern. [#2562](https://github.com/spotify/backstage/pull/2562) -- A service discovery mechanism for backend plugins has been added, and is now a requirement for several backend plugins. See [packages/backend/src/index.ts](./packages/backend/src/index.ts) for how to set it up using `SingleHostDiscovery` from `@backstage/backend-common`. Note that the default base path for plugins is set to `/api` to that change, but it can be set to use the old behavior via the `basePath` option. [#2600](https://github.com/spotify/backstage/pull/2600) +- The default mount point for backend plugins have been changed to `/api`. These changes are done in the backend package itself, so it is recommended that you sync up existing backend packages with this new pattern. [#2562](https://github.com/backstage/backstage/pull/2562) +- A service discovery mechanism for backend plugins has been added, and is now a requirement for several backend plugins. See [packages/backend/src/index.ts](./packages/backend/src/index.ts) for how to set it up using `SingleHostDiscovery` from `@backstage/backend-common`. Note that the default base path for plugins is set to `/api` to that change, but it can be set to use the old behavior via the `basePath` option. [#2600](https://github.com/backstage/backstage/pull/2600) ### @backstage/auth-backend -- The default mount path of backend plugins was changed to `/api/:pluginId`, and as part of that it was needed to enable configuration of the base path of the auth backend, so that it can construct redirect URLs correctly. Note that you will also need to reconfigure any allowed redirect URLs to include `/api` if you switch to the new recommended pattern. [#2562](https://github.com/spotify/backstage/pull/2562) +- The default mount path of backend plugins was changed to `/api/:pluginId`, and as part of that it was needed to enable configuration of the base path of the auth backend, so that it can construct redirect URLs correctly. Note that you will also need to reconfigure any allowed redirect URLs to include `/api` if you switch to the new recommended pattern. [#2562](https://github.com/backstage/backstage/pull/2562) - The auth backend now requires an implementation of `PluginEndpointDiscovery` from `@backstage/backend-common` to be passed in as `discovery`. See the changes to `@backstage/backend`. ### @backstage/proxy-backend @@ -50,28 +50,28 @@ If you encounter issues while upgrading to a newer version, don't hesitate to re ### @backstage/plugin-identity-backend -- This plugin was removed, remove it from your backend if it's there. [#2616](https://github.com/spotify/backstage/pull/2616) +- This plugin was removed, remove it from your backend if it's there. [#2616](https://github.com/backstage/backstage/pull/2616) ## v0.1.1-alpha.23 ### @backstage/core -- Renamed `SessionStateApi` to `SessionApi` and `logout` to `signOut`. Custom implementations of the `SingInPage` app-component will need to rename their `logout` function. The different auth provider items for the `UserSettingsMenu` have been consolidated into a single `ProviderSettingsItem`, meaning you need to replace existing usages of `OAuthProviderSettings` and `OIDCProviderSettings`. [#2555](https://github.com/spotify/backstage/pull/2555). +- Renamed `SessionStateApi` to `SessionApi` and `logout` to `signOut`. Custom implementations of the `SingInPage` app-component will need to rename their `logout` function. The different auth provider items for the `UserSettingsMenu` have been consolidated into a single `ProviderSettingsItem`, meaning you need to replace existing usages of `OAuthProviderSettings` and `OIDCProviderSettings`. [#2555](https://github.com/backstage/backstage/pull/2555). ## v0.1.1-alpha.22 ### @backstage/core -- Introduced initial version of an inverted app/plugin relationship, where plugins export components for apps to use, instead registering themselves directly into the app. This enables more fine-grained control of plugin features, and also composition of plugins such as catalog pages with additional cards and tabs. This breaks the use of `RouteRef`s, and there will be more changes related to this in the future, but this change lays the initial foundation. See `packages/app` and followup PRs for how to update plugins for this change. [#2076](https://github.com/spotify/backstage/pull/2076) -- Switch to an automatic dependency injection mechanism for all Utility APIs, allowing plugins to ship default implementations of their APIs. See [https://backstage.io/docs/api/utility-apis](https://backstage.io/docs/api/utility-apis). [#2285](https://github.com/spotify/backstage/pull/2285) +- Introduced initial version of an inverted app/plugin relationship, where plugins export components for apps to use, instead registering themselves directly into the app. This enables more fine-grained control of plugin features, and also composition of plugins such as catalog pages with additional cards and tabs. This breaks the use of `RouteRef`s, and there will be more changes related to this in the future, but this change lays the initial foundation. See `packages/app` and followup PRs for how to update plugins for this change. [#2076](https://github.com/backstage/backstage/pull/2076) +- Switch to an automatic dependency injection mechanism for all Utility APIs, allowing plugins to ship default implementations of their APIs. See [https://backstage.io/docs/api/utility-apis](https://backstage.io/docs/api/utility-apis). [#2285](https://github.com/backstage/backstage/pull/2285) ### @backstage/cli -- Change `backstage-cli backend:build-image` to forward all args to `docker image build`, instead of just tag. Also add `--build` flag for building all dependent packages before packaging the workspace for the docker build. [#2299](https://github.com/spotify/backstage/pull/2299) +- Change `backstage-cli backend:build-image` to forward all args to `docker image build`, instead of just tag. Also add `--build` flag for building all dependent packages before packaging the workspace for the docker build. [#2299](https://github.com/backstage/backstage/pull/2299) ### @backstage/create-app -- Change root `tsc` output dir to `dist-types`, in order to allow for standalone plugin repos. [#2278](https://github.com/spotify/backstage/pull/2278) +- Change root `tsc` output dir to `dist-types`, in order to allow for standalone plugin repos. [#2278](https://github.com/backstage/backstage/pull/2278) ### @backstage/catalog-backend @@ -79,7 +79,7 @@ If you encounter issues while upgrading to a newer version, don't hesitate to re ## v0.1.1-alpha.21 -- Added many more frontend plugins to the template along with the sidebar. [#1942](https://github.com/spotify/backstage/pull/1942), [#2084](https://github.com/spotify/backstage/pull/2084) +- Added many more frontend plugins to the template along with the sidebar. [#1942](https://github.com/backstage/backstage/pull/1942), [#2084](https://github.com/backstage/backstage/pull/2084) ### @backstage/core @@ -90,14 +90,14 @@ If you encounter issues while upgrading to a newer version, don't hesitate to re ### @backstage/cli -- Set `NODE_ENV` to `test` when running test. [#2214](https://github.com/spotify/backstage/pull/2214) +- Set `NODE_ENV` to `test` when running test. [#2214](https://github.com/backstage/backstage/pull/2214) -- Fix for backend plugins names requiring to be prefixed with `@backstage` to build. [#2224](https://github.com/spotify/backstage/pull/2224) +- Fix for backend plugins names requiring to be prefixed with `@backstage` to build. [#2224](https://github.com/backstage/backstage/pull/2224) ### @backstage/backend-common - The backend plugin - [service builder](https://github.com/spotify/backstage/blob/master/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts) + [service builder](https://github.com/backstage/backstage/blob/master/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts) no longer adds `express.json()` automatically to all routes. While convenient in a lot of cases, it also led to problems where for example the proxy middleware could hang because the body had already been altered and could not @@ -107,61 +107,61 @@ If you encounter issues while upgrading to a newer version, don't hesitate to re ### @backstage/catalog-backend -- Add rules configuration for catalog location and entity kinds. The default rules should cover most use-cases, but you may need to allow specific entity kinds when using things like Template or Group entities. [#2118](https://github.com/spotify/backstage/pull/2118) +- Add rules configuration for catalog location and entity kinds. The default rules should cover most use-cases, but you may need to allow specific entity kinds when using things like Template or Group entities. [#2118](https://github.com/backstage/backstage/pull/2118) ## v0.1.1-alpha.20 ### @backstage/cli -- Use config files according to `NODE_ENV` when serving and building frontend packages. [#2077](https://github.com/spotify/backstage/pull/2077) +- Use config files according to `NODE_ENV` when serving and building frontend packages. [#2077](https://github.com/backstage/backstage/pull/2077) -- Pin `rollup-plugin-dts` to avoid a later broken version. [#2097](https://github.com/spotify/backstage/pull/2097) +- Pin `rollup-plugin-dts` to avoid a later broken version. [#2097](https://github.com/backstage/backstage/pull/2097) ## v0.1.1-alpha.19 ### @backstage/backend-common -- Allow listen host and port to be configured separately, in order to support PORT environment variables. [#1950](https://github.com/spotify/backstage/pull/1950) +- Allow listen host and port to be configured separately, in order to support PORT environment variables. [#1950](https://github.com/backstage/backstage/pull/1950) ### @backstage/core -- Added new `DiscoveryApi` for discovering backend endpoint in the frontend, and use in most plugins. See [packages/app/src/apis.ts](https://github.com/spotify/backstage/blob/master/packages/app/src/apis.ts) for how to register in your app. [#2074](https://github.com/spotify/backstage/pull/2074) +- Added new `DiscoveryApi` for discovering backend endpoint in the frontend, and use in most plugins. See [packages/app/src/apis.ts](https://github.com/backstage/backstage/blob/master/packages/app/src/apis.ts) for how to register in your app. [#2074](https://github.com/backstage/backstage/pull/2074) ### @backstage/create-app -- Added catalog and scaffolder frontend plugins to the template along with the sidebar. [#1942](https://github.com/spotify/backstage/pull/1942), [#2084](https://github.com/spotify/backstage/pull/2084) -- Many plugins have been added to the catalog and will for now be required to be added to separate apps as well. This will be solved as [#1536](https://github.com/spotify/backstage/issues/1536) gets sorted out, but for now you may need to install some plugins just to get pages to work. +- Added catalog and scaffolder frontend plugins to the template along with the sidebar. [#1942](https://github.com/backstage/backstage/pull/1942), [#2084](https://github.com/backstage/backstage/pull/2084) +- Many plugins have been added to the catalog and will for now be required to be added to separate apps as well. This will be solved as [#1536](https://github.com/backstage/backstage/issues/1536) gets sorted out, but for now you may need to install some plugins just to get pages to work. ### @backstage/catalog-backend -- Added the possibility to add static locations via `app-config.yaml`. This changed the signature of `new LocationReaders(logger)` inside `packages/backend/src/plugins/catalog.ts` to `new LocationReaders({config, logger})`. [#1890](https://github.com/spotify/backstage/pull/1890) +- Added the possibility to add static locations via `app-config.yaml`. This changed the signature of `new LocationReaders(logger)` inside `packages/backend/src/plugins/catalog.ts` to `new LocationReaders({config, logger})`. [#1890](https://github.com/backstage/backstage/pull/1890) ### @backstage/theme -- Changed the type signature of the palette, removing `sidebar: string` and adding `navigation: { background: string; indicator: string}`. [#1880](https://github.com/spotify/backstage/pull/1880) +- Changed the type signature of the palette, removing `sidebar: string` and adding `navigation: { background: string; indicator: string}`. [#1880](https://github.com/backstage/backstage/pull/1880) ## v0.1.1-alpha.18 ### @backstage/catalog-backend -- Fixed an issue with duplicated location logs. Applying the database migrations from this fix will clear the existing migration logs. [#1836](https://github.com/spotify/backstage/pull/1836) +- Fixed an issue with duplicated location logs. Applying the database migrations from this fix will clear the existing migration logs. [#1836](https://github.com/backstage/backstage/pull/1836) ### @backstage/auth-backend This version fixes a breakage in CSP policies set by the auth backend. If you're facing trouble with auth in alpha.17, upgrade to alpha.18. -- OAuth redirect URLs no longer receive the `env` parameter, as it is now passed through state instead. This will likely require a reconfiguration of the OAuth app, where a redirect URL like `http://localhost:7000/auth/google/handler/frame?env=development` should now be configured as `http://localhost:7000/auth/google/handler/frame`. [#1812](https://github.com/spotify/backstage/pull/1812) +- OAuth redirect URLs no longer receive the `env` parameter, as it is now passed through state instead. This will likely require a reconfiguration of the OAuth app, where a redirect URL like `http://localhost:7000/auth/google/handler/frame?env=development` should now be configured as `http://localhost:7000/auth/google/handler/frame`. [#1812](https://github.com/backstage/backstage/pull/1812) ### @backstage/core -- `SignInPage` props have been changed to receive a list of provider objects instead of simple string identifiers for all but the `'guest'` and `'custom'` providers. This opens up for configuration of custom providers, but may break existing configurations. See [packages/app/src/App.tsx](https://github.com/spotify/backstage/blob/032ba401af36a760efdac41668d7000ccf09bc57/packages/app/src/App.tsx#L36) and [packages/app/src/identityProviders.ts](https://github.com/spotify/backstage/blob/032ba401af36a760efdac41668d7000ccf09bc57/packages/app/src/identityProviders.ts#L24) for how to bring back the existing providers. [#1816](https://github.com/spotify/backstage/pull/1816) +- `SignInPage` props have been changed to receive a list of provider objects instead of simple string identifiers for all but the `'guest'` and `'custom'` providers. This opens up for configuration of custom providers, but may break existing configurations. See [packages/app/src/App.tsx](https://github.com/backstage/backstage/blob/032ba401af36a760efdac41668d7000ccf09bc57/packages/app/src/App.tsx#L36) and [packages/app/src/identityProviders.ts](https://github.com/backstage/backstage/blob/032ba401af36a760efdac41668d7000ccf09bc57/packages/app/src/identityProviders.ts#L24) for how to bring back the existing providers. [#1816](https://github.com/backstage/backstage/pull/1816) ## v0.1.1-alpha.17 ### @backstage/techdocs-backend -- The techdocs backend now requires more configuration to be supplied when creating the router. See [packages/backend/src/plugins/techdocs.ts](https://github.com/spotify/backstage/blob/0201fd9b4a52429519dd59e9184106ba69456deb/packages/backend/src/plugins/techdocs.ts#L42) for an example. [#1736](https://github.com/spotify/backstage/pull/1736) +- The techdocs backend now requires more configuration to be supplied when creating the router. See [packages/backend/src/plugins/techdocs.ts](https://github.com/backstage/backstage/blob/0201fd9b4a52429519dd59e9184106ba69456deb/packages/backend/src/plugins/techdocs.ts#L42) for an example. [#1736](https://github.com/backstage/backstage/pull/1736) ### @backstage/cli -- The `create-app` command was moved out from the CLI to a standalone package. It's now invoked with `npx @backstage/create-app` instead. [#1745](https://github.com/spotify/backstage/pull/1745) +- The `create-app` command was moved out from the CLI to a standalone package. It's now invoked with `npx @backstage/create-app` instead. [#1745](https://github.com/backstage/backstage/pull/1745) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7edbc6d17b..b7157d9f05 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,11 +12,11 @@ Backstage is released under the Apache2.0 License, and original creations contri ## Report bugs -No one likes bugs. Report bugs as an issue [here](https://github.com/spotify/backstage/issues/new?template=bug_template.md). +No one likes bugs. Report bugs as an issue [here](https://github.com/backstage/backstage/issues/new?template=bug_template.md). ## Fix bugs or build new features -Look through the GitHub issues for [bugs](https://github.com/spotify/backstage/labels/bugs), [good first issues](https://github.com/spotify/backstage/labels/good%20first%20issue) or [help wanted](https://github.com/spotify/backstage/labels/help%20wanted). +Look through the GitHub issues for [bugs](https://github.com/backstage/backstage/labels/bugs), [good first issues](https://github.com/backstage/backstage/labels/good%20first%20issue) or [help wanted](https://github.com/backstage/backstage/labels/help%20wanted). ## Build a plugin @@ -24,17 +24,17 @@ The value of Backstage grows with every new plugin that gets added. Wouldn't it A great reference example of a plugin can be found on [our blog](https://backstage.io/blog/2020/04/06/lighthouse-plugin) (thanks [@fastfrwrd](https://github.com/fastfrwrd)!) -What kind of plugins should/could be created? Some inspiration from the 120+ plugins that we have developed inside Spotify can be found [here](https://backstage.io/demos), but we will keep a running list of suggestions labeled with [[plugin]](https://github.com/spotify/backstage/labels/plugin). +What kind of plugins should/could be created? Some inspiration from the 120+ plugins that we have developed inside Spotify can be found [here](https://backstage.io/demos), but we will keep a running list of suggestions labeled with [[plugin]](https://github.com/backstage/backstage/labels/plugin). ## Suggesting a plugin -If you start developing a plugin that you aim to release as open source, we suggest that you create a [new Issue](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). This helps the community know what plugins are in development. +If you start developing a plugin that you aim to release as open source, we suggest that you create a [new Issue](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). This helps the community know what plugins are in development. You can also use this process if you have an idea for a good plugin but you hope that someone else will pick up the work. ## Adding Non-code Contributions -Since there is such a large landscape of possible development, build, and deployment environments, we welcome community contributions in these areas in the [`/contrib`](https://github.com/spotify/backstage/tree/master/contrib) folder of the project. This is an excellent place to put things that help out the community at large, but which may not fit within the scope of the core product to support natively. Here, you will find Helm charts, alternative Docker images, and much more. +Since there is such a large landscape of possible development, build, and deployment environments, we welcome community contributions in these areas in the [`/contrib`](https://github.com/backstage/backstage/tree/master/contrib) folder of the project. This is an excellent place to put things that help out the community at large, but which may not fit within the scope of the core product to support natively. Here, you will find Helm charts, alternative Docker images, and much more. ## Write Documentation @@ -44,11 +44,11 @@ The current documentation is very limited. Help us make the `/docs` folder come We think the best way to ensure different plugins provide a consistent experience is through a solid set of reusable UI/UX components. Backstage uses [Storybook](http://backstage.io/storybook). -Either help us [create new components](https://github.com/spotify/backstage/labels/help%20wanted) or improve stories for the existing ones (look for files with `*.stories.tsx`). +Either help us [create new components](https://github.com/backstage/backstage/labels/help%20wanted) or improve stories for the existing ones (look for files with `*.stories.tsx`). ## Submit Feedback -The best way to send feedback is to file [an issue](https://github.com/spotify/backstage/issues). +The best way to send feedback is to file [an issue](https://github.com/backstage/backstage/issues). If you are proposing a feature: @@ -74,7 +74,7 @@ All code is formatted with `prettier` using the configuration in the repo. If po If you're contributing to the backend or CLI tooling, be mindful of cross-platform support. [This](https://shapeshed.com/writing-cross-platform-node/) blog post is a good guide of what to keep in mind when writing cross-platform NodeJS. -Also be sure to skim through our [ADRs](https://github.com/spotify/backstage/tree/master/docs/architecture-decisions) to see if they cover what you're working on. In particular [ADR006: Avoid React.FC and React.SFC](https://github.com/spotify/backstage/blob/master/docs/architecture-decisions/adr006-avoid-react-fc.md) is one to look out for. +Also be sure to skim through our [ADRs](https://github.com/backstage/backstage/tree/master/docs/architecture-decisions) to see if they cover what you're working on. In particular [ADR006: Avoid React.FC and React.SFC](https://github.com/backstage/backstage/blob/master/docs/architecture-decisions/adr006-avoid-react-fc.md) is one to look out for. If there are any updates in `markdown` file please make sure to run `yarn run lint:docs`. Though it is checked on `lint-staged`. It is required to install [vale](https://docs.errata.ai/vale/install) separately and make sure it is accessed by global command. @@ -97,7 +97,7 @@ For more information, checkout [adding a changeset](https://github.com/atlassian This project adheres to the [Spotify FOSS Code of Conduct][code-of-conduct]. By participating, you are expected to honor this code. -[code-of-conduct]: https://github.com/spotify/backstage/blob/master/CODE_OF_CONDUCT.md +[code-of-conduct]: https://github.com/backstage/backstage/blob/master/CODE_OF_CONDUCT.md # Security Issues? diff --git a/README.md b/README.md index 70badd5321..a4b21539b5 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,15 @@ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![CNCF Status](https://img.shields.io/badge/cncf%20status-sandbox-blue.svg)](https://www.cncf.io/projects) -[![Main CI Build](https://github.com/spotify/backstage/workflows/Main%20Master%20Build/badge.svg)](https://github.com/spotify/backstage/actions?query=workflow%3A%22Main+Master+Build%22) +[![Main CI Build](https://github.com/backstage/backstage/workflows/Main%20Master%20Build/badge.svg)](https://github.com/backstage/backstage/actions?query=workflow%3A%22Main+Master+Build%22) [![Discord](https://img.shields.io/discord/687207715902193673)](https://discord.gg/EBHEGzX) ![Code style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg) -[![Codecov](https://img.shields.io/codecov/c/github/spotify/backstage)](https://codecov.io/gh/spotify/backstage) -[![](https://img.shields.io/npm/v/@backstage/core?label=Version)](https://github.com/spotify/backstage/releases) +[![Codecov](https://img.shields.io/codecov/c/github/backstage/backstage)](https://codecov.io/gh/backstage/backstage) +[![](https://img.shields.io/npm/v/@backstage/core?label=Version)](https://github.com/backstage/backstage/releases) + +> We recently moved from `spotify/backstage`, update your remotes! +> +> `git remote set-url origin git@github.com:backstage/backstage.git` ## What is Backstage? @@ -23,7 +27,7 @@ Out of the box, Backstage includes: - [Backstage Service Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview) for managing all your software (microservices, libraries, data pipelines, websites, ML models, etc.) - [Backstage Software Templates](https://backstage.io/docs/features/software-templates/software-templates-index) for quickly spinning up new projects and standardizing your tooling with your organization’s best practices - [Backstage TechDocs](https://backstage.io/docs/features/techdocs/techdocs-overview) for making it easy to create, maintain, find, and use technical documentation, using a "docs like code" approach -- Plus, a growing ecosystem of [open source plugins](https://github.com/spotify/backstage/tree/master/plugins) that further expand Backstage’s customizability and functionality +- Plus, a growing ecosystem of [open source plugins](https://github.com/backstage/backstage/tree/master/plugins) that further expand Backstage’s customizability and functionality Backstage was created by Spotify but is now hosted by the [Cloud Native Computing Foundation (CNCF)](https://www.cncf.io) as a Sandbox level project. Read the announcement [here](https://backstage.io/blog/2020/09/23/backstage-cncf-sandbox). @@ -46,8 +50,8 @@ Check out [the documentation](https://backstage.io/docs/getting-started) on how ## Community - [Discord chatroom](https://discord.gg/MUpMjP2) - Get support or discuss the project -- [Good First Issues](https://github.com/spotify/backstage/contribute) - Start here if you want to contribute -- [RFCs](https://github.com/spotify/backstage/labels/rfc) - Help shape the technical direction +- [Good First Issues](https://github.com/backstage/backstage/contribute) - Start here if you want to contribute +- [RFCs](https://github.com/backstage/backstage/labels/rfc) - Help shape the technical direction - [FAQ](https://backstage.io/docs/FAQ) - Frequently Asked Questions - [Code of Conduct](CODE_OF_CONDUCT.md) - This is how we roll - [Adopters](ADOPTERS.md) - Companies already using Backstage diff --git a/app-config.yaml b/app-config.yaml index 6f82af7772..148627dc5a 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -16,7 +16,7 @@ backend: credentials: true csp: connect-src: ["'self'", 'http:', 'https:'] - # workingDirectory: /tmp # Use this to configure a working direcotry for the scaffolder, defaults to the OS temp-dir + # workingDirectory: /tmp # Use this to configure a working directory for the scaffolder, defaults to the OS temp-dir # See README.md in the proxy-backend plugin for information on the configuration format proxy: @@ -138,22 +138,22 @@ catalog: locations: # Backstage example components - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/all-components.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-components.yaml # Example component for github-actions - type: url - target: https://github.com/spotify/backstage/blob/master/plugins/github-actions/examples/sample.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/github-actions/examples/sample.yaml # Example component for techdocs - type: url - target: https://github.com/spotify/backstage/blob/master/plugins/techdocs-backend/examples/documented-component/documented-component.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend/examples/documented-component/documented-component.yaml # Backstage example APIs - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/all-apis.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-apis.yaml # Backstage example templates - type: url - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/all-templates.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/all-templates.yaml # Backstage example groups and users - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme-corp.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme-corp.yaml scaffolder: github: @@ -232,6 +232,14 @@ auth: $env: AUTH_MICROSOFT_CLIENT_SECRET tenantId: $env: AUTH_MICROSOFT_TENANT_ID + onelogin: + development: + clientId: + $env: AUTH_ONELOGIN_CLIENT_ID + clientSecret: + $env: AUTH_ONELOGIN_CLIENT_SECRET + issuer: + $env: AUTH_ONELOGIN_ISSUER costInsights: engineerCost: 200000 products: diff --git a/catalog-info.yaml b/catalog-info.yaml index 405c3f31b4..617d01093e 100644 --- a/catalog-info.yaml +++ b/catalog-info.yaml @@ -5,10 +5,10 @@ metadata: description: | Backstage is an open-source developer portal that puts the developer experience first. annotations: - github.com/project-slug: spotify/backstage - backstage.io/techdocs-ref: github:https://github.com/spotify/backstage.git + github.com/project-slug: backstage/backstage + backstage.io/techdocs-ref: github:https://github.com/backstage/backstage.git lighthouse.com/website-url: https://backstage.io spec: type: library - owner: Spotify + owner: CNCF lifecycle: experimental diff --git a/contrib/chart/backstage/Chart.yaml b/contrib/chart/backstage/Chart.yaml index 24c6f2a4d7..8aeab9be3e 100644 --- a/contrib/chart/backstage/Chart.yaml +++ b/contrib/chart/backstage/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: backstage -description: A Helm chart for Spotify Backstage +description: A Helm chart for Backstage type: application # This is the chart version. This version number should be incremented each time you make changes @@ -12,7 +12,7 @@ version: 0.1.1 appVersion: v0.1.1-alpha.23 sources: - - https://github.com/spotify/backstage + - https://github.com/backstage/backstage - https://github.com/spotify/lighthouse-audit-service dependencies: diff --git a/contrib/chart/backstage/README.md b/contrib/chart/backstage/README.md index 9d1c93765b..7b60062265 100644 --- a/contrib/chart/backstage/README.md +++ b/contrib/chart/backstage/README.md @@ -36,7 +36,7 @@ appConfig: Then use it to run: ``` -git clone https://github.com/spotify/backstage.git +git clone https://github.com/backstage/backstage.git cd contrib/chart/backstage helm dependency update helm install -f backstage-mydomain.yaml backstage . @@ -125,12 +125,14 @@ lighthouse: ``` -For the CA, create a `configMap` named `-postgres-ca` with a file called `ca.crt`: +For the CA, create a `configMap` named `--postgres-ca` with a file called `ca.crt`: ``` -kubectl create configmap my-backstage --from-file=ca.crt" +kubectl create configmap my-company-backstage-postgres-ca --from-file=ca.crt" ``` +> Where the release name contains the chart name "backstage" then only the release name will be used. + Now install the helm chart: ``` @@ -155,10 +157,26 @@ backend: lighthouse: image: - repository: tag: ``` +### Use a private docker repo + +Create a docker-registry secret + +``` +kubectl create secret docker-registry # args +``` + +> For private images on docker hub --docker-server can be set to docker.io + +Reference the secret in your chart values + +```yaml +dockerRegistrySecretName: +``` + ### Different namespace To install the charts a specific namespace use `--namespace `: diff --git a/contrib/chart/backstage/files/app-config.development.yaml.tpl b/contrib/chart/backstage/files/app-config.development.yaml.tpl index 76d6499145..1e0a41ad63 100644 --- a/contrib/chart/backstage/files/app-config.development.yaml.tpl +++ b/contrib/chart/backstage/files/app-config.development.yaml.tpl @@ -18,19 +18,19 @@ catalog: locations: # Backstage example components - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/all-components.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-components.yaml # Example component for github-actions - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/github-actions/examples/sample.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/github-actions/examples/sample.yaml # Example component for techdocs - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/techdocs-backend/examples/documented-component/documented-component.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend/examples/documented-component/documented-component.yaml # Backstage example APIs - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/all-apis.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-apis.yaml # Backstage example templates - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/all-templates.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/all-templates.yaml {{- else }} locations: [] {{- end }} diff --git a/contrib/chart/backstage/templates/backend-deployment.yaml b/contrib/chart/backstage/templates/backend-deployment.yaml index c57764db8e..99ec955242 100644 --- a/contrib/chart/backstage/templates/backend-deployment.yaml +++ b/contrib/chart/backstage/templates/backend-deployment.yaml @@ -20,6 +20,10 @@ spec: component: backend spec: + {{- if .Values.dockerRegistrySecretName }} + imagePullSecrets: + - name: {{ .Values.dockerRegistrySecretName }} + {{- end}} containers: - name: {{ .Chart.Name }}-backend image: {{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }} diff --git a/contrib/chart/backstage/templates/frontend-deployment.yaml b/contrib/chart/backstage/templates/frontend-deployment.yaml index a5d84be2b2..5430ef041f 100644 --- a/contrib/chart/backstage/templates/frontend-deployment.yaml +++ b/contrib/chart/backstage/templates/frontend-deployment.yaml @@ -20,6 +20,10 @@ spec: component: frontend spec: + {{- if .Values.dockerRegistrySecretName }} + imagePullSecrets: + - name: {{ .Values.dockerRegistrySecretName }} + {{- end}} containers: - name: {{ .Chart.Name }}-frontend image: {{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }} diff --git a/contrib/chart/backstage/templates/lighthouse-deployment.yaml b/contrib/chart/backstage/templates/lighthouse-deployment.yaml index 70341a2a22..13bb8eadbb 100644 --- a/contrib/chart/backstage/templates/lighthouse-deployment.yaml +++ b/contrib/chart/backstage/templates/lighthouse-deployment.yaml @@ -21,6 +21,10 @@ spec: component: lighthouse-audit-service spec: + {{- if .Values.dockerRegistrySecretName }} + imagePullSecrets: + - name: {{ .Values.dockerRegistrySecretName }} + {{- end}} containers: - name: lighthouse-audit-service image: {{ .Values.lighthouse.image.repository }}:{{ .Values.lighthouse.image.tag }} diff --git a/contrib/chart/backstage/templates/postgresql-password-secret.yaml b/contrib/chart/backstage/templates/postgresql-password-secret.yaml index 9685130a03..e53369adb9 100644 --- a/contrib/chart/backstage/templates/postgresql-password-secret.yaml +++ b/contrib/chart/backstage/templates/postgresql-password-secret.yaml @@ -8,7 +8,7 @@ metadata: labels: release: {{ .Release.Name }} annotations: - "helm.sh/hook": "pre-install" + "helm.sh/hook": "pre-install,pre-upgrade" "helm.sh/hook-delete-policy": "before-hook-creation" data: postgresql-password: {{ .Values.appConfig.backend.database.connection.password | b64enc }} @@ -23,7 +23,7 @@ metadata: labels: release: {{ .Release.Name }} annotations: - "helm.sh/hook": "pre-install" + "helm.sh/hook": "pre-install,pre-upgrade" "helm.sh/hook-delete-policy": "before-hook-creation" data: postgresql-password: {{ .Values.lighthouse.database.connection.password | b64enc }} diff --git a/contrib/chart/backstage/values.yaml b/contrib/chart/backstage/values.yaml index eb06422d34..a4a0fadcc2 100644 --- a/contrib/chart/backstage/values.yaml +++ b/contrib/chart/backstage/values.yaml @@ -105,14 +105,14 @@ appConfig: rejectUnauthorized: false ca: sentry: - organization: spotify + organization: example-org-name techdocs: storageUrl: https://demo.example.com/api/techdocs/static/docs requestUrl: https://demo.example.com/api/techdocs lighthouse: baseUrl: https://demo.example.com/lighthouse-api rollbar: - organization: roadie + organization: example-org-name # Auth config has recently moved into the app config file in upstream Backstage. However, # most of this config simply mandates that items like the client id and client secret should diff --git a/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/Chart.yaml b/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/Chart.yaml index efc3635a7f..6cbb7ea3cb 100644 --- a/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/Chart.yaml +++ b/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v1 appVersion: '1.0' -description: A Helm chart for Spotify Backstage +description: A Helm chart for Backstage name: backstage version: 0.1.1-alpha.12 diff --git a/contrib/kubernetes/plain_single_backend_deplyoment/README.md b/contrib/kubernetes/plain_single_backend_deployment/README.md similarity index 97% rename from contrib/kubernetes/plain_single_backend_deplyoment/README.md rename to contrib/kubernetes/plain_single_backend_deployment/README.md index 685bed92a5..48c3490f81 100644 --- a/contrib/kubernetes/plain_single_backend_deplyoment/README.md +++ b/contrib/kubernetes/plain_single_backend_deployment/README.md @@ -13,7 +13,7 @@ yarn install yarn docker-build -kubectl apply -f contrib/kubernetes/plain_single_backend_deplyoment/deployment.yaml +kubectl apply -f contrib/kubernetes/plain_single_backend_deployment/deployment.yaml ``` You can use the following commands to monitor the deployment: diff --git a/contrib/kubernetes/plain_single_backend_deplyoment/deployment.yaml b/contrib/kubernetes/plain_single_backend_deployment/deployment.yaml similarity index 84% rename from contrib/kubernetes/plain_single_backend_deplyoment/deployment.yaml rename to contrib/kubernetes/plain_single_backend_deployment/deployment.yaml index a20c47229d..25c9207438 100644 --- a/contrib/kubernetes/plain_single_backend_deplyoment/deployment.yaml +++ b/contrib/kubernetes/plain_single_backend_deployment/deployment.yaml @@ -38,12 +38,12 @@ spec: - name: NODE_ENV value: development - # This makes it possible for the app to reach the backend when serving through `kubectl proxy` - # If you expose the service using for example an ingress controller, you should - # switch this out or remove it. - # - # Note that we're not setting app.baseUrl here, as setting the base path is not working at the moment. - # Further work is needed around the routing in the frontend or react-router before we can support that. + # This makes it possible for the app to reach the backend when serving through `kubectl proxy` + # If you expose the service using for example an ingress controller, you should + # switch this out or remove it. + # + # Note that we're not setting app.baseUrl here, as setting the base path is not working at the moment. + # Further work is needed around the routing in the frontend or react-router before we can support that. - name: APP_CONFIG_backend_baseUrl value: http://localhost:8001/api/v1/namespaces/backstage/services/backstage-backend:http/proxy diff --git a/docs/FAQ.md b/docs/FAQ.md index 7163d955c7..7b906a341b 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -48,11 +48,11 @@ source candidates. (And we'll probably end up writing some brand new ones, too.) ### What's the roadmap for Backstage? We envision three phases, which you can learn about in -[our project roadmap](https://github.com/spotify/backstage#project-roadmap). +[our project roadmap](https://github.com/backstage/backstage#project-roadmap). Even though the open source version of Backstage is relatively new compared to our internal version, we have already begun work on various aspects of all three phases. Looking at the -[milestones for active issues](https://github.com/spotify/backstage/milestones) +[milestones for active issues](https://github.com/backstage/backstage/milestones) will also give you a sense of our progress. ### My company doesn't have thousands of developers or services. Is Backstage overkill? @@ -87,8 +87,8 @@ well-known tech and a large flora of components. ### What technology does Backstage use? The codebase is a large-scale React application that uses TypeScript. For -[Phase 2](https://github.com/spotify/backstage#project-roadmap), we plan to use -Node.js and GraphQL. +[Phase 2](https://github.com/backstage/backstage#project-roadmap), we plan to +use Node.js and GraphQL. ### What is the end-to-end user flow? The happy path story. @@ -116,7 +116,7 @@ components. Plugins can fetch data either from the backend or an API exposed through the proxy. Learn more about -[the different components](https://github.com/spotify/backstage#overview) that +[the different components](https://github.com/backstage/backstage#overview) that make up Backstage. ### Do I have to write plugins in TypeScript? @@ -127,10 +127,10 @@ APIs in TypeScript, but aren't forcing it on individual plugins. ### How do I find out if a plugin already exists? Before you write a plugin, -[search the plugin issues](https://github.com/spotify/backstage/issues?q=is%3Aissue+label%3Aplugin+) +[search the plugin issues](https://github.com/backstage/backstage/issues?q=is%3Aissue+label%3Aplugin+) to see if it already exists or is in the works. If no one's thought of it yet, great! Open a new issue as -[a plugin suggestion](https://github.com/spotify/backstage/issues/new/choose) +[a plugin suggestion](https://github.com/backstage/backstage/issues/new/choose) and describe what your plugin will do. This will help coordinate our contributors' efforts and avoid duplicating existing functionality. @@ -151,7 +151,7 @@ above) ### Are you planning to have plugins baked into the repo? Or should they be developed in separate repos? Contributors can add open source plugins to the plugins directory in -[this monorepo](https://github.com/spotify/backstage). Integrators can then +[this monorepo](https://github.com/backstage/backstage). Integrators can then configure which open source plugins are available to use in their instance of the app. Open source plugins are downloaded as npm packages published in the open source repository. While we encourage using the open source model, we know @@ -166,7 +166,7 @@ We chose GitHub because it is the tool that we are most familiar with, so that will naturally lead to integrations for GitHub being developed at an early stage. Hosting this project on GitHub does not exclude integrations with alternatives, such as -[GitLab](https://github.com/spotify/backstage/issues?q=is%3Aissue+is%3Aopen+GitLab) +[GitLab](https://github.com/backstage/backstage/issues?q=is%3Aissue+is%3Aopen+GitLab) or Bitbucket. We believe that in time there will be plugins that will provide functionality for these tools as well. Hopefully, contributed by the community! Also note, implementations of Backstage can be hosted wherever you feel suits @@ -215,17 +215,17 @@ data is shared with. Yes. The core frontend framework could be used for building any large-scale web application where (1) multiple teams are building separate parts of the app, and (2) you want the overall experience to be consistent. That being said, in -[Phase 2](https://github.com/spotify/backstage#project-roadmap) of the project +[Phase 2](https://github.com/backstage/backstage#project-roadmap) of the project we will add features that are needed for developer portals and systems for managing software ecosystems. Our ambition will be to keep Backstage modular. ### How can I get involved? Jump right in! Come help us fix some of the -[early bugs and first issues](https://github.com/spotify/backstage/labels/good%20first%20issue) -or reach [a new milestone](https://github.com/spotify/backstage/milestones). Or -write an open source plugin for Backstage, like this -[Lighthouse plugin](https://github.com/spotify/backstage/tree/master/plugins/lighthouse). +[early bugs and first issues](https://github.com/backstage/backstage/labels/good%20first%20issue) +or reach [a new milestone](https://github.com/backstage/backstage/milestones). +Or write an open source plugin for Backstage, like this +[Lighthouse plugin](https://github.com/backstage/backstage/tree/master/plugins/lighthouse). See all the ways you can -[contribute here](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md). +[contribute here](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md). We'd love to have you as part of the community. diff --git a/docs/api/utility-apis.md b/docs/api/utility-apis.md index 1ebf2ae88b..a4d154b44b 100644 --- a/docs/api/utility-apis.md +++ b/docs/api/utility-apis.md @@ -22,7 +22,7 @@ during their entire life cycle. Each Utility API is tied to an `ApiRef` instance, which is a global singleton object without any additional state or functionality, its only purpose is to -reference Utility APIs. `ApiRef`s are create using `createApiRef`, which is +reference Utility APIs. `ApiRef`s are created using `createApiRef`, which is exported by `@backstage/core`. There are many [predefined Utility APIs](../reference/utility-apis/README.md) defined in `@backstage/core`, and they're all exported with a name of the pattern @@ -160,7 +160,8 @@ const app = createApp({ ``` A common pattern is to export a list of all APIs from `apis.ts`, next to -`App.tsx`. See the [example app in this repo](../../packages/app/src/apis.ts) +`App.tsx`. See the +[example app in this repo](https://github.com/backstage/backstage/blob/master/packages/app/src/apis.ts) for an example. ## Custom implementations of Utility APIs diff --git a/docs/architecture-decisions/adr002-default-catalog-file-format.md b/docs/architecture-decisions/adr002-default-catalog-file-format.md index d831581d5b..699f7af8ed 100644 --- a/docs/architecture-decisions/adr002-default-catalog-file-format.md +++ b/docs/architecture-decisions/adr002-default-catalog-file-format.md @@ -39,7 +39,7 @@ inside Backstage, or by push events from a CI/CD pipelines, or by webhook triggers from the version control system, etc. Each file describes one or more entities in accordance with the -[Backstage System Model](https://github.com/spotify/backstage/issues/390). All +[Backstage System Model](https://github.com/backstage/backstage/issues/390). All of these entities have a common structure and nomenclature, and they are stored in the software catalog from which they then can be queried. @@ -87,7 +87,7 @@ The root envelope object has the following structure. ### `apiVersion` and `kind` The `kind` is the high level entity type being described, typically from the -[Backstage system model](https://github.com/spotify/backstage/issues/390). The +[Backstage system model](https://github.com/backstage/backstage/issues/390). The first versions of the catalog will focus on the `Component` kind. The `apiVersion`is the version of specification format for that particular diff --git a/docs/architecture-decisions/adr007-use-msw-to-mock-service-requests.md b/docs/architecture-decisions/adr007-use-msw-to-mock-service-requests.md index 045588f505..68394de17c 100644 --- a/docs/architecture-decisions/adr007-use-msw-to-mock-service-requests.md +++ b/docs/architecture-decisions/adr007-use-msw-to-mock-service-requests.md @@ -41,7 +41,7 @@ worker.start(); ``` and in a more real life scenario, taken from -[CatalogClient.test.ts](https://github.com/spotify/backstage/blob/f3245c4f8f0b6b2625c4a6d5d50161b612fb4757/plugins/catalog/src/api/CatalogClient.test.ts) +[CatalogClient.test.ts](https://github.com/backstage/backstage/blob/f3245c4f8f0b6b2625c4a6d5d50161b612fb4757/plugins/catalog/src/api/CatalogClient.test.ts) ```ts beforeEach(() => { diff --git a/docs/architecture-decisions/adr008-default-catalog-file-name.md b/docs/architecture-decisions/adr008-default-catalog-file-name.md index d4716318bc..6794dc87cc 100644 --- a/docs/architecture-decisions/adr008-default-catalog-file-name.md +++ b/docs/architecture-decisions/adr008-default-catalog-file-name.md @@ -11,7 +11,7 @@ While the spec for the catalog file format is well described in to the name of the catalog file. Following discussion in -[Issue 1822](https://github.com/spotify/backstage/pull/1822#pullrequestreview-461253670), +[Issue 1822](https://github.com/backstage/backstage/pull/1822#pullrequestreview-461253670), a decision was made. ## Name diff --git a/docs/architecture-decisions/adr009-entity-references.md b/docs/architecture-decisions/adr009-entity-references.md index 8b7984ea49..a6fe3ee583 100644 --- a/docs/architecture-decisions/adr009-entity-references.md +++ b/docs/architecture-decisions/adr009-entity-references.md @@ -13,7 +13,7 @@ There was also some confusion on how to reference entities in URLs in the Backstage frontend. Following discussion in -[Issue 1947](https://github.com/spotify/backstage/issues/1947), a decision was +[Issue 1947](https://github.com/backstage/backstage/issues/1947), a decision was made. ## Entity References in YAML files diff --git a/docs/architecture-decisions/index.md b/docs/architecture-decisions/index.md index ddf2805e75..3211f37550 100644 --- a/docs/architecture-decisions/index.md +++ b/docs/architecture-decisions/index.md @@ -25,9 +25,9 @@ Records should be stored under the `architecture-decisions` directory. - Address and integrate feedback from the community - Eventually, assign a number - Add the path of the ADR to the microsite sidebar in - [`sidebars.json`](https://github.com/spotify/backstage/blob/master/microsite/sidebars.json) + [`sidebars.json`](https://github.com/backstage/backstage/blob/master/microsite/sidebars.json) - Add the path of the ADR to the - [`mkdocs.yml`](https://github.com/spotify/backstage/blob/master/mkdocs.yml) + [`mkdocs.yml`](https://github.com/backstage/backstage/blob/master/mkdocs.yml) - Merge the pull request ## Superseding an ADR diff --git a/docs/auth/index.md b/docs/auth/index.md index d7fb5d8c59..3f95efaf61 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -58,7 +58,7 @@ token used to make authenticated calls within Backstage. The middleware that will be provided by `@backstage/backend-common` allows verification of Backstage ID tokens, and optionally loading additional information about the user. The progress is tracked in -https://github.com/spotify/backstage/issues/1435. +https://github.com/backstage/backstage/issues/1435. #### Identity for App Developers diff --git a/docs/auth/oauth.md b/docs/auth/oauth.md index 178b99b153..0655175b58 100644 --- a/docs/auth/oauth.md +++ b/docs/auth/oauth.md @@ -15,10 +15,10 @@ to various third party APIs. There are occasions when the user wants to perform actions towards third party services that require authorization via OAuth. Backstage provides standardized [Utility APIs](../api/utility-apis.md) such as the -[GoogleAuthApi](https://github.com/spotify/backstage/blob/master/packages/core-api/src/apis/definitions/auth.ts) +[GoogleAuthApi](https://github.com/backstage/backstage/blob/master/packages/core-api/src/apis/definitions/auth.ts) for that use-case. Backstage also includes a set of implementations of these APIs that integrate with the -[auth-backend](https://github.com/spotify/backstage/tree/master/plugins/auth-backend) +[auth-backend](https://github.com/backstage/backstage/tree/master/plugins/auth-backend) plugin to provide a popup-based OAuth flow. ## Background @@ -58,9 +58,9 @@ easier to make authenticated requests inside a plugin. ## OAuth Flow The following describes the OAuth flow implemented by the -[auth-backend](https://github.com/spotify/backstage/tree/master/plugins/auth-backend) +[auth-backend](https://github.com/backstage/backstage/tree/master/plugins/auth-backend) and -[DefaultAuthConnector](https://github.com/spotify/backstage/blob/master/packages/core-api/src/lib/AuthConnector/DefaultAuthConnector.ts) +[DefaultAuthConnector](https://github.com/backstage/backstage/blob/master/packages/core-api/src/lib/AuthConnector/DefaultAuthConnector.ts) in `@backstage/core-api`. Component and APIs can request Access or ID Tokens from any available Auth diff --git a/docs/conf/reading.md b/docs/conf/reading.md index a43ec8c026..6d4b61224d 100644 --- a/docs/conf/reading.md +++ b/docs/conf/reading.md @@ -117,7 +117,7 @@ The [ConfigApi](../reference/utility-apis/Config.md) in the frontend is a Depending on the config api in another API is slightly different though, as the `ConfigApi` implementation is supplied via the App itself and not instantiated like other APIs. See -[packages/app/src/apis.ts](https://github.com/spotify/backstage/blob/244eef851f5aa19f91c7c9b5c12d5df95cf482ca/packages/app/src/apis.ts#L66) +[packages/app/src/apis.ts](https://github.com/backstage/backstage/blob/244eef851f5aa19f91c7c9b5c12d5df95cf482ca/packages/app/src/apis.ts#L66) for an example of how this wiring is done. For standalone plugin setups in `dev/index.ts`, register a factory with a @@ -129,4 +129,4 @@ from `@backstage/core`. In backend plugins the configuration is passed in via options from the main backend package. See for example -[packages/backend/src/plugins/auth.ts](https://github.com/spotify/backstage/blob/244eef851f5aa19f91c7c9b5c12d5df95cf482ca/packages/backend/src/plugins/auth.ts#L23). +[packages/backend/src/plugins/auth.ts](https://github.com/backstage/backstage/blob/244eef851f5aa19f91c7c9b5c12d5df95cf482ca/packages/backend/src/plugins/auth.ts#L23). diff --git a/docs/conf/writing.md b/docs/conf/writing.md index 06d4b52f3f..4eb92bb2ff 100644 --- a/docs/conf/writing.md +++ b/docs/conf/writing.md @@ -19,7 +19,7 @@ backend: baseUrl: http://localhost:7000 organization: - name: Spotify + name: CNCF proxy: /my/api: diff --git a/docs/dls/design.md b/docs/dls/design.md index fa3a0c159e..3bf283b77f 100644 --- a/docs/dls/design.md +++ b/docs/dls/design.md @@ -46,9 +46,9 @@ referencing Figma documents to share specs and prototypes with the community. ### Creating a New Design Component -| Step 1 | Step 2 | Step 3 | Step 4 | Step 5 | Step 6 | -| :------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------- | :--------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | -| Platform design team submits an issue to **spotify/Backstage GitHub** with a potential component. | Backstage community offers feedback or approval on **spotify/Backstage GitHub**. | Platform design team adjusts accordingly (as they see fit) and update the Figma DLS document. | Designed component is added to **spotify/Backstage GitHub** as an issue. | External or internal Backstage open source contributors build the component. | External or internal contributors add the component to the **Backstage Storybook**. 🎉 | +| Step 1 | Step 2 | Step 3 | Step 4 | Step 5 | Step 6 | +| :-------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------- | :--------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | +| Platform design team submits an issue to **backstage/backstage GitHub** with a potential component. | Backstage community offers feedback or approval on **backstage/backstage GitHub**. | Platform design team adjusts accordingly (as they see fit) and update the Figma DLS document. | Designed component is added to **backstage/backstage GitHub** as an issue. | External or internal Backstage open source contributors build the component. | External or internal contributors add the component to the **Backstage Storybook**. 🎉 | ### Building for Backstage @@ -56,9 +56,9 @@ referencing Figma documents to share specs and prototypes with the community. | :------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------- | | External or internal contributors use Backstage and come up with an idea of an entity to build for Backstage. | External or internal contributors refer to the Backstage Open Source design system documentation in the Figma DLS document. | External or internal contributors leverage the components and tokens from the Backstage Storybook. | External or internal contributors build their Backstage entity. | -| Step 5 | Step 6 | Step 7 | Step 8 | -| :------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------ | -| External or internal contributors make a pull request for their entity on spotify/Backstage GitHub for review. | Platform designers and devs review the entity and submit feedback or approval on spotify/Backstage GitHub. | External or internal contributors make the changes, pull request is approved and the entity is merged. It’s live on Backstage! 🎉 | If the entity happens to be or include a UX component, it’s added to Backstage Storybook as well. | +| Step 5 | Step 6 | Step 7 | Step 8 | +| :--------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------ | +| External or internal contributors make a pull request for their entity on backstage/backstage GitHub for review. | Platform designers and devs review the entity and submit feedback or approval on backstage/backstage GitHub. | External or internal contributors make the changes, pull request is approved and the entity is merged. It’s live on Backstage! 🎉 | If the entity happens to be or include a UX component, it’s added to Backstage Storybook as well. | The following diagram shows the relationship between the Backstage Design System and our foundation, which comprises of [Material UI](https://material-ui.com/) @@ -99,9 +99,10 @@ issues in GitHub with ‘design’ and/or ‘storybook’ - so feel free to brow tackle the tasks that interest you. If you have any questions regarding an issue, you can ask them in the comments section of the issue or on [Discord](https://discord.gg/EBHEGzX). We absolutely adore our external -contributors and will send you virtual semlas for your contributions! +contributors and will send you virtual +[semlas](https://en.wikipedia.org/wiki/Semla) for your contributions! -### Request a component. +### Request a component Create an issue (label it design and assign it to katz95) or send us a message on [Discord](https://discord.gg/EBHEGzX) (_#design_ channel) with details of @@ -135,5 +136,3 @@ contributing to Backstage as a designer is easy. From styling guidelines to UX principles to Figma documents, we’ll make sure you’re equipped to chip in on this project. We’re excited to work with you! In the meantime, we’d love to hear from you on [Discord](https://discord.gg/EBHEGzX). - -[Back to Docs](../README.md) diff --git a/docs/features/software-catalog/configuration.md b/docs/features/software-catalog/configuration.md index dd19d4cd51..d10fb29e30 100644 --- a/docs/features/software-catalog/configuration.md +++ b/docs/features/software-catalog/configuration.md @@ -89,7 +89,7 @@ the catalog under the `catalog.locations` key, for example: catalog: locations: - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml ``` The locations added through static configuration can not be removed through the diff --git a/docs/features/software-catalog/extending-the-model.md b/docs/features/software-catalog/extending-the-model.md index b045660202..72170fb576 100644 --- a/docs/features/software-catalog/extending-the-model.md +++ b/docs/features/software-catalog/extending-the-model.md @@ -36,6 +36,6 @@ through plugins. Different plugins are used for managing different types of components. For example, the -[Lighthouse plugin](https://github.com/spotify/backstage/tree/master/plugins/lighthouse) +[Lighthouse plugin](https://github.com/backstage/backstage/tree/master/plugins/lighthouse) only makes sense for Websites. The more specific you can be in how you model your software, the easier it is to provide plugins that are contextual. diff --git a/docs/features/software-catalog/external-integrations.md b/docs/features/software-catalog/external-integrations.md index 00a9d95fc2..325bed5e4a 100644 --- a/docs/features/software-catalog/external-integrations.md +++ b/docs/features/software-catalog/external-integrations.md @@ -5,9 +5,159 @@ description: Documentation on External integrations to integrate systems with Backstage --- -Backstage natively supports storing software components in -[metadata YAML files](descriptor-format.md). However, companies that already -have an existing system for keeping track of software and its owners can -integrate such systems with Backstage. +Backstage natively supports importing catalog data through the use of +[entity descriptor YAML files](descriptor-format.md). However, companies that +already have an existing system for keeping track of software and its owners can +leverage those systems by integrating them with Backstage. This article shows +the most common way of doing that integration: by adding a custom catalog +_processor_. -TODO: Describe the API contract. +## Background + +The catalog has a frontend plugin part, that communicates via a service API to +the backend plugin part. The backend has a processing loop that repeatedly +ingests data from the sources you specify, to store them in its database. + +As a Backstage adopter, you would be able to customize or extend the catalog in +several ways - by replacing the entire backend API, or by replacing entire +implementation classes at certain points in the backend, or by leveraging the +ingestion process to fetch data from your own authoritative source. Each method +has benefits and drawbacks, but this article will focus on the last one of the +above. It is the one that is the most straight forward and future proof, and +leverages a lot of benefits that come with the builtin catalog. + +## Processors and the Ingestion Loop + +The catalog holds a number of registered locations, that were added either by +site admins or by individual Backstage users. Their purpose is to reference some +sort of data that the catalog shall keep itself up to date with. Each location +has a `type`, and a `target` that are both strings. + +```yaml +# Example location +type: url +target: https://github.com/backstage/backstage/blob/master/catalog-info.yaml +``` + +The builtin catalog backend has an ingestion loop that periodically goes through +all of these registered locations, and pushes them and their resulting output +through the list of _processors_. + +Processors are classes that the site admin has registered with the catalog at +startup. They are at the heart of all catalog logic, and have the ability to +read the contents of locations, modify in-flight entities that were read out of +a location, perform validation, and more. The catalog comes with a set of +builtin processors, that have the ability to read from a list of well known +location types, to perform the basic processing needs, etc, but more can be +added by the organization that adopts Backstage. + +We will now show the process of creating a new processor and location type, +which enables the ingestion of catalog data from an existing external API. + +## Deciding on the New Locations + +The first step is to decide how we want to point at the system that holds our +data. Let's assume that it is internally named System-X and can be reached +through HTTP REST calls to its API. + +Let's decide that our locations shall take the following form: + +```yaml +type: system-x +target: http://systemx.services.example.net/api/v2 +``` + +It got its own made-up `type`, and the `target` conveniently points to the +actual API endpoint to talk to. + +So now we have to make the catalog aware of such a location so that it can start +feeding it into the ingestion loop. For this kind of an integration, you'd +typically want to add it to the list of statically always-available locations in +the config. + +```yaml +# In app-config.yaml +catalog: + locations: + - type: system-x + target: http://systemx.services.example.net/api/v2 +``` + +If you start up the backend now, it will start to periodically say that it could +not find a processor that supports that location. So let's make a processor that +does so! + +## Creating a Catalog Data Reader Processor + +The recommended way of instantiating the catalog backend classes is to use the +[`CatalogBuilder`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/service/CatalogBuilder.ts), +as illustrated in the +[example backend here](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/catalog.ts). +We will create a new +[`CatalogProcessor`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/ingestion/types.ts) +subclass that can be added to this catalog builder. + +It is up to you where you put the code for this new processor class. For quick +experimentation you could place it in your backend package, but we recommend +putting all extensions like this in a backend plugin package of their own in the +`plugins` folder of your Backstage repo. + +The class will have this basic structure: + +```ts +import { UrlReader } from '@backstage/backend-common'; +import { LocationSpec } from '@backstage/catalog-model'; +import { + results, + CatalogProcessor, + CatalogProcessorEmit, +} from '@backstage/plugin-catalog-backend'; + +// A processor that reads from the fictional System-X +export class SystemXReaderProcessor implements CatalogProcessor { + constructor(private readonly reader: UrlReader) {} + + async readLocation( + location: LocationSpec, + _optional: boolean, + emit: CatalogProcessorEmit, + ): Promise { + // Pick a custom location type string. A location will be + // registered later with this type. + if (location.type !== 'system-x') { + return false; + } + + try { + // Use the builtin reader facility to grab data from the + // API. If you prefer, you can just use plain fetch here + // (from the cross-fetch package), or any other method of + // your choosing. + const data = await this.reader.read(location.target); + const json = JSON.parse(data.toString()); + // Repeatedly call emit(results.entity(location, )) + } catch (error) { + const message = `Unable to read ${location.type}, ${error}`; + emit(results.generalError(location, message)); + } + + return true; + } +} +``` + +The key points to note are: + +- Make a class that implements `CatalogProcessor` +- Only act on location types that you care about, and leave the rest alone by + returning `false` +- Read the data from the external system in any way you see fit. Use the + location `target` field if you designed it as mentioned above +- Call `emit` any number of times with the results of that process +- Finally return `true` + +You should now be able to instantiate this class in your backend, and add it to +the `CatalogBuilder` using the `addProcessors` method. + +Start up the backend - it should now start reading from the previously +registered location and you'll see your entities start to appear in Backstage. diff --git a/docs/features/software-catalog/index.md b/docs/features/software-catalog/index.md index 953540227c..6076068504 100644 --- a/docs/features/software-catalog/index.md +++ b/docs/features/software-catalog/index.md @@ -33,10 +33,10 @@ More specifically, the Service Catalog enables two main use-cases: ## Getting Started -The Software Catalog is available to browse on the start page at `/`. If you've -followed [Installing in your Backstage App](./installation.md) in your separate -App or [Getting Started with Backstage](../../getting-started) for this repo, -you should be able to browse the catalog at `http://localhost:3000`. +The Software Catalog is available to browse at `/catalog`. If you've followed +[Installing in your Backstage App](./installation.md) in your separate App or +[Getting Started with Backstage](../../getting-started) for this repo, you +should be able to browse the catalog at `http://localhost:3000`. ![](../../assets/software-catalog/service-catalog-home.png) @@ -62,11 +62,11 @@ Users can register new components by going to `/create` and clicking the Backstage expects the full URL to the YAML in your source control. Example: ```bash -https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml +https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml ``` _More examples can be found -[here](https://github.com/spotify/backstage/tree/master/packages/catalog-model/examples)._ +[here](https://github.com/backstage/backstage/tree/master/packages/catalog-model/examples)._ ![](../../assets/software-catalog/bsc-register-2.png) @@ -91,7 +91,7 @@ above example can be added using the following configuration: catalog: locations: - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml ``` More information about catalog configuration can be found @@ -135,7 +135,7 @@ in the catalog. ![tools](https://backstage.io/blog/assets/20-05-20/tabs.png) The Backstage platform can be customized by incorporating -[existing open source plugins](https://github.com/spotify/backstage/tree/master/plugins), +[existing open source plugins](https://github.com/backstage/backstage/tree/master/plugins), or by [building your own](../../plugins/index.md). ## Links diff --git a/docs/features/software-catalog/installation.md b/docs/features/software-catalog/installation.md index 1e037461b4..b2afd62878 100644 --- a/docs/features/software-catalog/installation.md +++ b/docs/features/software-catalog/installation.md @@ -56,7 +56,7 @@ The catalog components depend on a number of other [Utility APIs](../../api/utility-apis.md) to function, including at least the `ErrorApi` and `StorageApi`. You can find an example of how to install these in your app -[here](https://github.com/spotify/backstage/blob/61c3a7e5b750dc7c059ef16b188594d31b2c04c2/packages/app/src/apis.ts#L80). +[here](https://github.com/backstage/backstage/blob/61c3a7e5b750dc7c059ef16b188594d31b2c04c2/packages/app/src/apis.ts#L80). ## Gotchas that we will fix @@ -168,21 +168,21 @@ catalog: locations: # Backstage Example Component - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-order-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/playback-order-component.yaml - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/podcast-api-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/podcast-api-component.yaml - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/queue-proxy-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/queue-proxy-component.yaml - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/searcher-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/searcher-component.yaml - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-lib-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/playback-lib-component.yaml - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/www-artist-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/www-artist-component.yaml - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/shuffle-api-component.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/shuffle-api-component.yaml ``` ### Running the Backend diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index 44dac13d65..53f49d5df9 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -8,7 +8,7 @@ We believe that a strong shared understanding and terminology around software and resources leads to a better Backstage experience. _This description originates from -[this RFC](https://github.com/spotify/backstage/issues/390). Note that some of +[this RFC](https://github.com/backstage/backstage/issues/390). Note that some of the concepts are not yet supported in Backstage._ ## Core Entities @@ -113,5 +113,5 @@ Backstage currently supports Components and APIs. ## Links -- [Original RFC](https://github.com/spotify/backstage/issues/390) +- [Original RFC](https://github.com/backstage/backstage/issues/390) - [YAML file format](../../architecture-decisions/adr002-default-catalog-file-format.md) diff --git a/docs/features/software-catalog/well-known-annotations.md b/docs/features/software-catalog/well-known-annotations.md index 47b1d5885d..5cb6837340 100644 --- a/docs/features/software-catalog/well-known-annotations.md +++ b/docs/features/software-catalog/well-known-annotations.md @@ -23,7 +23,7 @@ use. # Example: metadata: annotations: - backstage.io/managed-by-location: github:http://github.com/spotify/backstage/catalog-info.yaml + backstage.io/managed-by-location: github:http://github.com/backstage/backstage/catalog-info.yaml ``` The value of this annotation is a so called location reference string, that @@ -47,7 +47,7 @@ colon is always present. # Example: metadata: annotations: - backstage.io/techdocs-ref: github:https://github.com/spotify/backstage.git + backstage.io/techdocs-ref: github:https://github.com/backstage/backstage.git ``` The value of this annotation is a location reference string (see above). If this @@ -75,7 +75,7 @@ that entity. # Example: metadata: annotations: - github.com/project-slug: spotify/backstage + github.com/project-slug: backstage/backstage ``` The value of this annotation is the so-called slug that identifies a project on @@ -93,7 +93,7 @@ that entity. # Example: metadata: annotations: - github.com/team-slug: spotify/backstage-core + github.com/team-slug: backstage/maintainers ``` The value of this annotation is the so-called slug that identifies a team on @@ -146,7 +146,7 @@ that entity. # Example: metadata: annotations: - rollbar.com/project-slug: spotify/pump-station + rollbar.com/project-slug: backstage/pump-station ``` The value of this annotation is the so-called slug (or alternatively, the ID) of @@ -158,6 +158,27 @@ fallback (`rollbar.organization` followed by `organization.name`). Specifying this annotation may enable Rollbar related features in Backstage for that entity. +### circleci.com/project-slug + +```yaml +# Example: +metadata: + annotations: + circleci.com/project-slug: github/spotify/pump-station +``` + +The value of this annotation is the so-called slug (or alternatively, the ID) of +a [CircleCI](https://circleci.com/) project within your organization. The value +can be the format of `[source-control-manager]/[organization]/[project-slug]` or +just `[organization]/[project-slug]`. When the `[source-control-manager]` slug +is omitted, `bitbucket` will be used as a fallback. + +Specifying this annotation will cause the CI/CD features in Backstage to display +data from CircleCI for that entity. + +Providing both the `github.com/project-slug` and `circleci.com/project-slug` +annotations can cause problems as both may be used for CI/CD features. + ### backstage.io/ldap-rdn, backstage.io/ldap-uuid, backstage.io/ldap-dn ```yaml diff --git a/docs/features/software-templates/extending/create-your-own-preparer.md b/docs/features/software-templates/extending/create-your-own-preparer.md index ef9d709bce..5419748c3a 100644 --- a/docs/features/software-templates/extending/create-your-own-preparer.md +++ b/docs/features/software-templates/extending/create-your-own-preparer.md @@ -15,10 +15,10 @@ location protocols: - `github://` These two are added to the `PreparersBuilder` and then passed into the -`createRouter` function of the `@spotify/plugin-scaffolder-backend`. +`createRouter` function of the `@backstage/plugin-scaffolder-backend`. A full example backend can be found in -[`scaffolder.ts`](https://github.com/spotify/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts), +[`scaffolder.ts`](https://github.com/backstage/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts), but it looks something like the following ```ts @@ -85,8 +85,8 @@ and put the contents into a temporary directory and return that directory path. Some good examples exist here: -- https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts -- https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +- https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts +- https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts ### Registering your own Preparer diff --git a/docs/features/software-templates/extending/create-your-own-publisher.md b/docs/features/software-templates/extending/create-your-own-publisher.md index 546980f033..97854c999a 100644 --- a/docs/features/software-templates/extending/create-your-own-publisher.md +++ b/docs/features/software-templates/extending/create-your-own-publisher.md @@ -18,11 +18,11 @@ Currently we provide the following `publishers`: - `github` This publisher is passed through to the `createRouter` function of the -`@spotify/plugin-scaffolder-backend`. Currently, only one publisher is +`@backstage/plugin-scaffolder-backend`. Currently, only one publisher is supported, but PR's are always welcome. An full example backend can be found -[here](https://github.com/spotify/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts), +[here](https://github.com/backstage/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts), but it looks something like the following ```ts @@ -82,7 +82,7 @@ Now it's up to you to implement the `publish` function and return Some good examples exist here: -- https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +- https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts ### Registering your own Publisher diff --git a/docs/features/software-templates/extending/create-your-own-templater.md b/docs/features/software-templates/extending/create-your-own-templater.md index d4a6eef5d2..63acd38286 100644 --- a/docs/features/software-templates/extending/create-your-own-templater.md +++ b/docs/features/software-templates/extending/create-your-own-templater.md @@ -17,10 +17,10 @@ Currently we provide the following templaters: - `cookiecutter` This templater is added to the `TemplaterBuilder` and then passed into the -`createRouter` function of the `@spotify/plugin-scaffolder-backend` +`createRouter` function of the `@backstage/plugin-scaffolder-backend` An full example backend can be found -[here](https://github.com/spotify/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts), +[here](https://github.com/backstage/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts), but it looks something like the following ```ts @@ -96,7 +96,7 @@ Now it's up to you to implement the `run` function, and then return a Some good examples exist here: -- https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts +- https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts ### Registering your own Templater diff --git a/docs/features/software-templates/extending/index.md b/docs/features/software-templates/extending/index.md index 944bf0e3ca..aaf42d6b12 100644 --- a/docs/features/software-templates/extending/index.md +++ b/docs/features/software-templates/extending/index.md @@ -51,7 +51,7 @@ passed through to the scaffolder backend. ### How it works Most of the heavy lifting is done in the -[router.ts](https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/src/service/router.ts#L93) +[router.ts](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/service/router.ts#L93) file in the `scaffolder-backend` plugin. There are two routes defined in the router: `POST /v1/jobs` and diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md index bac5f60789..724b86aed1 100644 --- a/docs/features/software-templates/installation.md +++ b/docs/features/software-templates/installation.md @@ -156,11 +156,11 @@ catalog: locations: # Backstage Example Templates - type: url - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml - type: url - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml - type: url - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml - type: url target: https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml ``` diff --git a/docs/features/techdocs/FAQ.md b/docs/features/techdocs/FAQ.md index e81e9d82c7..de424778cb 100644 --- a/docs/features/techdocs/FAQ.md +++ b/docs/features/techdocs/FAQ.md @@ -17,14 +17,12 @@ This page answers frequently asked questions about [TechDocs](README.md). TechDocs is using [MkDocs](https://www.mkdocs.org/) to build project documentation under the hood. Documentation built with the -[techdocs-container](https://github.com/spotify/backstage/blob/master/packages/techdocs-container/README.md) -is using the MkDocs -[Material Theme](https://github.com/squidfunk/mkdocs-material). +[techdocs-container](https://github.com/backstage/techdocs-container) is using +the MkDocs [Material Theme](https://github.com/squidfunk/mkdocs-material). #### What is the mkdocs-techdocs-core plugin? -The -[mkdocs-techdocs-core](https://github.com/spotify/backstage/blob/master/packages/techdocs-container/techdocs-core/README.md) +The [mkdocs-techdocs-core](https://github.com/backstage/mkdocs-techdocs-core) package is a MkDocs Plugin that works like a wrapper around multiple MkDocs plugins (e.g. [MkDocs Monorepo Plugin](https://github.com/spotify/mkdocs-monorepo-plugin)) as diff --git a/docs/features/techdocs/README.md b/docs/features/techdocs/README.md index e2b81b4a53..f1cf637997 100644 --- a/docs/features/techdocs/README.md +++ b/docs/features/techdocs/README.md @@ -40,10 +40,10 @@ about TechDocs and the philosophy in its | [TechDocs V.2 🔮⌛][v2] | Easy adoption of TechDocs (whatever environment you have) [See V.2 Use Cases.](#techdocs-v2) | | [TechDocs V.3 🔮⌛][v3] | Build a widget (plugin) framework so that contributors can easily contribute features to TechDocs - that others can use. [See V.3 Use Cases.](#techdocs-v3) | -[v0]: https://github.com/spotify/backstage/milestone/15 -[v1]: https://github.com/spotify/backstage/milestone/16 -[v2]: https://github.com/spotify/backstage/milestone/22 -[v3]: https://github.com/spotify/backstage/milestone/17 +[v0]: https://github.com/backstage/backstage/milestone/15 +[v1]: https://github.com/backstage/backstage/milestone/16 +[v2]: https://github.com/backstage/backstage/milestone/22 +[v3]: https://github.com/backstage/backstage/milestone/17 @@ -109,18 +109,16 @@ migrate Spotify's existing TechDocs features to open source. | ------------------------------------------- | -------------------------------------------------------- | | Frontend | [`@backstage/plugin-techdocs`][techdocs/frontend] | | Backend | [`@backstage/plugin-techdocs-backend`][techdocs/backend] | -| Docker Container (for generating doc sites) | [`packages/techdocs-container`][techdocs/container] | -| CLI (for local development) | [`packages/techdocs-cli`][techdocs/cli] | +| Docker Container (for generating doc sites) | [`techdocs-container`][techdocs/container] | +| CLI (for local development) | [`@techdocs/cli`][techdocs/cli] | [getting started]: getting-started.md [concepts]: concepts.md [creating and publishing documentation]: creating-and-publishing.md [faq]: FAQ.md 'Frequently asked questions' [techdocs/frontend]: - https://github.com/spotify/backstage/blob/master/plugins/techdocs + https://github.com/backstage/backstage/blob/master/plugins/techdocs [techdocs/backend]: - https://github.com/spotify/backstage/blob/master/plugins/techdocs-backend -[techdocs/container]: - https://github.com/spotify/backstage/blob/master/packages/techdocs-container -[techdocs/cli]: - https://github.com/spotify/backstage/blob/master/packages/techdocs-cli + https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend +[techdocs/container]: https://github.com/backstage/techdocs-container +[techdocs/cli]: https://github.com/backstage/techdocs-cli diff --git a/docs/features/techdocs/concepts.md b/docs/features/techdocs/concepts.md index 13144f8df0..1675c64288 100644 --- a/docs/features/techdocs/concepts.md +++ b/docs/features/techdocs/concepts.md @@ -14,7 +14,7 @@ The TechDocs Core Plugin is an [MkDocs](https://www.mkdocs.org/) plugin created as a wrapper around multiple MkDocs plugins and Python Markdown extensions to standardize the configuration of MkDocs used for TechDocs. -[TechDocs Core](https://github.com/spotify/backstage/blob/master/packages/techdocs-container/techdocs-core/README.md) +[TechDocs Core](https://github.com/backstage/mkdocs-techdocs-core) ### TechDocs container @@ -23,14 +23,14 @@ The TechDocs container is a Docker container available at pages, including stylesheets and scripts from Python flavored Markdown, through MkDocs. -[TechDocs Container](https://github.com/spotify/backstage/blob/master/packages/techdocs-container/README.md) +[TechDocs Container](https://github.com/backstage/techdocs-container) ### TechDocs publisher The `techdocs-backend` plugin currently comes with one publisher - `LocalPublish`. -[TechDocs Backend](https://github.com/spotify/backstage/tree/master/plugins/techdocs-backend) +[TechDocs Backend](https://github.com/backstage/backstage/tree/master/plugins/techdocs-backend) More standalone publishers will come in the near future... @@ -41,7 +41,7 @@ documentation for publishing. Currently it mostly acts as a wrapper around the TechDocs container and provides an easy-to-use interface for our docker container. -[TechDocs CLI](https://github.com/spotify/backstage/blob/master/packages/techdocs-cli/README.md) +[TechDocs CLI](https://github.com/backstage/techdocs-cli) ### TechDocs Reader @@ -53,7 +53,7 @@ The TechDocs Reader purpose is also to open up the opportunity to integrate TechDocs widgets for a customized full-featured TechDocs experience. ([coming soon V.3](./README.md#project-roadmap)) -[TechDocs Reader](https://github.com/spotify/backstage/blob/master/plugins/techdocs/src/reader/README.md) +[TechDocs Reader](https://github.com/backstage/backstage/blob/master/plugins/techdocs/src/reader/README.md) ### Transformers @@ -62,4 +62,4 @@ Reader. The reason why transformers were introduced was to provide a way to transform the HTML content on pre and post render (e.g. rewrite docs links or modify css). -[Transformers API docs](https://github.com/spotify/backstage/blob/master/plugins/techdocs/src/reader/README.md) +[Transformers API docs](https://github.com/backstage/backstage/blob/master/plugins/techdocs/src/reader/README.md) diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index 72efb6eee0..cbbbc1e6cd 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -73,10 +73,10 @@ required. ### Disable Docker in Docker situation (Optional) -The TechDocs backend plugin runs a docker container with mkdocs to generate the -frontend of the docs from source files (Markdown). If you are deploying -Backstage using Docker, this will mean that your Backstage Docker container will -try to run another Docker container for TechDocs backend. +The TechDocs backend plugin runs a docker container with mkdocs installed to +generate the frontend of the docs from source files (Markdown). If you are +deploying Backstage using Docker, this will mean that your Backstage Docker +container will try to run another Docker container for TechDocs backend. To avoid this problem, we have a configuration available. You can set a value in your `app-config.yaml` that tells the techdocs generator if it should run the @@ -90,10 +90,23 @@ techdocs: ``` Setting `generators.techdocs` to `local` means you will have to make sure your -environment is compatible with techdocs. You will have to install the -`mkdocs-techdocs-container` and 'mkdocs' package from pip, as well as graphviz -and plantuml from your package manager. This has only been tested with python -3.7 and python 3.8. +environment is compatible with techdocs. + +You will have to install the `mkdocs` and `mkdocs-techdocs-core` package from +pip, as well as `graphviz` and `plantuml` from your OS package manager (e.g. +apt). See our +[Dockerfile](https://github.com/spotify/backstage/blob/master/packages/techdocs-container/Dockerfile) +for the latest requirements. You should be trying to match your Dockerfile with +this one. + +Note: We recommend Python version 3.7 or higher. + +Caveat: Please install the `mkdocs-techdocs-core` package after all other Python +packages. The order is important to make sure we get correct version of some of +the dependencies. For example, we want `Markdown` version to be +[3.2.2](https://github.com/spotify/backstage/blob/f9f70c225548017b6a14daea75b00fbd399c11eb/packages/techdocs-container/techdocs-core/requirements.txt#L11). +You can also explicitly install `Markdown==3.2.2` after installing all other +Python packages. ## Run Backstage locally diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md index 97876c2ba1..79cd405198 100644 --- a/docs/getting-started/app-custom-theme.md +++ b/docs/getting-started/app-custom-theme.md @@ -37,7 +37,7 @@ in combination with [createMuiTheme](https://material-ui.com/customization/theming/#createmuitheme-options-args-theme) from [@material-ui/core](https://www.npmjs.com/package/@material-ui/core). See the -[@backstage/theme source](https://github.com/spotify/backstage/tree/master/packages/theme/src) +[@backstage/theme source](https://github.com/backstage/backstage/tree/master/packages/theme/src) and the implementation of the `createTheme` function for how this is done. You can also create a theme from scratch that matches the `BackstageTheme` type diff --git a/docs/getting-started/deployment-helm.md b/docs/getting-started/deployment-helm.md index c062ed3951..e1f3ea7629 100644 --- a/docs/getting-started/deployment-helm.md +++ b/docs/getting-started/deployment-helm.md @@ -8,7 +8,7 @@ sidebar_label: Kubernetes and Helm # Helm charts An example Backstage app can be deployed in Kubernetes using the -[Backstage Helm charts](https://github.com/spotify/backstage/tree/master/contrib/chart/backstage). +[Backstage Helm charts](https://github.com/backstage/backstage/tree/master/contrib/chart/backstage). First, choose a DNS name where Backstage will be hosted, and create a YAML file for your custom configuration. @@ -32,7 +32,7 @@ appConfig: Then use it to run: ```bash -git clone https://github.com/spotify/backstage.git +git clone https://github.com/backstage/backstage.git cd contrib/chart/backstage helm dependency update helm install -f backstage-mydomain.yaml backstage . @@ -61,4 +61,4 @@ backstage-ingress * 123.1.2.3 80 17m > **NOTE**: this is not a production ready deployment. For more information on how to customize the deployment check the -[README](https://github.com/spotify/backstage/tree/master/contrib/chart/backstage/README.md). +[README](https://github.com/backstage/backstage/tree/master/contrib/chart/backstage/README.md). diff --git a/docs/getting-started/deployment-k8s.md b/docs/getting-started/deployment-k8s.md index f123dd2548..bc24894ed1 100644 --- a/docs/getting-started/deployment-k8s.md +++ b/docs/getting-started/deployment-k8s.md @@ -9,5 +9,5 @@ Beyond that point we do not have an opinionated way to deploy Backstage within Kubernetes, as each cluster has its own unique set of tooling and patterns. We do provide examples to help you get started though. Check out -[this example](https://github.com/spotify/backstage/tree/master/contrib/kubernetes/plain_single_backend_deplyoment/) +[this example](https://github.com/backstage/backstage/tree/master/contrib/kubernetes/plain_single_backend_deployment/) for a basic single-deployment setup. diff --git a/docs/getting-started/development-environment.md b/docs/getting-started/development-environment.md index aa9aa0bde1..c5275114ce 100644 --- a/docs/getting-started/development-environment.md +++ b/docs/getting-started/development-environment.md @@ -56,7 +56,7 @@ system resources and slow things down. ## Package Scripts There are many commands to be found in the root -[package.json](https://github.com/spotify/backstage/blob/master/package.json), +[package.json](https://github.com/backstage/backstage/blob/master/package.json), here are some useful ones: ```python @@ -86,7 +86,7 @@ yarn create-plugin # Create a new plugin ``` > See -> [package.json](https://github.com/spotify/backstage/blob/master/package.json) +> [package.json](https://github.com/backstage/backstage/blob/master/package.json) > for other yarn commands/options. ## Local configuration diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 855c8b0634..7fc80b625c 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -24,7 +24,7 @@ Requests towards this repo. Backstage provides the `@backstage/create-app` package to scaffold standalone instances of Backstage. You will need to have [Node.js](https://nodejs.org/en/download/) Active LTS Release installed -(currently v12), [Yarn](https://classic.yarnpkg.com/en/docs/install) and +(currently v14), [Yarn](https://classic.yarnpkg.com/en/docs/install) and [Python](https://www.python.org/downloads/) (although you likely have it already). You will also need to have [Docker](https://docs.docker.com/engine/install/) installed to use some features @@ -44,7 +44,7 @@ look something like this. You can read more about this process in ### Contributing to Backstage You can read more in our -[CONTRIBUTING](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md) +[CONTRIBUTING](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md) guide, which can help you get setup with a Backstage development environment. ### Next steps diff --git a/docs/getting-started/running-backstage-locally.md b/docs/getting-started/running-backstage-locally.md index 1a9097afd3..a30a918fd0 100644 --- a/docs/getting-started/running-backstage-locally.md +++ b/docs/getting-started/running-backstage-locally.md @@ -42,7 +42,7 @@ of GitHub and run an initial build. ```bash # Start from your local development folder -git clone --depth 1 git@github.com:spotify/backstage.git +git clone --depth 1 git@github.com:backstage/backstage.git cd backstage # Fetch our dependencies and run an initial build @@ -84,19 +84,19 @@ exploring. But you can also set up any of the available authentication methods. The easiest option will be GitHub. To setup GitHub authentication in Backstage, see -[these instructions](https://github.com/spotify/backstage/tree/master/plugins/auth-backend#github). +[these instructions](https://github.com/backstage/backstage/tree/master/plugins/auth-backend#github). --- Congratulations! That should be it. Let us know how it went [on discord](https://discord.gg/EBHEGzX), file issues for any -[feature](https://github.com/spotify/backstage/issues/new?labels=help+wanted&template=feature_template.md) +[feature](https://github.com/backstage/backstage/issues/new?labels=help+wanted&template=feature_template.md) or -[plugin suggestions](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME), +[plugin suggestions](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME), or -[bugs](https://github.com/spotify/backstage/issues/new?labels=bug&template=bug_template.md) +[bugs](https://github.com/backstage/backstage/issues/new?labels=bug&template=bug_template.md) you have, and feel free to -[contribute](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md)! +[contribute](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md)! ## Creating a Plugin diff --git a/docs/openapi/definitions/auth.yaml b/docs/openapi/definitions/auth.yaml index cb736fd2a9..411ce69253 100644 --- a/docs/openapi/definitions/auth.yaml +++ b/docs/openapi/definitions/auth.yaml @@ -12,14 +12,14 @@ info: The API is supplied with a list of providers - such as `Google` or `Github` - and will add the endpoints described below to each of those providers. - Read more about [User Authentication and Authorization in Backstage](https://github.com/spotify/backstage/blob/master/docs/auth/overview.md). + Read more about [User Authentication and Authorization in Backstage](https://github.com/backstage/backstage/blob/master/docs/auth/overview.md). license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html version: 0.1.1-alpha.8 externalDocs: description: Backstage official documentation - url: https://github.com/spotify/backstage/blob/master/docs/README.md + url: https://github.com/backstage/backstage/blob/master/docs/README.md servers: - url: http://localhost:7000/api/auth/ tags: diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md index 6f3c6b1a71..d8069c8665 100644 --- a/docs/overview/architecture-overview.md +++ b/docs/overview/architecture-overview.md @@ -63,17 +63,17 @@ Each plugin is a client side application which mounts itself on the UI. Plugins are written in TypeScript or JavaScript. They each live in their own directory in `backstage/plugins`. For example, the source code for the lighthouse plugin is available at -[backstage/plugins/lighthouse](https://github.com/spotify/backstage/tree/master/plugins/lighthouse). +[backstage/plugins/lighthouse](https://github.com/backstage/backstage/tree/master/plugins/lighthouse). ### Installing plugins Plugins are typically loaded by the UI in your Backstage applications `plugins.ts` file. For example, -[here](https://github.com/spotify/backstage/blob/master/packages/app/src/plugins.ts) +[here](https://github.com/backstage/backstage/blob/master/packages/app/src/plugins.ts) is that file in the Backstage sample app. Plugins can be enabled, and passed configuration in `apis.ts`. For example, -[here](https://github.com/spotify/backstage/blob/master/packages/app/src/apis.ts) +[here](https://github.com/backstage/backstage/blob/master/packages/app/src/apis.ts) is that file in the Backstage sample app. This is how the Lighthouse plugin would be enabled in a typical Backstage @@ -148,7 +148,7 @@ The CircleCI plugin is an example of a third-party backed plugin. CircleCI is a SaaS service which can be used without any knowledge of Backstage. It has an API which a Backstage plugin consumes to display content. -Requests which go to CircleCI from the users browser are passed through a proxy +Requests going to CircleCI from the user's browser are passed through a proxy service that Backstage provides. Without this, the requests would be blocked by Cross Origin Resource Sharing policies which prevent a browser page served at [https://example.com](https://example.com) from serving resources hosted at @@ -161,16 +161,18 @@ https://circleci.com. As we have seen, both the `lighthouse-audit-service` and `catalog-backend` require a database to work with. -At the time of writing, the `lighthouse-audit-service` requires PostgreSQL to -work with. The service catalog backend uses an in-memory Sqlite3 instance. This -is a development-oriented setup and there are plans to support other databases -in the future. +The Backstage backend and its builtin plugins are based on the +[Knex](http://knexjs.org/) library, and set up a separate logical database per +plugin. This gives great isolation and lets them perform migrations and evolve +separate from each other. -To learn more about the future of databases and Backstage, see the following -GitHub issues. - -- [Knex + Plugins (Multiple vs Single Database) · Issue #1598 · spotify/backstage](https://github.com/spotify/backstage/issues/1598) -- [Update migrations to support postgres by dariddler · Pull Request #1527 · spotify/backstage](https://github.com/spotify/backstage/pull/1527#discussion_r450374145) +The Knex library supports a multitude of databases, but Backstage is at the time +of writing tested primarily against two of them: SQLite, which is mainly used as +an in-memory mock/test database, and PostgreSQL, which is the preferred +production database. Other databases such as the MySQL variants are reported to +work but +[aren't tested as fully](https://github.com/backstage/backstage/issues/2460) +yet. ## Containerization diff --git a/docs/overview/logos.md b/docs/overview/logos.md index 2a684420bc..4c0c345f36 100644 --- a/docs/overview/logos.md +++ b/docs/overview/logos.md @@ -8,7 +8,7 @@ description: Guidelines for how to use the Backstage logos and icons Guidelines for how to use the Backstage logo and icon can be found [here](/logo_assets/Backstage_Identity_Assets_Overview.pdf). The assets below are all in `.svg` format. Other formats are available in the -[repository](https://github.com/spotify/backstage/tree/master/microsite/static/logo_assets). +[repository](https://github.com/backstage/backstage/tree/master/microsite/static/logo_assets). ## Backstage logo diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index 51f09347ce..5ff4d49a7c 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -9,8 +9,8 @@ description: Roadmap of Backstage Project > Backstage is currently under rapid development. This means that you can expect > APIs and features to evolve. It is also recommended that teams who adopt > Backstage today upgrade their installation as new -> [releases](https://github.com/spotify/backstage/releases) become available, as -> Backwards compatibility is not yet guaranteed. +> [releases](https://github.com/backstage/backstage/releases) become available, +> as Backwards compatibility is not yet guaranteed. ## Phases @@ -37,34 +37,34 @@ We have divided the project into three high-level _phases_: If you have questions about the roadmap or want to provide feedback, we would love to hear from you! Please create an -[Issue](https://github.com/spotify/backstage/issues/new/choose), ping us on +[Issue](https://github.com/backstage/backstage/issues/new/choose), ping us on [Discord](https://discord.gg/EBHEGzX) or reach out directly at [alund@spotify.com](mailto:alund@spotify.com). Want to help out? Awesome ❤️ Head over to -[CONTRIBUTING](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md) +[CONTRIBUTING](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md) guidelines to get started. ### Ongoing work 🚧 -- **[Plugins for managing micro services end-2-end](https://github.com/spotify/backstage/milestone/14)** +- **[Plugins for managing micro services end-2-end](https://github.com/backstage/backstage/milestone/14)** Out of the box Backstage will ship with a set of plugins (Overview, CI, API and Docs) that will demonstrate how a user can manage a micro service and follow a change all the way out in production. Completing this work will make it much easier to see how a plugin can be built that integrates with the Backstage Service Catalog. -- **[Users and teams](https://github.com/spotify/backstage/issues/1807)** +- **[Users and teams](https://github.com/backstage/backstage/issues/1807)** Ownership is a central concept in Backstage. It should be easy to import your existing organizational data, such as users and groups/teams, into Backstage. A user the logs into Backstage should see software components owned by the team(s) they are in. -- **[Backstage platform is stable](https://github.com/spotify/backstage/milestone/19)** - +- **[Backstage platform is stable](https://github.com/backstage/backstage/milestone/19)** - The platform APIs and features are stable and can be depended on for production use. After this plugins will require little to no maintenance. -* **[Improved Kubernetes plugin](https://github.com/spotify/backstage/issues/2857)** - +* **[Improved Kubernetes plugin](https://github.com/backstage/backstage/issues/2857)** - Native support for Kubernetes, making it easier for developers to see and manage their services running in k8s. @@ -77,21 +77,21 @@ guidelines to get started. deployment available publicly so that people can click around and get a feel for the product without having to install anything. -- **[Global search](https://github.com/spotify/backstage/issues/1499)** - Extend - the basic search available in the Backstage Service Catalog with a global - search experience. Long term this search solution should be extensible, making - it possible for you add custom search results. +- **[Global search](https://github.com/backstage/backstage/issues/1499)** - + Extend the basic search available in the Backstage Service Catalog with a + global search experience. Long term this search solution should be extensible, + making it possible for you add custom search results. -- **[[TechDocs V.2] Stabilization release](https://github.com/spotify/backstage/milestone/17)** - +- **[[TechDocs V.2] Stabilization release](https://github.com/backstage/backstage/milestone/17)** - Platform stability and compatibility improvements. - **Additional auth providers** - Backstage should work for most (all!) auth solutions. Since Backstage can be used by companies regardless of what cloud (or on prem) you are using we are especially keen to get auth support for - [AWS](https://github.com/spotify/backstage/issues/290), - [Azure](https://github.com/spotify/backstage/issues/348) and others. + [AWS](https://github.com/backstage/backstage/issues/290), + [Azure](https://github.com/backstage/backstage/issues/348) and others. -- **[Initial GraphQL API](https://github.com/spotify/backstage/milestone/13)** - +- **[Initial GraphQL API](https://github.com/backstage/backstage/milestone/13)** - A GraphQL API will open up the rich metadata provided by Backstage in a single query. Plugins can easily query this API as well as extend the model where needed. @@ -102,18 +102,18 @@ Building and maintaining [plugins](https://backstage.io/plugins) is the work of the entire Backstage community. A list of plugins that are in development is -[available here](https://github.com/spotify/backstage/issues?q=is%3Aissue+is%3Aopen+label%3Aplugin+sort%3Areactions-%2B1-desc). +[available here](https://github.com/backstage/backstage/issues?q=is%3Aissue+is%3Aopen+label%3Aplugin+sort%3Areactions-%2B1-desc). We strongly recommend to upvote 👍 plugins you are interested in. This helps us and the community prioritize what plugins to build. Are you missing a plugin for your favorite tool? Please -[suggest a new one](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). +[suggest a new one](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). Chances are that someone will jump in and help build it. ### Completed milestones ✅ -- [Kubernetes plugin - v1](https://github.com/spotify/backstage/tree/master/plugins/kubernetes) -- [Helm charts](https://github.com/spotify/backstage/tree/master/contrib/chart/backstage) +- [Kubernetes plugin - v1](https://github.com/backstage/backstage/tree/master/plugins/kubernetes) +- [Helm charts](https://github.com/backstage/backstage/tree/master/contrib/chart/backstage) - [Backstage Design System 💅](https://backstage.io/blog/2020/09/30/backstage-design-system) - [Cost Insights plugin 💸](https://engineering.atspotify.com/2020/09/29/managing-clouds-from-the-ground-up-cost-engineering-at-spotify/) - [Donate Backstage to the CNCF 🎉](https://backstage.io/blog/2020/09/23/backstage-cncf-sandbox) @@ -123,11 +123,11 @@ Chances are that someone will jump in and help build it. - [Backstage Service Catalog (alpha)](https://backstage.io/blog/2020/06/22/backstage-service-catalog-alpha) - [Backstage Software Templates (alpha)](https://backstage.io/blog/2020/08/05/announcing-backstage-software-templates) - [Make it possible to add custom auth providers](https://backstage.io/blog/2020/07/01/how-to-enable-authentication-in-backstage-using-passport) -- [TechDocs v0](https://github.com/spotify/backstage/milestone/15) +- [TechDocs v0](https://github.com/backstage/backstage/milestone/15) - CI plugins: CircleCI, Jenkins, GitHub Actions and TravisCI -- [Service API documentation](https://github.com/spotify/backstage/pull/1737) +- [Service API documentation](https://github.com/backstage/backstage/pull/1737) - Backstage Service Catalog can read from: GitHub, GitLab, - [Bitbucket](https://github.com/spotify/backstage/pull/1938) + [Bitbucket](https://github.com/backstage/backstage/pull/1938) - Support auth providers: Google, Okta, GitHub, GitLab, - [auth0](https://github.com/spotify/backstage/pull/1611), - [AWS](https://github.com/spotify/backstage/pull/1990) + [auth0](https://github.com/backstage/backstage/pull/1611), + [AWS](https://github.com/backstage/backstage/pull/1990) diff --git a/docs/overview/what-is-backstage.md b/docs/overview/what-is-backstage.md index 3d41c714ee..5439b838bd 100644 --- a/docs/overview/what-is-backstage.md +++ b/docs/overview/what-is-backstage.md @@ -30,7 +30,7 @@ Out of the box, Backstage includes: code" approach - Plus, a growing ecosystem of - [open source plugins](https://github.com/spotify/backstage/tree/master/plugins) + [open source plugins](https://github.com/backstage/backstage/tree/master/plugins) that further expand Backstage’s customizability and functionality ## Backstage and the CNCF diff --git a/docs/plugins/add-to-marketplace.md b/docs/plugins/add-to-marketplace.md index 59cca07bff..790512e6aa 100644 --- a/docs/plugins/add-to-marketplace.md +++ b/docs/plugins/add-to-marketplace.md @@ -8,7 +8,7 @@ description: Documentation on Adding Plugin to Marketplace To add a new plugin to the [plugin marketplace](https://backstage.io/plugins) create a file in -[`microsite/data/plugins`](https://github.com/spotify/backstage/tree/master/microsite/data/plugins) +[`microsite/data/plugins`](https://github.com/backstage/backstage/tree/master/microsite/data/plugins) with your plugin's information. Example: ```yaml diff --git a/docs/plugins/call-existing-api.md b/docs/plugins/call-existing-api.md index 3fff90c3f6..75e054d2b9 100644 --- a/docs/plugins/call-existing-api.md +++ b/docs/plugins/call-existing-api.md @@ -137,7 +137,7 @@ router.use('/summary', async (req, res) => { ``` For a more detailed example, see -[the lighthouse plugin](https://github.com/spotify/backstage/tree/master/plugins/lighthouse) +[the lighthouse plugin](https://github.com/backstage/backstage/tree/master/plugins/lighthouse) that stores some state in a database and adds new capabilities to the underlying API. diff --git a/docs/plugins/index.md b/docs/plugins/index.md index 8836c1cd42..dcef3f995c 100644 --- a/docs/plugins/index.md +++ b/docs/plugins/index.md @@ -22,7 +22,7 @@ To create a plugin, follow the steps outlined [here](create-a-plugin.md). If you start developing a plugin that you aim to release as open source, we suggest that you create a -[new Issue](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). +[new Issue](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). This helps the community know what plugins are in development. You can also use this process if you have an idea for a good plugin but you hope diff --git a/docs/plugins/publishing.md b/docs/plugins/publishing.md index fbeab6340c..7eab61891e 100644 --- a/docs/plugins/publishing.md +++ b/docs/plugins/publishing.md @@ -7,7 +7,7 @@ description: Documentation on Publishing NPM packages ## NPM NPM packages are published through CI/CD in the -[.github/workflows/master.yml](https://github.com/spotify/backstage/blob/master/.github/workflows/master.yml) +[.github/workflows/master.yml](https://github.com/backstage/backstage/blob/master/.github/workflows/master.yml) workflow. Every commit that is merged to master will be checked for new versions of all public packages, and any new versions will automatically be published to NPM. @@ -56,5 +56,3 @@ $ git reset --hard master $ yarn release $ git push --force ``` - -[Back to Docs](../README.md) diff --git a/docs/plugins/structure-of-a-plugin.md b/docs/plugins/structure-of-a-plugin.md index 0f11896f7a..3f631a9a46 100644 --- a/docs/plugins/structure-of-a-plugin.md +++ b/docs/plugins/structure-of-a-plugin.md @@ -106,6 +106,6 @@ environment you will probably face challenges like CORS policies and/or backend-side authorization. To smooth this process out you can use proxy - either the one you already have (like Nginx, HAProxy, etc.) or the proxy-backend plugin that we provide for the Backstage backend. -[Read more](https://github.com/spotify/backstage/blob/master/plugins/proxy-backend/README.md) +[Read more](https://github.com/backstage/backstage/blob/master/plugins/proxy-backend/README.md) [Back to Getting Started](../README.md) diff --git a/docs/reference/utility-apis/AlertApi.md b/docs/reference/utility-apis/AlertApi.md index 7d3167fdb7..4116e964ae 100644 --- a/docs/reference/utility-apis/AlertApi.md +++ b/docs/reference/utility-apis/AlertApi.md @@ -1,7 +1,7 @@ # AlertApi The AlertApi type is defined at -[packages/core-api/src/apis/definitions/AlertApi.ts:29](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AlertApi.ts#L29). +[packages/core-api/src/apis/definitions/AlertApi.ts:29](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AlertApi.ts#L29). The following Utility API implements this type: [alertApiRef](./README.md#alert) @@ -38,7 +38,7 @@ export type AlertMessage = { Defined at -[packages/core-api/src/apis/definitions/AlertApi.ts:19](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AlertApi.ts#L19). +[packages/core-api/src/apis/definitions/AlertApi.ts:19](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AlertApi.ts#L19). Referenced by: [post](#post), [alert\$](#alert). @@ -67,7 +67,7 @@ export type Observable<T> = { Defined at -[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). +[packages/core-api/src/types.ts:53](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). Referenced by: [alert\$](#alert). @@ -86,7 +86,7 @@ export type Observer<T> = { Defined at -[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). +[packages/core-api/src/types.ts:24](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). Referenced by: [Observable](#observable). @@ -109,6 +109,6 @@ export type Subscription = { Defined at -[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). +[packages/core-api/src/types.ts:33](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). Referenced by: [Observable](#observable). diff --git a/docs/reference/utility-apis/AppThemeApi.md b/docs/reference/utility-apis/AppThemeApi.md index e103511246..0f5c095825 100644 --- a/docs/reference/utility-apis/AppThemeApi.md +++ b/docs/reference/utility-apis/AppThemeApi.md @@ -1,7 +1,7 @@ # AppThemeApi The AppThemeApi type is defined at -[packages/core-api/src/apis/definitions/AppThemeApi.ts:56](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AppThemeApi.ts#L56). +[packages/core-api/src/apis/definitions/AppThemeApi.ts:56](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AppThemeApi.ts#L56). The following Utility API implements this type: [appThemeApiRef](./README.md#apptheme) @@ -81,7 +81,7 @@ export type AppTheme = { Defined at -[packages/core-api/src/apis/definitions/AppThemeApi.ts:25](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AppThemeApi.ts#L25). +[packages/core-api/src/apis/definitions/AppThemeApi.ts:25](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AppThemeApi.ts#L25). Referenced by: [getInstalledThemes](#getinstalledthemes). @@ -92,7 +92,7 @@ export type BackstagePalette = Palette & Palette Defined at -[packages/theme/src/types.ts:74](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L74). +[packages/theme/src/types.ts:74](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L74). Referenced by: [BackstageTheme](#backstagetheme). @@ -107,7 +107,7 @@ export interface BackstageTheme extends Theme { Defined at -[packages/theme/src/types.ts:81](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L81). +[packages/theme/src/types.ts:81](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L81). Referenced by: [AppTheme](#apptheme). @@ -136,7 +136,7 @@ export type Observable<T> = { Defined at -[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). +[packages/core-api/src/types.ts:53](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). Referenced by: [activeThemeId\$](#activethemeid). @@ -155,7 +155,7 @@ export type Observer<T> = { Defined at -[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). +[packages/core-api/src/types.ts:24](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). Referenced by: [Observable](#observable). @@ -170,7 +170,7 @@ export type PageTheme = { Defined at -[packages/theme/src/types.ts:103](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L103). +[packages/theme/src/types.ts:103](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L103). Referenced by: [BackstageTheme](#backstagetheme). @@ -183,7 +183,7 @@ export type PageThemeSelector = { Defined at -[packages/theme/src/types.ts:77](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L77). +[packages/theme/src/types.ts:77](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L77). Referenced by: [BackstageTheme](#backstagetheme). @@ -243,7 +243,7 @@ type PaletteAdditions = { Defined at -[packages/theme/src/types.ts:23](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L23). +[packages/theme/src/types.ts:23](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/theme/src/types.ts#L23). Referenced by: [BackstagePalette](#backstagepalette). @@ -266,6 +266,6 @@ export type Subscription = { Defined at -[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). +[packages/core-api/src/types.ts:33](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). Referenced by: [Observable](#observable). diff --git a/docs/reference/utility-apis/BackstageIdentityApi.md b/docs/reference/utility-apis/BackstageIdentityApi.md index 4e86717101..dafdb7d55f 100644 --- a/docs/reference/utility-apis/BackstageIdentityApi.md +++ b/docs/reference/utility-apis/BackstageIdentityApi.md @@ -1,7 +1,7 @@ # BackstageIdentityApi The BackstageIdentityApi type is defined at -[packages/core-api/src/apis/definitions/auth.ts:134](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L134). +[packages/core-api/src/apis/definitions/auth.ts:134](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L134). The following Utility APIs implement this type: @@ -70,7 +70,7 @@ export type AuthRequestOptions = { Defined at -[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L40). +[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L40). Referenced by: [getBackstageIdentity](#getbackstageidentity). @@ -91,6 +91,6 @@ export type BackstageIdentity = { Defined at -[packages/core-api/src/apis/definitions/auth.ts:147](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L147). +[packages/core-api/src/apis/definitions/auth.ts:147](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L147). Referenced by: [getBackstageIdentity](#getbackstageidentity). diff --git a/docs/reference/utility-apis/Config.md b/docs/reference/utility-apis/Config.md index 9d184dd56a..2ae047a700 100644 --- a/docs/reference/utility-apis/Config.md +++ b/docs/reference/utility-apis/Config.md @@ -1,7 +1,7 @@ # Config The Config type is defined at -[packages/config/src/types.ts:32](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L32). +[packages/config/src/types.ts:32](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L32). The following Utility API implements this type: [configApiRef](./README.md#config) @@ -140,7 +140,7 @@ export type Config = { Defined at -[packages/config/src/types.ts:32](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L32). +[packages/config/src/types.ts:32](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L32). Referenced by: [getConfig](#getconfig), [getOptionalConfig](#getoptionalconfig), [getConfigArray](#getconfigarray), @@ -153,7 +153,7 @@ export type JsonArray = JsonValue[] Defined at -[packages/config/src/types.ts:18](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L18). +[packages/config/src/types.ts:18](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L18). Referenced by: [JsonValue](#jsonvalue). @@ -164,7 +164,7 @@ export type JsonObject = { [key in string]?: JsonValue Defined at -[packages/config/src/types.ts:17](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L17). +[packages/config/src/types.ts:17](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L17). Referenced by: [JsonValue](#jsonvalue). @@ -181,7 +181,7 @@ export type JsonValue = Defined at -[packages/config/src/types.ts:19](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L19). +[packages/config/src/types.ts:19](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/config/src/types.ts#L19). Referenced by: [get](#get), [getOptional](#getoptional), [JsonObject](#jsonobject), [JsonArray](#jsonarray), [Config](#config). diff --git a/docs/reference/utility-apis/DiscoveryApi.md b/docs/reference/utility-apis/DiscoveryApi.md index 72f37dc58d..ac278fdd97 100644 --- a/docs/reference/utility-apis/DiscoveryApi.md +++ b/docs/reference/utility-apis/DiscoveryApi.md @@ -1,7 +1,7 @@ # DiscoveryApi The DiscoveryApi type is defined at -[packages/core-api/src/apis/definitions/DiscoveryApi.ts:30](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/DiscoveryApi.ts#L30). +[packages/core-api/src/apis/definitions/DiscoveryApi.ts:30](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/DiscoveryApi.ts#L30). The following Utility API implements this type: [discoveryApiRef](./README.md#discovery) diff --git a/docs/reference/utility-apis/ErrorApi.md b/docs/reference/utility-apis/ErrorApi.md index 2234aaa543..93f4f9cd48 100644 --- a/docs/reference/utility-apis/ErrorApi.md +++ b/docs/reference/utility-apis/ErrorApi.md @@ -1,7 +1,7 @@ # ErrorApi The ErrorApi type is defined at -[packages/core-api/src/apis/definitions/ErrorApi.ts:53](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ErrorApi.ts#L53). +[packages/core-api/src/apis/definitions/ErrorApi.ts:53](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ErrorApi.ts#L53). The following Utility API implements this type: [errorApiRef](./README.md#error) @@ -41,7 +41,7 @@ type Error = { Defined at -[packages/core-api/src/apis/definitions/ErrorApi.ts:24](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ErrorApi.ts#L24). +[packages/core-api/src/apis/definitions/ErrorApi.ts:24](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ErrorApi.ts#L24). Referenced by: [post](#post), [error\$](#error). @@ -58,7 +58,7 @@ export type ErrorContext = { Defined at -[packages/core-api/src/apis/definitions/ErrorApi.ts:33](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ErrorApi.ts#L33). +[packages/core-api/src/apis/definitions/ErrorApi.ts:33](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ErrorApi.ts#L33). Referenced by: [post](#post), [error\$](#error). @@ -87,7 +87,7 @@ export type Observable<T> = { Defined at -[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). +[packages/core-api/src/types.ts:53](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). Referenced by: [error\$](#error). @@ -106,7 +106,7 @@ export type Observer<T> = { Defined at -[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). +[packages/core-api/src/types.ts:24](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). Referenced by: [Observable](#observable). @@ -129,6 +129,6 @@ export type Subscription = { Defined at -[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). +[packages/core-api/src/types.ts:33](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). Referenced by: [Observable](#observable). diff --git a/docs/reference/utility-apis/FeatureFlagsApi.md b/docs/reference/utility-apis/FeatureFlagsApi.md index ed04ecfd8d..529d2ac5dc 100644 --- a/docs/reference/utility-apis/FeatureFlagsApi.md +++ b/docs/reference/utility-apis/FeatureFlagsApi.md @@ -1,7 +1,7 @@ # FeatureFlagsApi The FeatureFlagsApi type is defined at -[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:60](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L60). +[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:60](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L60). The following Utility API implements this type: [featureFlagsApiRef](./README.md#featureflags) @@ -68,7 +68,7 @@ export type FeatureFlag = { Defined at -[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:31](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L31). +[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:31](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L31). Referenced by: [registerFlag](#registerflag), [getRegisteredFlags](#getregisteredflags). @@ -83,7 +83,7 @@ export enum FeatureFlagState { Defined at -[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:36](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L36). +[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:36](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L36). Referenced by: [FeatureFlagsSaveOptions](#featureflagssaveoptions). @@ -108,6 +108,6 @@ export type FeatureFlagsSaveOptions = { Defined at -[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:44](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L44). +[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:44](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L44). Referenced by: [save](#save). diff --git a/docs/reference/utility-apis/IdentityApi.md b/docs/reference/utility-apis/IdentityApi.md index 51ea146eec..a88aaf0b8a 100644 --- a/docs/reference/utility-apis/IdentityApi.md +++ b/docs/reference/utility-apis/IdentityApi.md @@ -1,7 +1,7 @@ # IdentityApi The IdentityApi type is defined at -[packages/core-api/src/apis/definitions/IdentityApi.ts:22](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/IdentityApi.ts#L22). +[packages/core-api/src/apis/definitions/IdentityApi.ts:22](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/IdentityApi.ts#L22). The following Utility API implements this type: [identityApiRef](./README.md#identity) @@ -76,6 +76,6 @@ export type ProfileInfo = { Defined at -[packages/core-api/src/apis/definitions/auth.ts:162](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L162). +[packages/core-api/src/apis/definitions/auth.ts:162](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L162). Referenced by: [getProfile](#getprofile). diff --git a/docs/reference/utility-apis/OAuthApi.md b/docs/reference/utility-apis/OAuthApi.md index 42517410fa..79b55812ef 100644 --- a/docs/reference/utility-apis/OAuthApi.md +++ b/docs/reference/utility-apis/OAuthApi.md @@ -1,7 +1,7 @@ # OAuthApi The OAuthApi type is defined at -[packages/core-api/src/apis/definitions/auth.ts:67](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L67). +[packages/core-api/src/apis/definitions/auth.ts:67](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L67). The following Utility APIs implement this type: @@ -82,7 +82,7 @@ export type AuthRequestOptions = { Defined at -[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L40). +[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L40). Referenced by: [getAccessToken](#getaccesstoken). @@ -108,6 +108,6 @@ export type OAuthScope = string | string[] Defined at -[packages/core-api/src/apis/definitions/auth.ts:38](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L38). +[packages/core-api/src/apis/definitions/auth.ts:38](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L38). Referenced by: [getAccessToken](#getaccesstoken). diff --git a/docs/reference/utility-apis/OAuthRequestApi.md b/docs/reference/utility-apis/OAuthRequestApi.md index 690df9dbff..f1c2311ce9 100644 --- a/docs/reference/utility-apis/OAuthRequestApi.md +++ b/docs/reference/utility-apis/OAuthRequestApi.md @@ -1,7 +1,7 @@ # OAuthRequestApi The OAuthRequestApi type is defined at -[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:99](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L99). +[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:99](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L99). The following Utility API implements this type: [oauthRequestApiRef](./README.md#oauthrequest) @@ -73,7 +73,7 @@ export type AuthProvider = { Defined at -[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:27](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L27). +[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:27](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L27). Referenced by: [AuthRequesterOptions](#authrequesteroptions), [PendingAuthRequest](#pendingauthrequest). @@ -97,7 +97,7 @@ export type AuthRequester<AuthResponse> = ( Defined at -[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:66](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L66). +[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:66](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L66). Referenced by: [createAuthRequester](#createauthrequester). @@ -122,7 +122,7 @@ export type AuthRequesterOptions<AuthResponse> = { Defined at -[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:43](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L43). +[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:43](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L43). Referenced by: [createAuthRequester](#createauthrequester). @@ -151,7 +151,7 @@ export type Observable<T> = { Defined at -[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). +[packages/core-api/src/types.ts:53](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). Referenced by: [authRequest\$](#authrequest). @@ -170,7 +170,7 @@ export type Observer<T> = { Defined at -[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). +[packages/core-api/src/types.ts:24](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). Referenced by: [Observable](#observable). @@ -205,7 +205,7 @@ export type PendingAuthRequest = { Defined at -[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:77](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L77). +[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:77](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L77). Referenced by: [authRequest\$](#authrequest). @@ -228,6 +228,6 @@ export type Subscription = { Defined at -[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). +[packages/core-api/src/types.ts:33](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). Referenced by: [Observable](#observable). diff --git a/docs/reference/utility-apis/OpenIdConnectApi.md b/docs/reference/utility-apis/OpenIdConnectApi.md index 11ac589ef1..eaea530708 100644 --- a/docs/reference/utility-apis/OpenIdConnectApi.md +++ b/docs/reference/utility-apis/OpenIdConnectApi.md @@ -1,7 +1,7 @@ # OpenIdConnectApi The OpenIdConnectApi type is defined at -[packages/core-api/src/apis/definitions/auth.ts:99](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L99). +[packages/core-api/src/apis/definitions/auth.ts:99](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L99). The following Utility APIs implement this type: @@ -66,6 +66,6 @@ export type AuthRequestOptions = { Defined at -[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L40). +[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L40). Referenced by: [getIdToken](#getidtoken). diff --git a/docs/reference/utility-apis/ProfileInfoApi.md b/docs/reference/utility-apis/ProfileInfoApi.md index c5b2ae456b..76d04045e8 100644 --- a/docs/reference/utility-apis/ProfileInfoApi.md +++ b/docs/reference/utility-apis/ProfileInfoApi.md @@ -1,7 +1,7 @@ # ProfileInfoApi The ProfileInfoApi type is defined at -[packages/core-api/src/apis/definitions/auth.ts:117](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L117). +[packages/core-api/src/apis/definitions/auth.ts:117](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L117). The following Utility APIs implement this type: @@ -67,7 +67,7 @@ export type AuthRequestOptions = { Defined at -[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L40). +[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L40). Referenced by: [getProfile](#getprofile). @@ -95,6 +95,6 @@ export type ProfileInfo = { Defined at -[packages/core-api/src/apis/definitions/auth.ts:162](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L162). +[packages/core-api/src/apis/definitions/auth.ts:162](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L162). Referenced by: [getProfile](#getprofile). diff --git a/docs/reference/utility-apis/README.md b/docs/reference/utility-apis/README.md index 84674d9fff..1ef5b6197e 100644 --- a/docs/reference/utility-apis/README.md +++ b/docs/reference/utility-apis/README.md @@ -3,7 +3,7 @@ The following is a list of all Utility APIs defined by `@backstage/core`. They are available to use by plugins and components, and can be accessed using the `useApi` hook, also provided by `@backstage/core`. For more information, see -https://github.com/spotify/backstage/blob/master/docs/api/utility-apis.md. +https://github.com/backstage/backstage/blob/master/docs/api/utility-apis.md. ### alert @@ -12,7 +12,7 @@ Used to report alerts and forward them to the app Implemented type: [AlertApi](./AlertApi.md) ApiRef: -[alertApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AlertApi.ts#L41) +[alertApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AlertApi.ts#L41) ### appTheme @@ -21,7 +21,7 @@ API Used to configure the app theme, and enumerate options Implemented type: [AppThemeApi](./AppThemeApi.md) ApiRef: -[appThemeApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AppThemeApi.ts#L80) +[appThemeApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/AppThemeApi.ts#L80) ### auth0Auth @@ -32,7 +32,7 @@ Implemented types: [OpenIdConnectApi](./OpenIdConnectApi.md), [BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md) ApiRef: -[auth0AuthApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L275) +[auth0AuthApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L275) ### config @@ -41,7 +41,7 @@ Used to access runtime configuration Implemented type: [Config](./Config.md) ApiRef: -[configApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ConfigApi.ts#L22) +[configApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ConfigApi.ts#L22) ### discovery @@ -50,7 +50,7 @@ Provides service discovery of backend plugins Implemented type: [DiscoveryApi](./DiscoveryApi.md) ApiRef: -[discoveryApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/DiscoveryApi.ts#L44) +[discoveryApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/DiscoveryApi.ts#L44) ### error @@ -59,7 +59,7 @@ Used to report errors and forward them to the app Implemented type: [ErrorApi](./ErrorApi.md) ApiRef: -[errorApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ErrorApi.ts#L65) +[errorApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/ErrorApi.ts#L65) ### featureFlags @@ -68,7 +68,7 @@ Used to toggle functionality in features across Backstage Implemented type: [FeatureFlagsApi](./FeatureFlagsApi.md) ApiRef: -[featureFlagsApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L83) +[featureFlagsApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L83) ### githubAuth @@ -79,7 +79,7 @@ Implemented types: [OAuthApi](./OAuthApi.md), [BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md) ApiRef: -[githubAuthApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L232) +[githubAuthApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L232) ### gitlabAuth @@ -90,7 +90,7 @@ Implemented types: [OAuthApi](./OAuthApi.md), [BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md) ApiRef: -[gitlabAuthApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L262) +[gitlabAuthApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L262) ### googleAuth @@ -102,7 +102,7 @@ Implemented types: [OAuthApi](./OAuthApi.md), [BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md) ApiRef: -[googleAuthApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L215) +[googleAuthApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L215) ### identity @@ -111,7 +111,7 @@ Provides access to the identity of the signed in user Implemented type: [IdentityApi](./IdentityApi.md) ApiRef: -[identityApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/IdentityApi.ts#L54) +[identityApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/IdentityApi.ts#L54) ### microsoftAuth @@ -123,7 +123,7 @@ Implemented types: [OAuthApi](./OAuthApi.md), [BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md) ApiRef: -[microsoftAuthApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L289) +[microsoftAuthApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L289) ### oauth2 @@ -135,7 +135,7 @@ Implemented types: [OAuthApi](./OAuthApi.md), [BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md) ApiRef: -[oauth2ApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L303) +[oauth2ApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L303) ### oauthRequest @@ -144,7 +144,7 @@ An API for implementing unified OAuth flows in Backstage Implemented type: [OAuthRequestApi](./OAuthRequestApi.md) ApiRef: -[oauthRequestApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L130) +[oauthRequestApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L130) ### oktaAuth @@ -156,7 +156,7 @@ Implemented types: [OAuthApi](./OAuthApi.md), [BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md) ApiRef: -[oktaAuthApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L245) +[oktaAuthApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L245) ### samlAuth @@ -166,7 +166,7 @@ Implemented types: [ProfileInfoApi](./ProfileInfoApi.md), [BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md) ApiRef: -[samlAuthApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L317) +[samlAuthApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L317) ### storage @@ -175,4 +175,4 @@ Provides the ability to store data which is unique to the user Implemented type: [StorageApi](./StorageApi.md) ApiRef: -[storageApiRef](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/StorageApi.ts#L68) +[storageApiRef](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/StorageApi.ts#L68) diff --git a/docs/reference/utility-apis/SessionApi.md b/docs/reference/utility-apis/SessionApi.md index f2e9097143..7d271558d6 100644 --- a/docs/reference/utility-apis/SessionApi.md +++ b/docs/reference/utility-apis/SessionApi.md @@ -1,7 +1,7 @@ # SessionApi The SessionApi type is defined at -[packages/core-api/src/apis/definitions/auth.ts:190](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L190). +[packages/core-api/src/apis/definitions/auth.ts:190](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L190). The following Utility APIs implement this type: @@ -77,7 +77,7 @@ export type Observable<T> = { Defined at -[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). +[packages/core-api/src/types.ts:53](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). Referenced by: [sessionState\$](#sessionstate). @@ -96,7 +96,7 @@ export type Observer<T> = { Defined at -[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). +[packages/core-api/src/types.ts:24](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). Referenced by: [Observable](#observable). @@ -112,7 +112,7 @@ export enum SessionState { Defined at -[packages/core-api/src/apis/definitions/auth.ts:182](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L182). +[packages/core-api/src/apis/definitions/auth.ts:182](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/auth.ts#L182). Referenced by: [sessionState\$](#sessionstate). @@ -135,6 +135,6 @@ export type Subscription = { Defined at -[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). +[packages/core-api/src/types.ts:33](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). Referenced by: [Observable](#observable). diff --git a/docs/reference/utility-apis/SessionStateApi.md b/docs/reference/utility-apis/SessionStateApi.md index 81f25aa349..a8a4c3bc3d 100644 --- a/docs/reference/utility-apis/SessionStateApi.md +++ b/docs/reference/utility-apis/SessionStateApi.md @@ -1,7 +1,7 @@ # SessionStateApi The SessionStateApi type is defined at -[packages/core-api/src/apis/definitions/auth.ts:201](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L201). +[packages/core-api/src/apis/definitions/auth.ts:201](https://github.com/backstage/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L201). The following Utility APIs implement this type: @@ -56,7 +56,7 @@ export type Observable<T> = { Defined at -[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L53). +[packages/core-api/src/types.ts:53](https://github.com/backstage/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L53). Referenced by: [sessionState\$](#sessionstate). @@ -75,7 +75,7 @@ export type Observer<T> = { Defined at -[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L24). +[packages/core-api/src/types.ts:24](https://github.com/backstage/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L24). Referenced by: [Observable](#observable). @@ -91,7 +91,7 @@ export enum SessionState { Defined at -[packages/core-api/src/apis/definitions/auth.ts:192](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L192). +[packages/core-api/src/apis/definitions/auth.ts:192](https://github.com/backstage/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L192). Referenced by: [sessionState\$](#sessionstate). @@ -114,6 +114,6 @@ export type Subscription = { Defined at -[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L33). +[packages/core-api/src/types.ts:33](https://github.com/backstage/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L33). Referenced by: [Observable](#observable). diff --git a/docs/reference/utility-apis/StorageApi.md b/docs/reference/utility-apis/StorageApi.md index 9fe10e358b..6c5595d3d8 100644 --- a/docs/reference/utility-apis/StorageApi.md +++ b/docs/reference/utility-apis/StorageApi.md @@ -1,7 +1,7 @@ # StorageApi The StorageApi type is defined at -[packages/core-api/src/apis/definitions/StorageApi.ts:31](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/StorageApi.ts#L31). +[packages/core-api/src/apis/definitions/StorageApi.ts:31](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/StorageApi.ts#L31). The following Utility API implements this type: [storageApiRef](./README.md#storage) @@ -79,7 +79,7 @@ export type Observable<T> = { Defined at -[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). +[packages/core-api/src/types.ts:53](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L53). Referenced by: [observe\$](#observe), [StorageApi](#storageapi). @@ -98,7 +98,7 @@ export type Observer<T> = { Defined at -[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). +[packages/core-api/src/types.ts:24](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L24). Referenced by: [Observable](#observable). @@ -144,7 +144,7 @@ export interface StorageApi { Defined at -[packages/core-api/src/apis/definitions/StorageApi.ts:31](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/StorageApi.ts#L31). +[packages/core-api/src/apis/definitions/StorageApi.ts:31](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/StorageApi.ts#L31). Referenced by: [forBucket](#forbucket). @@ -158,7 +158,7 @@ export type StorageValueChange<T = any> = { Defined at -[packages/core-api/src/apis/definitions/StorageApi.ts:21](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/StorageApi.ts#L21). +[packages/core-api/src/apis/definitions/StorageApi.ts:21](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/apis/definitions/StorageApi.ts#L21). Referenced by: [observe\$](#observe), [StorageApi](#storageapi). @@ -181,6 +181,6 @@ export type Subscription = { Defined at -[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). +[packages/core-api/src/types.ts:33](https://github.com/backstage/backstage/blob/ca535f2f66c3a4980c80f4b1a049dfd07569010e/packages/core-api/src/types.ts#L33). Referenced by: [Observable](#observable). diff --git a/docs/support/project-structure.md b/docs/support/project-structure.md index 9720c4db3e..034fba4cb8 100644 --- a/docs/support/project-structure.md +++ b/docs/support/project-structure.md @@ -15,48 +15,48 @@ In the project root, there are a set of files and folders which are not part of the project as such, and may or may not be familiar to someone looking through the code. -- [`.changeset/`](https://github.com/spotify/backstage/tree/master/.changeset) - +- [`.changeset/`](https://github.com/backstage/backstage/tree/master/.changeset) - This folder contains files outlining which changes occurred in the project since the last release. These files are added manually, but managed by [changesets](https://github.com/atlassian/changesets) and will be removed at every new release. They are essentially building-blocks of a CHANGELOG. -- [`.github/`](https://github.com/spotify/backstage/tree/master/.github) - +- [`.github/`](https://github.com/backstage/backstage/tree/master/.github) - Standard GitHub folder. It contains - amongst other things - our workflow definitions and templates. Worth noting is the - [styles](https://github.com/spotify/backstage/tree/master/.github/styles) + [styles](https://github.com/backstage/backstage/tree/master/.github/styles) folder which is used for a markdown spellchecker. -- [`.yarn/`](https://github.com/spotify/backstage/tree/master/.yarn) - Backstage - ships with it's own `yarn` implementation. This allows us to have better - control over our `yarn.lock` file and hopefully avoid problems due to yarn - versioning differences. +- [`.yarn/`](https://github.com/backstage/backstage/tree/master/.yarn) - + Backstage ships with it's own `yarn` implementation. This allows us to have + better control over our `yarn.lock` file and hopefully avoid problems due to + yarn versioning differences. -- [`docker/`](https://github.com/spotify/backstage/tree/master/docker) - Files +- [`docker/`](https://github.com/backstage/backstage/tree/master/docker) - Files related to our root Dockerfile. We are planning to refactor this, so expect this folder to be moved in the future. -- [`contrib/`](https://github.com/spotify/backstage/tree/master/contrib) - +- [`contrib/`](https://github.com/backstage/backstage/tree/master/contrib) - Collection of examples or resources provided by the community. We really appreciate contributions in here and encourage them being kept up to date. -- [`docs/`](https://github.com/spotify/backstage/tree/master/docs) - This is +- [`docs/`](https://github.com/backstage/backstage/tree/master/docs) - This is where we keep all of our documentation Markdown files. These ends up on http://backstage.io/docs. Just keep in mind that changes to the - [`sidebars.json`](https://github.com/spotify/backstage/blob/master/microsite/sidebars.json) + [`sidebars.json`](https://github.com/backstage/backstage/blob/master/microsite/sidebars.json) file may be needed as sections are added/removed. -- [`.editorconfig`](https://github.com/spotify/backstage/tree/master/.editorconfig) - +- [`.editorconfig`](https://github.com/backstage/backstage/tree/master/.editorconfig) - A configuration file used by most common code editors. -- [`.imgbotconfig`](https://github.com/spotify/backstage/tree/master/.imgbotconfig) - +- [`.imgbotconfig`](https://github.com/backstage/backstage/tree/master/.imgbotconfig) - Configuration for a [bot](https://imgbot.net/) ## Monorepo packages Every folder in both `packages/` and `plugins/` is within our monorepo setup, as defined in -[`package.json`](https://github.com/spotify/backstage/blob/master/package.json): +[`package.json`](https://github.com/backstage/backstage/blob/master/package.json): ```json "workspaces": { @@ -74,30 +74,30 @@ Let's look at them individually. These are all the packages that we use within the project. [Plugins](#plugins) are separated out into their own folder, see further down. -- [`app/`](https://github.com/spotify/backstage/tree/master/packages/app) - This - is our take on how an App could look like, bringing together a set of packages - and plugins into a working Backstage App. This is not a published package, and - the main goals are to provide a demo of what an App could look like and to - enable local development. +- [`app/`](https://github.com/backstage/backstage/tree/master/packages/app) - + This is our take on how an App could look like, bringing together a set of + packages and plugins into a working Backstage App. This is not a published + package, and the main goals are to provide a demo of what an App could look + like and to enable local development. -- [`backend/`](https://github.com/spotify/backstage/tree/master/packages/backend) - +- [`backend/`](https://github.com/backstage/backstage/tree/master/packages/backend) - Every standalone Backstage project will have both an `app` _and_ a `backend` package. The `backend` uses plugins to construct a working backend that the frontend (`app`) can use. -- [`backend-common/`](https://github.com/spotify/backstage/tree/master/packages/backend-common) - +- [`backend-common/`](https://github.com/backstage/backstage/tree/master/packages/backend-common) - There are no "core" packages in the backend. Instead we have `backend-common` which contains helper middleware and other utils. -- [`catalog-model/`](https://github.com/spotify/backstage/tree/master/packages/catalog-model) - +- [`catalog-model/`](https://github.com/backstage/backstage/tree/master/packages/catalog-model) - You can consider this to be a library for working with the catalog of sorts. It contains the definition of an [Entity](https://backstage.io/docs/features/software-catalog/references#docsNav), as well as validation and other logic related to it. This package can be used in both the frontend and the backend. -- [`cli/`](https://github.com/spotify/backstage/tree/master/packages/cli) - One - of the biggest packages in our project, the `cli` is used to build, serve, +- [`cli/`](https://github.com/backstage/backstage/tree/master/packages/cli) - + One of the biggest packages in our project, the `cli` is used to build, serve, diff, create-plugins and more. In the early days of this project, we started out with calling tools directly - such as `eslint` - through `package.json`. But as it was tricky to have a good development experience around that when we @@ -105,86 +105,81 @@ are separated out into their own folder, see further down. everything looks the same in `package.json`. Much like [react-scripts](https://github.com/facebook/create-react-app/tree/master/packages/react-scripts). -- [`cli-common/`](https://github.com/spotify/backstage/tree/master/packages/cli-common) - +- [`cli-common/`](https://github.com/backstage/backstage/tree/master/packages/cli-common) - This package mainly handles path resolving. It is a separate package to reduce - bugs in [cli](https://github.com/spotify/backstage/tree/master/packages/cli). - We also want as few dependencies as possible to reduce download time when - running the cli which is another reason this is a separate package. + bugs in + [cli](https://github.com/backstage/backstage/tree/master/packages/cli). We + also want as few dependencies as possible to reduce download time when running + the cli which is another reason this is a separate package. -- [`config/`](https://github.com/spotify/backstage/tree/master/packages/config) - +- [`config/`](https://github.com/backstage/backstage/tree/master/packages/config) - The way we read configuration data. This package can take a bunch of config objects and merge them together. - [app-config.yaml](https://github.com/spotify/backstage/blob/master/app-config.yaml) + [app-config.yaml](https://github.com/backstage/backstage/blob/master/app-config.yaml) is an example of an config object. -- [`config-loader/`](https://github.com/spotify/backstage/tree/master/packages/config-loader) - +- [`config-loader/`](https://github.com/backstage/backstage/tree/master/packages/config-loader) - This package is used to read config objects. It does not know how to merge, but only reads files and passes them on to the config. As this part is only used by the backend, we chose to separate `config` and `config-loader` into two different packages. -- [`core/`](https://github.com/spotify/backstage/tree/master/packages/core) - +- [`core/`](https://github.com/backstage/backstage/tree/master/packages/core) - This package contains our visual React components, some of which you can find in [plugin examples](https://backstage.io/storybook/?path=/story/plugins-examples--plugin-with-data). Apart from that it re-exports everything from [`core-api`] so that users only need to rely on one package. -- [`core-api/`](https://github.com/spotify/backstage/tree/master/packages/core-api) - +- [`core-api/`](https://github.com/backstage/backstage/tree/master/packages/core-api) - This package contains APIs and definitions of such. It is it's own package because we needed to split our `test-utils` package. It's an implementation detail that we try to hide from our users, and no one should have to depend on it directly. -- [`test-utils/`](https://github.com/spotify/backstage/tree/master/packages/test-utils) - +- [`test-utils/`](https://github.com/backstage/backstage/tree/master/packages/test-utils) - This package contains specific testing facilities used when testing `core-api`. -- [`test-utils-core/`](https://github.com/spotify/backstage/tree/master/packages/test-utils-core) - +- [`test-utils-core/`](https://github.com/backstage/backstage/tree/master/packages/test-utils-core) - This package contains more general purpose testing facilities for testing a Backstage App. -- [`create-app/`](https://github.com/spotify/backstage/tree/master/packages/create-app) - +- [`create-app/`](https://github.com/backstage/backstage/tree/master/packages/create-app) - An CLI to specifically scaffold a new Backstage App. It does so by using a - [template](https://github.com/spotify/backstage/tree/master/packages/create-app/templates/default-app). + [template](https://github.com/backstage/backstage/tree/master/packages/create-app/templates/default-app). -- [`dev-utils/`](https://github.com/spotify/backstage/tree/master/packages/dev-utils) - +- [`dev-utils/`](https://github.com/backstage/backstage/tree/master/packages/dev-utils) - Helps you setup a plugin for isolated development so that it can be served separately. -- [`docgen/`](https://github.com/spotify/backstage/tree/master/packages/docgen) - +- [`docgen/`](https://github.com/backstage/backstage/tree/master/packages/docgen) - Uses the [Typescript Compiler API](https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API) to read out definitions and generate documentation for it. -- [`e2e-test/`](https://github.com/spotify/backstage/tree/master/packages/e2e-test) - +- [`e2e-test/`](https://github.com/backstage/backstage/tree/master/packages/e2e-test) - Another CLI that can be run to try out what would happen if you built all the packages, publish them, created a new app, and the run it. CI uses this for e2e-tests. -- [`storybook/`](https://github.com/spotify/backstage/tree/master/packages/storybook) - +- [`storybook/`](https://github.com/backstage/backstage/tree/master/packages/storybook) - This folder contains only the storybook config. Stories are within the core package. The Backstage Storybook is found [here](https://backstage.io/storybook) -- [`techdocs-cli/`](https://github.com/spotify/backstage/tree/master/packages/techdocs-cli) - - Used for verifying TechDocs locally. +- [`test-utils-core/`](https://github.com/backstage/backstage/tree/master/packages/test-utils-core) -- [`techdocs-container/`](https://github.com/spotify/backstage/tree/master/packages/techdocs-container) - - Used by the `techdocs-cli` +- [`test-utils/`](https://github.com/backstage/backstage/tree/master/packages/test-utils) -- [`test-utils-core/`](https://github.com/spotify/backstage/tree/master/packages/test-utils-core) - -- [`test-utils/`](https://github.com/spotify/backstage/tree/master/packages/test-utils) - -- [`theme/`](https://github.com/spotify/backstage/tree/master/packages/theme) - +- [`theme/`](https://github.com/backstage/backstage/tree/master/packages/theme) - Holds the Backstage Theme. ### `plugins/` Most of the functionality of a Backstage App comes from plugins. Even core features can be plugins, take the -[catalog](https://github.com/spotify/backstage/tree/master/plugins/catalog) as +[catalog](https://github.com/backstage/backstage/tree/master/plugins/catalog) as an example. We can categorize plugins into three different types; **Frontend**, **Backend** @@ -196,18 +191,18 @@ reason is for clear separation of concerns. Take a look at our [Plugin Gallery](https://backstage.io/plugins) or browse through the -[`plugins/`](https://github.com/spotify/backstage/tree/master/plugins) folder. +[`plugins/`](https://github.com/backstage/backstage/tree/master/plugins) folder. ## Packages outside of the monorepo For convenience we include packages in our project that are not part of our monorepo setup. -- [`microsite/`](https://github.com/spotify/backstage/blob/master/microsite) - +- [`microsite/`](https://github.com/backstage/backstage/blob/master/microsite) - This folder contains the source code for backstage.io. It is built with [Docusaurus](https://docusaurus.io/). This folder is not part of the monorepo due to dependency reasons. Look at the - [README](https://github.com/spotify/backstage/blob/master/microsite/README.md) + [README](https://github.com/backstage/backstage/blob/master/microsite/README.md) for instructions on how to run it locally. ## Root files specifically used by the `app` @@ -216,22 +211,22 @@ These files are kept in the root of the project mostly by historical reasons. Some of these files may be subject to be moved out of the root sometime in the future. -- [`.npmrc`](https://github.com/spotify/backstage/tree/master/.npmrc) - It's +- [`.npmrc`](https://github.com/backstage/backstage/tree/master/.npmrc) - It's common for companies to have their own npm registry, this files makes sure that this folder use the public registry. -- [`.vale.ini`](https://github.com/spotify/backstage/tree/master/.vale.ini) - +- [`.vale.ini`](https://github.com/backstage/backstage/tree/master/.vale.ini) - [Spell checker](https://github.com/errata-ai/vale) for Markdown files. -- [`.yarnrc`](https://github.com/spotify/backstage/tree/master/.yarnrc) - +- [`.yarnrc`](https://github.com/backstage/backstage/tree/master/.yarnrc) - Enforces "our" version of Yarn. -- [`app-config.yaml`](https://github.com/spotify/backstage/tree/master/app-config.yaml) - +- [`app-config.yaml`](https://github.com/backstage/backstage/tree/master/app-config.yaml) - Configuration for the app, both frontend and backend. -- [`catalog-info.yaml`](https://github.com/spotify/backstage/tree/master/catalog-info.yaml) - +- [`catalog-info.yaml`](https://github.com/backstage/backstage/tree/master/catalog-info.yaml) - Description of Backstage in the Backstage Entity format. -- [`lerna.json`](https://github.com/spotify/backstage/tree/master/lerna.json) - +- [`lerna.json`](https://github.com/backstage/backstage/tree/master/lerna.json) - [Lerna](https://github.com/lerna/lerna) monorepo config. We are using `yarn workspaces`, so this will only be used for executing scripts. diff --git a/docs/support/support.md b/docs/support/support.md index 12bc7cfaf9..797aca041f 100644 --- a/docs/support/support.md +++ b/docs/support/support.md @@ -6,9 +6,9 @@ description: Support and Community Details and Links - [Discord chatroom](https://discord.gg/MUpMjP2) - Get support or discuss the project -- [Good First Issues](https://github.com/spotify/backstage/contribute) - Start +- [Good First Issues](https://github.com/backstage/backstage/contribute) - Start here if you want to contribute -- [RFCs](https://github.com/spotify/backstage/labels/rfc) - Help shape the +- [RFCs](https://github.com/backstage/backstage/labels/rfc) - Help shape the technical direction - [FAQ](../FAQ.md) - Frequently Asked Questions - [Code of Conduct](../../CODE_OF_CONDUCT.md) - This is how we roll diff --git a/docs/tutorials/journey.md b/docs/tutorials/journey.md index 7627920a75..664d4b77d3 100644 --- a/docs/tutorials/journey.md +++ b/docs/tutorials/journey.md @@ -264,14 +264,9 @@ release of Sam's plugin specifies a dependency on Backstage with a minimum version set to the same release as the one were the annotation was added to the core schema. -
- - # 9. Revenge of the Sam Sam, now in full control of all theme tunes in Backstage, releases v2.0.1, which switches all tracks to 4uLU6hMCjMI75M1A2tKUQC. Sam wanted to do something more nefarious, but since Backstage sandboxes sensitive actions and is mostly read-only with strict CSP, Sam's hands were tied. - -
diff --git a/docs/tutorials/quickstart-app-plugin.md b/docs/tutorials/quickstart-app-plugin.md index daf76aa1cd..216ff9659f 100644 --- a/docs/tutorials/quickstart-app-plugin.md +++ b/docs/tutorials/quickstart-app-plugin.md @@ -120,10 +120,10 @@ If everything is saved, you should see your name, id, and email on the github-playground page. Our data accessed is synchronous. So we just grab and go. -https://github.com/spotify/backstage/tree/master/contrib +https://github.com/backstage/backstage/tree/master/contrib 6. Here is the entire file for reference - [ExampleComponent.tsx](https://github.com/spotify/backstage/tree/master/contrib/docs/tutorials/quickstart-app-plugin/ExampleComponent.md) + [ExampleComponent.tsx](https://github.com/backstage/backstage/tree/master/contrib/docs/tutorials/quickstart-app-plugin/ExampleComponent.md) # The Wipe @@ -302,7 +302,7 @@ return ( 8. After saving that, and given we don't have any errors, you should see a table with basic information on your repositories. 9. Here is the entire file for reference - [ExampleFetchComponent.tsx](https://github.com/spotify/backstage/tree/master/contrib/docs/tutorials/quickstart-app-plugin/ExampleFetchComponent.md) + [ExampleFetchComponent.tsx](https://github.com/backstage/backstage/tree/master/contrib/docs/tutorials/quickstart-app-plugin/ExampleFetchComponent.md) 10. We finished! You should see your own GitHub repository's information displayed in a basic table. If you run into issues, you can compare the repo that backs this document, diff --git a/lerna.json b/lerna.json index 5871423f78..dd2dd884eb 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "packages": ["packages/*", "plugins/*"], "npmClient": "yarn", "useWorkspaces": true, - "version": "0.1.1-alpha.26" + "version": "0.1.1" } diff --git a/microsite/blog/2020-03-18-what-is-backstage.md b/microsite/blog/2020-03-18-what-is-backstage.md index 8b0a0fcbe6..0a0ff9e0b1 100644 --- a/microsite/blog/2020-03-18-what-is-backstage.md +++ b/microsite/blog/2020-03-18-what-is-backstage.md @@ -81,8 +81,8 @@ Similar to how Backstage ties together all of Spotify’s infrastructure, our am ## What’s next? -We are envisioning [three phases](https://github.com/spotify/backstage/milestones) of the project (so far), and we have already begun work on various aspects of these phases. The best way to track the work and see where you can jump in and help out is: +We are envisioning [three phases](https://github.com/backstage/backstage/milestones) of the project (so far), and we have already begun work on various aspects of these phases. The best way to track the work and see where you can jump in and help out is: -https://github.com/spotify/backstage/milestones +https://github.com/backstage/backstage/milestones Want to discuss the project or need support? Join us on [Discord](https://discord.gg/MUpMjP2) or reach out on [alund@spotify.com](mailto:alund@spotify.com). diff --git a/microsite/blog/2020-04-06-lighthouse-plugin.md b/microsite/blog/2020-04-06-lighthouse-plugin.md index 2d5c7b96b7..b8fd68e783 100644 --- a/microsite/blog/2020-04-06-lighthouse-plugin.md +++ b/microsite/blog/2020-04-06-lighthouse-plugin.md @@ -33,7 +33,7 @@ Trigger an audit directly from Backstage, or trigger audits programmatically wit ## Using Lighthouse in Backstage -To learn how you can enable Lighthouse auditing within Backstage, head over to the [README](https://github.com/spotify/backstage/tree/master/plugins/lighthouse) for the plugin to get started. +To learn how you can enable Lighthouse auditing within Backstage, head over to the [README](https://github.com/backstage/backstage/tree/master/plugins/lighthouse) for the plugin to get started. ## A personal note diff --git a/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md b/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md index dff567eaf3..85f40dd9ea 100644 --- a/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md +++ b/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md @@ -132,4 +132,4 @@ If you are developing a plugin that might be useful for others, consider releasi ## Ready to get started? -Head over to GitHub and check out the [project](https://github.com/spotify/backstage) or download our [CLI](https://www.npmjs.com/package/@backstage/cli). If you have more questions, join us on [Discord](https://discord.gg/MUpMjP2) or [create an issue](https://github.com/spotify/backstage/issues/new/choose). +Head over to GitHub and check out the [project](https://github.com/backstage/backstage) or download our [CLI](https://www.npmjs.com/package/@backstage/cli). If you have more questions, join us on [Discord](https://discord.gg/MUpMjP2) or [create an issue](https://github.com/backstage/backstage/issues/new/choose). diff --git a/microsite/blog/2020-05-14-tech-radar-plugin.md b/microsite/blog/2020-05-14-tech-radar-plugin.md index d78d5d67fa..80c1eb8b5a 100644 --- a/microsite/blog/2020-05-14-tech-radar-plugin.md +++ b/microsite/blog/2020-05-14-tech-radar-plugin.md @@ -34,11 +34,11 @@ To learn about how you can bring the Tech Radar to your Backstage installation, I want to thank both the Backstage team and Spotify. Firstly, I’ve been working with our internal version of Backstage for over a year, and the developer experience since open sourcing has been even more of a joy to work with. Secondly, the 10% hack time that Spotify generously provides to all engineers enabled me to open source the Tech Radar plugin. -Since open sourcing it, the community has shown great interest in yet another powerful use case of Backstage. There was also an enthusiastic open source contributor who volunteered to migrate the plugin to TypeScript and React Hooks [in just 29 minutes](https://github.com/spotify/backstage/issues/661) of opening the issue! +Since open sourcing it, the community has shown great interest in yet another powerful use case of Backstage. There was also an enthusiastic open source contributor who volunteered to migrate the plugin to TypeScript and React Hooks [in just 29 minutes](https://github.com/backstage/backstage/issues/661) of opening the issue! I can’t wait to see how others benefit from the Tech Radar in their organizations! [lighthouse website audits]: https://backstage.io/blog/2020/04/06/lighthouse-plugin -[tech radar plugin]: https://github.com/spotify/backstage/tree/master/plugins/tech-radar +[tech radar plugin]: https://github.com/backstage/backstage/tree/master/plugins/tech-radar [thoughtworks]: https://www.thoughtworks.com/radar [zalando]: https://opensource.zalando.com/tech-radar/ diff --git a/microsite/blog/2020-05-22-phase-2-service-catalog.md b/microsite/blog/2020-05-22-phase-2-service-catalog.md index 5c988c03aa..103750dcc6 100644 --- a/microsite/blog/2020-05-22-phase-2-service-catalog.md +++ b/microsite/blog/2020-05-22-phase-2-service-catalog.md @@ -7,7 +7,7 @@ authorImageURL: https://pbs.twimg.com/profile_images/121166861/6919c047c0d0edaac **TL;DR** Thanks to the help from the Backstage community, we’ve made excellent progress and are now moving into Phase 2 of Backstage — building out a Service Catalog and the surrounding systems that will help unify the tools you use to manage your software. -We released the open source version of Backstage a little less than two months ago, and have been thrilled to see so many people jumping in and contributing to the project in its early stages. We’re excited to see what the community can build together as we progress through [each phase of Backstage](https://github.com/spotify/backstage#project-roadmap). +We released the open source version of Backstage a little less than two months ago, and have been thrilled to see so many people jumping in and contributing to the project in its early stages. We’re excited to see what the community can build together as we progress through [each phase of Backstage](https://github.com/backstage/backstage#project-roadmap). ![img](assets/20-05-20/Service_Catalog_MVP.png) @@ -15,7 +15,7 @@ We released the open source version of Backstage a little less than two months a ## Progress so far -Phase 1 was all about building an extensible frontend platform, enabling teams to start creating a single, consistent UI layer for your internal infrastructure and tools in the form of [plugins](https://github.com/spotify/backstage/labels/plugin). In fact, thanks to our amazing (30+) [contributors](https://github.com/spotify/backstage/graphs/contributors), we were able to complete most of Phase 1 earlier than expected. 🎉 +Phase 1 was all about building an extensible frontend platform, enabling teams to start creating a single, consistent UI layer for your internal infrastructure and tools in the form of [plugins](https://github.com/backstage/backstage/labels/plugin). In fact, thanks to our amazing (30+) [contributors](https://github.com/backstage/backstage/graphs/contributors), we were able to complete most of Phase 1 earlier than expected. 🎉 Today, we are happy to announce that we are shifting our focus to Phase 2! @@ -27,7 +27,7 @@ Quote from [Platform Nuts & Bolts: Extendable Data Models](https://www.kislayver Entities, or what we refer to as “components” in Backstage, represent all software, including services, websites, libraries, data pipelines, and so forth. The focus of Phase 2 will be on adding an entity model in Backstage that makes it easy for engineers to create and manage the software components they own. -With the ability to create a plethora of components in Backstage, how does one keep track of all the software in the ecosystem? Therein lies the highlight feature of Phase 2: the [Service Catalog](https://github.com/spotify/backstage/milestone/4). The service catalog — or software catalog — is a centralized system that keeps track of ownership and metadata about all software in your ecosystem. The catalog is built around the concept of [metadata yaml files](/docs/architecture-decisions/adrs-adr002) stored together with the code, which are then harvested and visualized in Backstage. +With the ability to create a plethora of components in Backstage, how does one keep track of all the software in the ecosystem? Therein lies the highlight feature of Phase 2: the [Service Catalog](https://github.com/backstage/backstage/milestone/4). The service catalog — or software catalog — is a centralized system that keeps track of ownership and metadata about all software in your ecosystem. The catalog is built around the concept of [metadata yaml files](/docs/architecture-decisions/adrs-adr002) stored together with the code, which are then harvested and visualized in Backstage. ![img](assets/20-05-20/Service_Catalog_MVP.png) @@ -39,13 +39,13 @@ On top of that, we have found that the service catalog is a great way to organis ![img](assets/20-05-20/tabs.png) -More concretely, having this structure in place will allow plugins such as [CircleCI](https://github.com/spotify/backstage/tree/master/plugins/circleci) to show only the builds for the specific service you are viewing, or a [Spinnaker](https://github.com/spotify/backstage/issues/631) plugin to show running deployments, or an Open API plugin to [show documentation](https://github.com/spotify/backstage/issues/627) for endpoints exposed by the service, or the [Lighthouse](https://github.com/spotify/backstage/tree/master/plugins/lighthouse) plugin to show audit reports for your website. You get the point. +More concretely, having this structure in place will allow plugins such as [CircleCI](https://github.com/backstage/backstage/tree/master/plugins/circleci) to show only the builds for the specific service you are viewing, or a [Spinnaker](https://github.com/backstage/backstage/issues/631) plugin to show running deployments, or an Open API plugin to [show documentation](https://github.com/backstage/backstage/issues/627) for endpoints exposed by the service, or the [Lighthouse](https://github.com/backstage/backstage/tree/master/plugins/lighthouse) plugin to show audit reports for your website. You get the point. ## Timeline Our estimated timeline has us delivering these pieces in increments leading up to June 22. But with the support of the community we wouldn’t be surprised if things land earlier than that. 🙏 -If you are interested in joining us, check out our [Milestones](https://github.com/spotify/backstage/milestones) and connected Issues. +If you are interested in joining us, check out our [Milestones](https://github.com/backstage/backstage/milestones) and connected Issues. ## Long-term vision diff --git a/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md b/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md index 167cc753f8..eeed43b713 100644 --- a/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md +++ b/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md @@ -40,7 +40,7 @@ You’ll be able to see many of these virtues in action with this alpha release Alpha is our shorthand for "we don’t yet think Backstage is ready for production, but we’d love for you to test it and provide us with feedback". However, you should be able to try out the functionality of the service catalog: -1. Register software components ([examples](https://github.com/spotify/backstage/tree/master/packages/catalog-model/examples)) +1. Register software components ([examples](https://github.com/backstage/backstage/tree/master/packages/catalog-model/examples)) 2. See all components represented in the catalog 3. Search across all components 4. Get an overview of the metadata of the components @@ -49,6 +49,6 @@ Alpha is our shorthand for "we don’t yet think Backstage is ready for producti As with most alpha releases, you should expect things to change quite a lot until we reach the beta stage (we’re targeting the end of summer). There are obviously many things missing as well, but we wanted to start collecting feedback early and make it easier to see the end-to-end flow. -If you have feedback or questions, please open a [GitHub issue](https://github.com/spotify/backstage/issues), ping us on [Discord chat](https://discord.gg/EBHEGzX) or send me an email at [alund@spotify.com](mailto:alund@spotify.com) 🙏 +If you have feedback or questions, please open a [GitHub issue](https://github.com/backstage/backstage/issues), ping us on [Discord chat](https://discord.gg/EBHEGzX) or send me an email at [alund@spotify.com](mailto:alund@spotify.com) 🙏 To get regular product updates and news about the Backstage community, sign up for the [Backstage newsletter](https://mailchi.mp/spotify/backstage-community). diff --git a/microsite/blog/2020-07-01-how-to-enable-authentication-in-backstage-using-passport.md b/microsite/blog/2020-07-01-how-to-enable-authentication-in-backstage-using-passport.md index b2a944bf26..9d41a21d05 100644 --- a/microsite/blog/2020-07-01-how-to-enable-authentication-in-backstage-using-passport.md +++ b/microsite/blog/2020-07-01-how-to-enable-authentication-in-backstage-using-passport.md @@ -21,7 +21,7 @@ Passport has allowed us to leverage an existing open-source authentication frame ![auth-landing-page](assets/20-07-01/auth-sidebar.png) -First, check out the provided Google and GitHub implementations! [Spin up a local copy of Backstage](https://backstage.io/blog/2020/04/30/how-to-quickly-set-up-backstage) along with our example-backend. You can find more documentation on setting up the example backend [here](https://github.com/spotify/backstage/tree/master/packages/backend), but be sure to include the relevant client IDs and secrets when running `yarn start`: +First, check out the provided Google and GitHub implementations! [Spin up a local copy of Backstage](https://backstage.io/blog/2020/04/30/how-to-quickly-set-up-backstage) along with our example-backend. You can find more documentation on setting up the example backend [here](https://github.com/backstage/backstage/tree/master/packages/backend), but be sure to include the relevant client IDs and secrets when running `yarn start`: ``` AUTH_GOOGLE_CLIENT_ID=x AUTH_GOOGLE_CLIENT_SECRET=x AUTH_GITHUB_CLIENT_ID=x AUTH_GITHUB_CLIENT_SECRET=x SENTRY_TOKEN=x LOG_LEVEL=debug yarn start @@ -43,4 +43,4 @@ For full details, take a look at our [“Adding authentication providers” docu ## Interested in contributing to the next steps for authentication? -We’ve already seen both GitLab and Okta contributions from the community — and we’re thinking about a few more providers we’d like to add to Backstage, too. You can find those, and other authentication-related issues, in our repository by filtering with the [auth label](https://github.com/spotify/backstage/issues?q=is%3Aissue+is%3Aopen+label%3Aauth). +We’ve already seen both GitLab and Okta contributions from the community — and we’re thinking about a few more providers we’d like to add to Backstage, too. You can find those, and other authentication-related issues, in our repository by filtering with the [auth label](https://github.com/backstage/backstage/issues?q=is%3Aissue+is%3Aopen+label%3Aauth). diff --git a/microsite/blog/2020-08-05-announcing-backstage-software-templates.md b/microsite/blog/2020-08-05-announcing-backstage-software-templates.md index 81d495e1c3..c216d7e398 100644 --- a/microsite/blog/2020-08-05-announcing-backstage-software-templates.md +++ b/microsite/blog/2020-08-05-announcing-backstage-software-templates.md @@ -73,6 +73,6 @@ Backstage ships with four example templates, but since these are likely not the We have learned that one of the keys to getting these standards adopted is to keep an open process. Templates are code. By making it clear to your engineers that you are open to pull requests, and that teams with different needs can add their own templates, you are on the path of striking a good balance between autonomy and standardization. -If you have feedback or questions, please open a [GitHub issue](https://github.com/spotify/backstage/issues), ping us on [Discord chat](https://discord.gg/EBHEGzX) or send me an email at [alund@spotify.com](mailto:alund@spotify.com) 🙏 +If you have feedback or questions, please open a [GitHub issue](https://github.com/backstage/backstage/issues), ping us on [Discord chat](https://discord.gg/EBHEGzX) or send me an email at [alund@spotify.com](mailto:alund@spotify.com) 🙏 To get regular product updates and news about the Backstage community, sign up for the [Backstage newsletter](https://mailchi.mp/spotify/backstage-community). diff --git a/microsite/blog/2020-09-08-announcing-tech-docs.md b/microsite/blog/2020-09-08-announcing-tech-docs.md index 48b6eeb7cc..ceab17d7be 100644 --- a/microsite/blog/2020-09-08-announcing-tech-docs.md +++ b/microsite/blog/2020-09-08-announcing-tech-docs.md @@ -21,11 +21,11 @@ But this is just one way to do it. Today we’re most excited for what the open ## Okay, let’s start collaborating -If you go to [GitHub](https://github.com/spotify/backstage/tree/master/plugins) now, you’ll find everything you need to start collaborating with us to build out the docs-like-code Backstage plugin — we’ll call it TechDocs in the open as well. +If you go to [GitHub](https://github.com/backstage/backstage/tree/master/plugins) now, you’ll find everything you need to start collaborating with us to build out the docs-like-code Backstage plugin — we’ll call it TechDocs in the open as well. -You’ll find the code in [techdocs](https://github.com/spotify/backstage/tree/master/plugins/techdocs) (frontend) and [techdocs-backend](https://github.com/spotify/backstage/tree/master/plugins/techdocs-backend). (There are also two separate packages [techdocs-cli](https://github.com/spotify/backstage/tree/master/packages/techdocs-cli) and [techdocs-container](https://github.com/spotify/backstage/tree/master/packages/techdocs-container).) +You’ll find the code in [techdocs](https://github.com/backstage/backstage/tree/master/plugins/techdocs) (frontend) and [techdocs-backend](https://github.com/backstage/backstage/tree/master/plugins/techdocs-backend). (There are also two separate packages [techdocs-cli](https://github.com/backstage/techdocs-cli) and [techdocs-container](https://github.com/backstage/techdocs-container).) -You’ll find issues to work on in the [issues queue](https://github.com/spotify/backstage/issues?q=is%3Aissue+is%3Aopen+label%3A%22docs-like-code%22+label%3A%22help+wanted%22), typically starting with TechDocs: and labeled with docs-like-code, some labeled good first issue. Feel free to add your own issues, of course. +You’ll find issues to work on in the [issues queue](https://github.com/backstage/backstage/issues?q=is%3Aissue+is%3Aopen+label%3A%22docs-like-code%22+label%3A%22help+wanted%22), typically starting with TechDocs: and labeled with docs-like-code, some labeled good first issue. Feel free to add your own issues, of course. ![available-templates](assets/announcing-techdocs/github-issues.png) diff --git a/microsite/blog/2020-09-23-backstage-cncf-sandbox.md b/microsite/blog/2020-09-23-backstage-cncf-sandbox.md index bcfd7c6245..fbf47a39c3 100644 --- a/microsite/blog/2020-09-23-backstage-cncf-sandbox.md +++ b/microsite/blog/2020-09-23-backstage-cncf-sandbox.md @@ -14,7 +14,7 @@ Backstage garnered quite a bit of interest from developers and organizations whe Backstage’s ability to simplify tooling and standardize engineering practices has attracted interest from other major tech companies, as well as airlines, auto manufacturers, investment firms, and global retailers. We know that Backstage solves a problem — infrastructure complexity — that’s common to a lot of large and growing companies today. But different companies work differently, use particular toolsets, and have unique use cases. By making Backstage open source, we can build it with people working inside a variety of engineering organizations all over the world. It makes for a better product that serves a wider group of users (beyond that of Spotify’s) and their needs. -The Backstage community is healthy and growing quickly. Over [130 people](https://github.com/spotify/backstage/graphs/contributors) have contributed to the project, and roughly 40% of pull requests are now coming from external, non-Spotify, contributors. With companies now deciding to [adopt Backstage](https://github.com/spotify/backstage/blob/master/ADOPTERS.md) we are also seeing a shift in the kinds of contributions we are getting from the community. It is truly amazing to see contributions to core parts of the platform as well as significant functionality additions through working [plugins](https://backstage.io/plugins). +The Backstage community is healthy and growing quickly. Over [130 people](https://github.com/backstage/backstage/graphs/contributors) have contributed to the project, and roughly 40% of pull requests are now coming from external, non-Spotify, contributors. With companies now deciding to [adopt Backstage](https://github.com/backstage/backstage/blob/master/ADOPTERS.md) we are also seeing a shift in the kinds of contributions we are getting from the community. It is truly amazing to see contributions to core parts of the platform as well as significant functionality additions through working [plugins](https://backstage.io/plugins). We’re excited to embark on this journey with the CNCF community. There’s so much great tech being built here, and it’s about time we share it to build even greater products, together. Entering into the CNCF Sandbox is just the first step. We are committed to working with the community to bring Backstage through the Incubation step, and finally all the way to becoming a Graduated, top-level project. diff --git a/microsite/blog/2020-09-30-backstage-design-system.md b/microsite/blog/2020-09-30-backstage-design-system.md index 4faea98782..a1d087f755 100644 --- a/microsite/blog/2020-09-30-backstage-design-system.md +++ b/microsite/blog/2020-09-30-backstage-design-system.md @@ -68,9 +68,9 @@ To keep up with our latest design guidelines, go to [Designing for Backstage](ht ![img](assets/backstage-github-ds.png) -### [GitHub](https://github.com/spotify/backstage) +### [GitHub](https://github.com/backstage/backstage) -Join in on the action [at spotify/backstage on GitHub](https://github.com/spotify/backstage) by submitting issues and opening pull requests for all things related to components and patterns in Backstage. +Join in on the action [at backstage/backstage on GitHub](https://github.com/backstage/backstage) by submitting issues and opening pull requests for all things related to components and patterns in Backstage. ![img](assets/backstage-discord-DS.png) diff --git a/microsite/blog/2020-09-30-plugin-marketplace.md b/microsite/blog/2020-09-30-plugin-marketplace.md index 0b96abbc60..10928112b8 100644 --- a/microsite/blog/2020-09-30-plugin-marketplace.md +++ b/microsite/blog/2020-09-30-plugin-marketplace.md @@ -34,10 +34,10 @@ This grand vision is actually not that far off. Already today there is a growing Not all plugins you need will be open source. Every company has their own homegrown tooling. Building internal plugins lets you tailor your version of Backstage to be a perfect fit for your infrastructure and software development needs. If you end up [building plugins](https://backstage.io/docs/plugins/create-a-plugin) that could be useful for other companies, please consider releasing them as open source and [add them to the Marketplace](https://backstage.io/docs/plugins/add-to-marketplace). -If you start developing a plugin that you aim to release as open source, we suggest that you create a [new plugin Issue](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). This helps the community know what plugins are in development and opens up opportunities for collaboration. You can also use this process if you have an idea for a good plugin, but you need help building it. +If you start developing a plugin that you aim to release as open source, we suggest that you create a [new plugin Issue](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). This helps the community know what plugins are in development and opens up opportunities for collaboration. You can also use this process if you have an idea for a good plugin, but you need help building it. We are really excited to see all the amazing plugins that have already been built, and look forward to seeing even more ideas and collaboration as the Backstage community continues to grow. -What plugins would you like to see in the Plugin Marketplace? [Tell us](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME)! +What plugins would you like to see in the Plugin Marketplace? [Tell us](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME)! _Special shout-out to community member [Iain Billett](https://github.com/iain-b) from [Roadie](https://roadie.io) for helping build and contribute the [Plugin Marketplace page](https://backstage.io/plugins) (as his first PR no less!)._ diff --git a/microsite/blog/2020-10-22-cost-insights-plugin.md b/microsite/blog/2020-10-22-cost-insights-plugin.md index 421ebacdd2..15647f8418 100644 --- a/microsite/blog/2020-10-22-cost-insights-plugin.md +++ b/microsite/blog/2020-10-22-cost-insights-plugin.md @@ -4,7 +4,7 @@ author: Janisa Anandamohan authorURL: https://twitter.com/janisa_a --- -How did Spotify save millions on cloud costs within a matter of months?? We made cost optimization just another part of the daily development process. Our newly open sourced [Cost Insights plugin](https://github.com/spotify/backstage/tree/master/plugins/cost-insights) makes a team’s cloud costs visible — and actionable — right inside Backstage. So engineers can see the impact of their cloud usage (down to a product and resource level) and make optimizations wherever and whenever it makes sense. By managing cloud costs from the ground up, you can make smarter decisions that let you continue to build and scale quickly, without wasting resources. +How did Spotify save millions on cloud costs within a matter of months?? We made cost optimization just another part of the daily development process. Our newly open sourced [Cost Insights plugin](https://github.com/backstage/backstage/tree/master/plugins/cost-insights) makes a team’s cloud costs visible — and actionable — right inside Backstage. So engineers can see the impact of their cloud usage (down to a product and resource level) and make optimizations wherever and whenever it makes sense. By managing cloud costs from the ground up, you can make smarter decisions that let you continue to build and scale quickly, without wasting resources. @@ -59,7 +59,7 @@ Engineers can then determine for themselves if the time invested in an optimizat ## Getting started -You can begin working with the Cost Insights plugin today on [GitHub](https://github.com/spotify/backstage/tree/master/plugins/cost-insights). We include an example client with static data in the expected format. The `CostInsightsApi` should talk with a cloud billing backend that aggregates billing data from your cloud provider. +You can begin working with the Cost Insights plugin today on [GitHub](https://github.com/backstage/backstage/tree/master/plugins/cost-insights). We include an example client with static data in the expected format. The `CostInsightsApi` should talk with a cloud billing backend that aggregates billing data from your cloud provider. The current release of Cost Insights includes: @@ -72,8 +72,8 @@ The current release of Cost Insights includes: Our hope is to help other companies translate their cloud cost in a relatable way for their engineers to better understand their impact and accurately identify their opportunities for optimizations. -And if you’re interested in contributing to our outstanding issues, you can find them in the issues queue, filtered under the [‘cost-insights’ label](https://github.com/spotify/backstage/labels/cost-insights). +And if you’re interested in contributing to our outstanding issues, you can find them in the issues queue, filtered under the [‘cost-insights’ label](https://github.com/backstage/backstage/labels/cost-insights). ## Ready for DevSecCostOpsPlus (and whatever’s next) -There’s DevOps, there’s DevSecOps, and then there’s Backstage: one frontend for all your infrastructure. From building, testing, and deploying to monitoring and security — Backstage helps you manage your entire tech organization and provides a seamless developer experience for engineers, from end to end to end. And now that also extends to cost management for your cloud infrastructure and tooling. Happy building and [happy optimizing](https://github.com/spotify/backstage/tree/master/plugins/cost-insights). +There’s DevOps, there’s DevSecOps, and then there’s Backstage: one frontend for all your infrastructure. From building, testing, and deploying to monitoring and security — Backstage helps you manage your entire tech organization and provides a seamless developer experience for engineers, from end to end to end. And now that also extends to cost management for your cloud infrastructure and tooling. Happy building and [happy optimizing](https://github.com/backstage/backstage/tree/master/plugins/cost-insights). diff --git a/microsite/core/Footer.js b/microsite/core/Footer.js index d41b15b74c..6ce3c3dd84 100644 --- a/microsite/core/Footer.js +++ b/microsite/core/Footer.js @@ -41,7 +41,7 @@ class Footer extends React.Component {
Community
Support chatroom - + Contributing @@ -59,7 +59,7 @@ class Footer extends React.Component { className="github-button" href={this.props.config.repoUrl} data-icon="octicon-star" - data-count-href="/spotify/backstage/stargazers" + data-count-href="/backstage/backstage/stargazers" data-show-count="true" data-count-aria-label="# stargazers on GitHub" aria-label="Star this project on GitHub" diff --git a/microsite/data/plugins/api-docs.yaml b/microsite/data/plugins/api-docs.yaml index babcbf74f1..3343a46693 100644 --- a/microsite/data/plugins/api-docs.yaml +++ b/microsite/data/plugins/api-docs.yaml @@ -4,6 +4,6 @@ author: SDA SE authorUrl: https://sda.se/ category: Discovery description: Components to discover and display API entities as an extension to the catalog plugin. -documentation: https://github.com/spotify/backstage/blob/master/plugins/api-docs/README.md +documentation: https://github.com/backstage/backstage/blob/master/plugins/api-docs/README.md iconUrl: https://thecoders.io/wp-content/uploads/2019/11/tech-swagger.svg npmPackageName: '@backstage/plugin-api-docs' diff --git a/microsite/data/plugins/circleci.yaml b/microsite/data/plugins/circleci.yaml index 5f7b4b08e2..467da9fb1e 100644 --- a/microsite/data/plugins/circleci.yaml +++ b/microsite/data/plugins/circleci.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: CI description: Automate your development process with CI hosted in the cloud or on a private server. -documentation: https://github.com/spotify/backstage/tree/master/plugins/circleci +documentation: https://github.com/backstage/backstage/tree/master/plugins/circleci iconUrl: https://www.saaves.com/storage/brochure/logo-circleci-icon1583764538.png npmPackageName: '@backstage/plugin-circleci' tags: diff --git a/microsite/data/plugins/cloud-build.yaml b/microsite/data/plugins/cloud-build.yaml index cbd3a3cb6c..2b40d02de2 100644 --- a/microsite/data/plugins/cloud-build.yaml +++ b/microsite/data/plugins/cloud-build.yaml @@ -4,7 +4,7 @@ author: Trivago authorUrl: https://www.trivago.com category: CI description: Build, test, and deploy on Google's serverless CI/CD platform. -documentation: https://github.com/spotify/backstage/tree/master/plugins/cloudbuild +documentation: https://github.com/backstage/backstage/tree/master/plugins/cloudbuild iconUrl: https://avatars2.githubusercontent.com/u/38220399?s=400&v=4 npmPackageName: '@backstage/plugin-cloudbuild' tags: diff --git a/microsite/data/plugins/cost-insights.yaml b/microsite/data/plugins/cost-insights.yaml index 7950879833..daa4f55a02 100644 --- a/microsite/data/plugins/cost-insights.yaml +++ b/microsite/data/plugins/cost-insights.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: Discovery description: Visualize, understand and optimize your team's cloud costs. -documentation: https://github.com/spotify/backstage/tree/master/plugins/cost-insights +documentation: https://github.com/backstage/backstage/tree/master/plugins/cost-insights iconUrl: https://www.materialui.co/materialIcons/editor/monetization_on_white_192x192.png npmPackageName: '@backstage/plugin-cost-insights' tags: diff --git a/microsite/data/plugins/gcp-projects.yaml b/microsite/data/plugins/gcp-projects.yaml index 7eff42af98..1c015821b2 100644 --- a/microsite/data/plugins/gcp-projects.yaml +++ b/microsite/data/plugins/gcp-projects.yaml @@ -4,7 +4,7 @@ author: Trivago authorUrl: https://www.trivago.com category: Cloud description: Create, list and manage your Google Cloud Projects. -documentation: https://github.com/spotify/backstage/tree/master/plugins/gcp-projects +documentation: https://github.com/backstage/backstage/tree/master/plugins/gcp-projects iconUrl: https://avatars1.githubusercontent.com/u/2810941?s=280&v=4 npmPackageName: '@backstage/plugin-gcp-projects' tags: diff --git a/microsite/data/plugins/github-actions.yaml b/microsite/data/plugins/github-actions.yaml index 062d0fff61..aeccdc9b86 100644 --- a/microsite/data/plugins/github-actions.yaml +++ b/microsite/data/plugins/github-actions.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: CI description: GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. -documentation: https://github.com/spotify/backstage/tree/master/plugins/github-actions +documentation: https://github.com/backstage/backstage/tree/master/plugins/github-actions iconUrl: https://avatars2.githubusercontent.com/u/44036562?s=400&v=4 npmPackageName: '@backstage/plugin-github-actions' tags: diff --git a/microsite/data/plugins/gitops-cluster.yaml b/microsite/data/plugins/gitops-cluster.yaml index 6f8ab6b097..ad6e7979aa 100644 --- a/microsite/data/plugins/gitops-cluster.yaml +++ b/microsite/data/plugins/gitops-cluster.yaml @@ -4,7 +4,7 @@ author: Weaveworks authorUrl: https://www.weave.works/ category: Kubernetes description: Create GitOps-managed Kubernetes clusters. Currently, it supports provisioning EKS clusters on GitHub via GitHub Actions. -documentation: https://github.com/spotify/backstage/tree/master/plugins/gitops-profiles +documentation: https://github.com/backstage/backstage/tree/master/plugins/gitops-profiles iconUrl: https://res-5.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_256,w_256,f_auto,q_auto:eco/v1462316670/i9d3delzvx1erzjhmcws.png npmPackageName: '@backstage/plugin-gitops-profiles' tags: diff --git a/microsite/data/plugins/graphiql.yaml b/microsite/data/plugins/graphiql.yaml index e997360b04..eda91206eb 100644 --- a/microsite/data/plugins/graphiql.yaml +++ b/microsite/data/plugins/graphiql.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: Debugging description: Integrates GraphiQL as a tool to browse GraphQL API endpoints inside Backstage. -documentation: https://github.com/spotify/backstage/tree/master/plugins/graphiql +documentation: https://github.com/backstage/backstage/tree/master/plugins/graphiql iconUrl: https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/GraphQL_Logo.svg/1024px-GraphQL_Logo.svg.png npmPackageName: '@backstage/plugin-graphiql' tags: diff --git a/microsite/data/plugins/jenkins.yaml b/microsite/data/plugins/jenkins.yaml index 78b3616595..638758d54d 100644 --- a/microsite/data/plugins/jenkins.yaml +++ b/microsite/data/plugins/jenkins.yaml @@ -4,7 +4,7 @@ author: '@timja' authorUrl: https://github.com/timja category: CI description: Jenkins offers a simple way to set up a continuous integration and continuous delivery environment. -documentation: https://github.com/spotify/backstage/tree/master/plugins/jenkins +documentation: https://github.com/backstage/backstage/tree/master/plugins/jenkins iconUrl: https://img.icons8.com/color/1600/jenkins.png npmPackageName: '@backstage/plugin-jenkins' tags: diff --git a/microsite/data/plugins/lighthouse.yaml b/microsite/data/plugins/lighthouse.yaml index 0819455ed2..88d444e0ef 100644 --- a/microsite/data/plugins/lighthouse.yaml +++ b/microsite/data/plugins/lighthouse.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: Accessibility description: Google's Lighthouse tool is a great resource for benchmarking and improving the accessibility, performance, SEO, and best practices of your website. -documentation: https://github.com/spotify/backstage/tree/master/plugins/lighthouse +documentation: https://github.com/backstage/backstage/tree/master/plugins/lighthouse iconUrl: https://seeklogo.com/images/G/google-lighthouse-logo-1C7FA08580-seeklogo.com.png npmPackageName: '@backstage/plugin-lighthouse' tags: diff --git a/microsite/data/plugins/new-relic.yaml b/microsite/data/plugins/new-relic.yaml index e3ddf18652..d728a9d1c7 100644 --- a/microsite/data/plugins/new-relic.yaml +++ b/microsite/data/plugins/new-relic.yaml @@ -4,7 +4,7 @@ author: '@timwheelercom' authorUrl: https://github.com/timwheelercom category: Monitoring description: Observability platform built to help engineers create and monitor their software. -documentation: https://github.com/spotify/backstage/tree/master/plugins/newrelic +documentation: https://github.com/backstage/backstage/tree/master/plugins/newrelic iconUrl: https://www.mulesoft.com/sites/default/files/2018-10/New_relic.png npmPackageName: '@backstage/plugin-newrelic' tags: diff --git a/microsite/data/plugins/rollbar.yaml b/microsite/data/plugins/rollbar.yaml index 8ef3d8d66a..05f0d4ef78 100644 --- a/microsite/data/plugins/rollbar.yaml +++ b/microsite/data/plugins/rollbar.yaml @@ -4,6 +4,6 @@ author: '@andrewthauer' authorUrl: https://github.com/andrewthauer category: Monitoring description: View Rollbar errors for your services in Backstage. -documentation: https://github.com/spotify/backstage/tree/master/plugins/rollbar +documentation: https://github.com/backstage/backstage/tree/master/plugins/rollbar iconUrl: https://rollbar.com/assets/media/rollbar-mark-color.png npmPackageName: '@backstage/plugin-rollbar' diff --git a/microsite/data/plugins/sentry.yaml b/microsite/data/plugins/sentry.yaml index 8da488f727..3445d6abb7 100644 --- a/microsite/data/plugins/sentry.yaml +++ b/microsite/data/plugins/sentry.yaml @@ -4,6 +4,6 @@ author: Spotify authorUrl: https://github.com/spotify category: Monitoring description: View Sentry issues in Backstage. -documentation: https://github.com/spotify/backstage/tree/master/plugins/sentry +documentation: https://github.com/backstage/backstage/tree/master/plugins/sentry iconUrl: https://sentry-brand.storage.googleapis.com/sentry-glyph-white.png npmPackageName: '@backstage/plugin-sentry' diff --git a/microsite/data/plugins/sonarqube.yaml b/microsite/data/plugins/sonarqube.yaml index a2982a4a58..e9e22d18a4 100644 --- a/microsite/data/plugins/sonarqube.yaml +++ b/microsite/data/plugins/sonarqube.yaml @@ -4,6 +4,6 @@ author: SDA SE authorUrl: https://sda.se/ category: Quality description: Components to display code quality metrics from SonarCloud and SonarQube. -documentation: https://github.com/spotify/backstage/blob/master/plugins/sonarqube/README.md +documentation: https://github.com/backstage/backstage/blob/master/plugins/sonarqube/README.md iconUrl: img/sonarqube-icon.svg npmPackageName: '@backstage/plugin-sonarqube' diff --git a/microsite/data/plugins/tech-radar.yaml b/microsite/data/plugins/tech-radar.yaml index b1d4f5cc17..f2d5b12663 100644 --- a/microsite/data/plugins/tech-radar.yaml +++ b/microsite/data/plugins/tech-radar.yaml @@ -4,6 +4,6 @@ author: Spotify authorUrl: https://github.com/spotify category: Discovery description: Visualize the your company's official guidelines of different areas of software development. -documentation: https://github.com/spotify/backstage/tree/master/plugins/tech-radar +documentation: https://github.com/backstage/backstage/tree/master/plugins/tech-radar iconUrl: https://www.materialui.co/materialIcons/action/track_changes_white_192x192.png npmPackageName: '@backstage/plugin-tech-radar' diff --git a/microsite/pages/en/index.js b/microsite/pages/en/index.js index 6e649aa574..0422bfab63 100644 --- a/microsite/pages/en/index.js +++ b/microsite/pages/en/index.js @@ -31,7 +31,7 @@ class Index extends React.Component { high-quality code quickly — without compromising autonomy. GitHub @@ -282,7 +282,7 @@ class Index extends React.Component { Build your own software templates Contribute diff --git a/microsite/pages/en/plugins.js b/microsite/pages/en/plugins.js index 36957c2b4e..b1854135dc 100644 --- a/microsite/pages/en/plugins.js +++ b/microsite/pages/en/plugins.js @@ -98,11 +98,11 @@ const Plugins = () => (

See what plugins are already{' '} - + in progress {' '} and 👍. Missing a plugin for your favorite tool? Please{' '} - + suggest {' '} a new one. diff --git a/microsite/siteConfig.js b/microsite/siteConfig.js index 06ae8453a0..6e8f8edddf 100644 --- a/microsite/siteConfig.js +++ b/microsite/siteConfig.js @@ -17,7 +17,7 @@ const siteConfig = { url: 'https://backstage.io', // Your website URL cname: 'backstage.io', baseUrl: '/', // Base URL for your project */ - editUrl: 'https://github.com/spotify/backstage/edit/master/docs/', + editUrl: 'https://github.com/backstage/backstage/edit/master/docs/', // Used for publishing and more projectName: 'backstage', @@ -30,7 +30,7 @@ const siteConfig = { // For no header links in the top nav bar -> headerLinks: [], headerLinks: [ { - href: 'https://github.com/spotify/backstage', + href: 'https://github.com/backstage/backstage', label: 'GitHub', }, { @@ -111,7 +111,7 @@ const siteConfig = { // You may provide arbitrary config keys to be used as needed by your // template. For example, if you need your repo's URL... - repoUrl: 'https://github.com/spotify/backstage', + repoUrl: 'https://github.com/backstage/backstage', twitterUsername: 'SpotifyEng', stylesheets: [ diff --git a/microsite/static/schema/config-v1 b/microsite/static/schema/config-v1 new file mode 100644 index 0000000000..f85f2844cc --- /dev/null +++ b/microsite/static/schema/config-v1 @@ -0,0 +1,170 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://backstage.io/schema/config-v1", + "title": "Backstage Configuration Meta-Schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "allOf": [ + { "$ref": "#/definitions/nonNegativeInteger" }, + { "default": 0 } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + }, + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "$comment": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": true, + "readOnly": { + "type": "boolean", + "default": false + }, + "writeOnly": { + "type": "boolean", + "default": false + }, + "examples": { + "type": "array", + "items": true + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, + "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { "$ref": "#" }, + "items": { + "anyOf": [{ "$ref": "#" }, { "$ref": "#/definitions/schemaArray" }], + "default": true + }, + "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, + "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "contains": { "$ref": "#" }, + "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, + "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { "$ref": "#" }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "propertyNames": { "format": "regex" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [{ "$ref": "#" }, { "$ref": "#/definitions/stringArray" }] + } + }, + "propertyNames": { "$ref": "#" }, + "const": true, + "enum": { + "type": "array", + "items": true, + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "contentMediaType": { "type": "string" }, + "contentEncoding": { "type": "string" }, + "if": { "$ref": "#" }, + "then": { "$ref": "#" }, + "else": { "$ref": "#" }, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" }, + "visibility": { + "type": "string", + "enum": ["frontend", "backend", "secret"] + } + }, + "default": true +} diff --git a/package.json b/package.json index 96e02e33f9..505ee0caad 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "docker-build": "yarn tsc && yarn workspace example-backend build-image", "create-plugin": "backstage-cli create-plugin --scope backstage --no-private", "remove-plugin": "backstage-cli remove-plugin", - "release": "if [ \"$(git symbolic-ref --short HEAD)\" = master ]; then echo \"don't try to release master\"; exit 1; else lerna version --no-push --force-publish; fi", + "release": "changeset version && yarn prettier --write '{packages,plugins}/*/{package.json,CHANGELOG.md}'", "prettier:check": "prettier --check .", "lerna": "lerna", "storybook": "yarn workspace storybook start", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md new file mode 100644 index 0000000000..458f5a5e5c --- /dev/null +++ b/packages/app/CHANGELOG.md @@ -0,0 +1,121 @@ +# example-app + +## 0.2.0 + +### Minor Changes + +- 6d97d2d6f: The InfoCard variant `'height100'` is deprecated. Use variant `'gridItem'` instead. + + When the InfoCard is displayed as a grid item within a grid, you may want items to have the same height for all items. + Set to the `'gridItem'` variant to display the InfoCard with full height suitable for Grid: + `...` + + Changed the InfoCards in '@backstage/plugin-github-actions', '@backstage/plugin-jenkins', '@backstage/plugin-lighthouse' + to pass an optional variant to the corresponding card of the plugin. + + As a result the overview content of the EntityPage shows cards with full height suitable for Grid. + +### Patch Changes + +- 65d722455: Add Pull Request tab to components view. +- 26e69ab1a: Remove cost insights example client from demo app and export from plugin + Create cost insights dev plugin using example client + Make PluginConfig and dependent types public +- e7f5471fd: cleaning up because external plugins have already implemented new api for creating +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [2846ef95c] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [d67c529ab] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [8351ad79b] +- Updated dependencies [30dd11122] +- Updated dependencies [1297dcb3a] +- Updated dependencies [368fd8243] +- Updated dependencies [fb74f1db6] +- Updated dependencies [3472c8be7] +- Updated dependencies [cab473771] +- Updated dependencies [1d0aec70f] +- Updated dependencies [1c60f716e] +- Updated dependencies [a73979d45] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [a3840bed2] +- Updated dependencies [339668995] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [8d1360aa9] +- Updated dependencies [72f6cda35] +- Updated dependencies [0ee9e9f66] +- Updated dependencies [5c70f3d35] +- Updated dependencies [bb48b9833] +- Updated dependencies [fd8384d7e] +- Updated dependencies [8c2b76e45] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [c5ef12926] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [6a84cb072] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [cba4e4d97] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [4fc1d440e] +- Updated dependencies [fa56f4615] +- Updated dependencies [8afce088a] +- Updated dependencies [4512b9967] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [9a3b3dbf1] +- Updated dependencies [e7d4ac7ce] +- Updated dependencies [0b956f21b] +- Updated dependencies [1c8c43756] +- Updated dependencies [0e67c6b40] +- Updated dependencies [26e69ab1a] +- Updated dependencies [97c2cb19b] +- Updated dependencies [02c60b5f8] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [57b54c8ed] +- Updated dependencies [1611c6dbc] +- Updated dependencies [7bbeb049f] + - @backstage/cli@0.2.0 + - @backstage/plugin-api-docs@0.2.0 + - @backstage/plugin-catalog@0.2.0 + - @backstage/plugin-circleci@0.2.0 + - @backstage/plugin-explore@0.2.0 + - @backstage/plugin-gcp-projects@0.2.0 + - @backstage/plugin-github-actions@0.2.0 + - @backstage/plugin-gitops-profiles@0.2.0 + - @backstage/plugin-graphiql@0.2.0 + - @backstage/plugin-jenkins@0.2.0 + - @backstage/plugin-kubernetes@0.2.0 + - @backstage/plugin-lighthouse@0.2.0 + - @backstage/plugin-newrelic@0.2.0 + - @backstage/plugin-register-component@0.2.0 + - @backstage/plugin-rollbar@0.2.0 + - @backstage/plugin-scaffolder@0.2.0 + - @backstage/plugin-sentry@0.2.0 + - @backstage/plugin-tech-radar@0.2.0 + - @backstage/plugin-techdocs@0.2.0 + - @backstage/plugin-welcome@0.2.0 + - @backstage/core@0.2.0 + - @backstage/plugin-cloudbuild@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 + - @backstage/plugin-cost-insights@0.2.0 + - @backstage/plugin-user-settings@0.2.0 + - @backstage/test-utils@0.1.2 diff --git a/packages/app/package.json b/packages/app/package.json index f36806b93a..5cf74b0fbb 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,42 +1,42 @@ { "name": "example-app", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "private": true, "bundled": true, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-api-docs": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/plugin-circleci": "^0.1.1-alpha.26", - "@backstage/plugin-cloudbuild": "^0.1.1-alpha.26", - "@backstage/plugin-cost-insights": "^0.1.1-alpha.26", - "@backstage/plugin-explore": "^0.1.1-alpha.26", - "@backstage/plugin-gcp-projects": "^0.1.1-alpha.26", - "@backstage/plugin-github-actions": "^0.1.1-alpha.26", - "@backstage/plugin-gitops-profiles": "^0.1.1-alpha.26", - "@backstage/plugin-graphiql": "^0.1.1-alpha.26", - "@backstage/plugin-jenkins": "^0.1.1-alpha.26", - "@backstage/plugin-kubernetes": "^0.1.1-alpha.26", - "@backstage/plugin-lighthouse": "^0.1.1-alpha.26", - "@backstage/plugin-newrelic": "^0.1.1-alpha.26", - "@backstage/plugin-register-component": "^0.1.1-alpha.26", - "@backstage/plugin-rollbar": "^0.1.1-alpha.26", - "@backstage/plugin-scaffolder": "^0.1.1-alpha.26", - "@backstage/plugin-sentry": "^0.1.1-alpha.26", - "@backstage/plugin-tech-radar": "^0.1.1-alpha.26", - "@backstage/plugin-techdocs": "^0.1.1-alpha.26", - "@backstage/plugin-user-settings": "^0.1.1-alpha.26", - "@backstage/plugin-welcome": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/cli": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-api-docs": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/plugin-circleci": "^0.2.0", + "@backstage/plugin-cloudbuild": "^0.2.0", + "@backstage/plugin-cost-insights": "^0.2.0", + "@backstage/plugin-explore": "^0.2.0", + "@backstage/plugin-gcp-projects": "^0.2.0", + "@backstage/plugin-github-actions": "^0.2.0", + "@backstage/plugin-gitops-profiles": "^0.2.0", + "@backstage/plugin-graphiql": "^0.2.0", + "@backstage/plugin-jenkins": "^0.2.0", + "@backstage/plugin-kubernetes": "^0.2.0", + "@backstage/plugin-lighthouse": "^0.2.0", + "@backstage/plugin-newrelic": "^0.2.0", + "@backstage/plugin-register-component": "^0.2.0", + "@backstage/plugin-rollbar": "^0.2.0", + "@backstage/plugin-scaffolder": "^0.2.0", + "@backstage/plugin-sentry": "^0.2.0", + "@backstage/plugin-tech-radar": "^0.2.0", + "@backstage/plugin-techdocs": "^0.2.0", + "@backstage/plugin-user-settings": "^0.2.0", + "@backstage/plugin-welcome": "^0.2.0", + "@backstage/test-utils": "^0.1.2", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@octokit/rest": "^18.0.0", - "@roadiehq/backstage-plugin-github-insights": "^0.2.10", - "@roadiehq/backstage-plugin-github-pull-requests": "^0.6.0", - "@roadiehq/backstage-plugin-travis-ci": "^0.2.5", + "@roadiehq/backstage-plugin-github-insights": "^0.2.12", + "@roadiehq/backstage-plugin-github-pull-requests": "^0.6.1", + "@roadiehq/backstage-plugin-travis-ci": "^0.2.7", "history": "^5.0.0", "prop-types": "^15.7.2", "react": "^16.12.0", diff --git a/packages/app/src/identityProviders.ts b/packages/app/src/identityProviders.ts index 388bc8d8b6..06ff6b07d3 100644 --- a/packages/app/src/identityProviders.ts +++ b/packages/app/src/identityProviders.ts @@ -21,6 +21,7 @@ import { githubAuthApiRef, samlAuthApiRef, microsoftAuthApiRef, + oneloginAuthApiRef, } from '@backstage/core'; export const providers = [ @@ -60,4 +61,10 @@ export const providers = [ message: 'Sign In using SAML', apiRef: samlAuthApiRef, }, + { + id: 'onelogin-auth-provider', + title: 'OneLogin', + message: 'Sign In using OneLogin', + apiRef: oneloginAuthApiRef, + }, ]; diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md new file mode 100644 index 0000000000..2b8b38b9b0 --- /dev/null +++ b/packages/backend-common/CHANGELOG.md @@ -0,0 +1,64 @@ +# @backstage/backend-common + +## 0.2.0 + +### Minor Changes + +- 5249594c5: Add service discovery interface and implement for single host deployments + + Fixes #1847, #2596 + + Went with an interface similar to the frontend DiscoveryApi, since it's dead simple but still provides a lot of flexibility in the implementation. + + Also ended up with two different methods, one for internal endpoint discovery and one for external. The two use-cases are explained a bit more in the docs, but basically it's service-to-service vs callback URLs. + + This did get me thinking about uniqueness and that we're heading towards a global namespace for backend plugin IDs. That's probably fine, but if we're happy with that we should leverage it a bit more to simplify the backend setup. For example we'd have each plugin provide its own ID and not manually mount on paths in the backend. + + Draft until we're happy with the implementation, then I can add more docs and changelog entry. Also didn't go on a thorough hunt for places where discovery can be used, but I don't think there are many since it's been pretty awkward to do service-to-service communication. + +- 56e4eb589: Make CSP configurable to fix app-backend served app not being able to fetch + + See discussion [here on discord](https://discordapp.com/channels/687207715902193673/687235481154617364/758721460163575850) + +- e37c0a005: Use localhost to fall back to IPv4 if IPv6 isn't available +- f00ca3cb8: Auto-create plugin databases + + Relates to #1598. + + This creates databases for plugins before handing off control to plugins. + + The list of plugins currently need to be hard-coded depending on the installed plugins. A later PR will properly refactor the code to provide a factory pattern where plugins specify what they need, and Knex instances will be provided based on the input. + +- 6579769df: Add the ability to import components from Bitbucket Server to the service catalog +- 8c2b76e45: **BREAKING CHANGE** + + The existing loading of additional config files like `app-config.development.yaml` using APP_ENV or NODE_ENV has been removed. + Instead, the CLI and backend process now accept one or more `--config` flags to load config files. + + Without passing any flags, `app-config.yaml` and, if it exists, `app-config.local.yaml` will be loaded. + If passing any `--config ` flags, only those files will be loaded, **NOT** the default `app-config.yaml` one. + + The old behaviour of for example `APP_ENV=development` can be replicated using the following flags: + + ```bash + --config ../../app-config.yaml --config ../../app-config.development.yaml + ``` + +- 8afce088a: Use APP_ENV before NODE_ENV for determining what config to load +- 7bbeb049f: Change loadBackendConfig to return the config directly + +### Patch Changes + +- 440a17b39: Added new UrlReader interface for reading opaque data from URLs with different providers. + + This new URL reading system is intended as a replacement for the various integrations towards + external systems in the catalog, scaffolder, and techdocs. It is configured via a new top-level + config section called 'integrations'. + + Along with the UrlReader interface is a new UrlReaders class, which exposes static factory + methods for instantiating readers that can read from many different integrations simultaneously. + +- Updated dependencies [8c2b76e45] +- Updated dependencies [ce5512bc0] + - @backstage/config-loader@0.2.0 + - @backstage/test-utils@0.1.2 diff --git a/packages/backend-common/README.md b/packages/backend-common/README.md index 82db0454d2..dc08d89416 100644 --- a/packages/backend-common/README.md +++ b/packages/backend-common/README.md @@ -34,5 +34,5 @@ app.listen(PORT, () => { ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 076e644afd..c004eaac28 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.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -13,7 +13,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/backend-common" }, "keywords": [ @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli-common": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/config-loader": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli-common": "^0.1.1", + "@backstage/config": "^0.1.1", + "@backstage/config-loader": "^0.2.0", + "@backstage/test-utils": "^0.1.2", "@types/cors": "^2.8.6", "@types/express": "^4.17.6", "compression": "^1.7.4", @@ -62,7 +62,7 @@ } }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "@types/compression": "^1.7.0", "@types/http-errors": "^1.6.3", "@types/minimist": "^1.2.0", diff --git a/packages/backend-common/src/service/lib/metrics.test.ts b/packages/backend-common/src/service/lib/metrics.test.ts new file mode 100644 index 0000000000..9126423b7e --- /dev/null +++ b/packages/backend-common/src/service/lib/metrics.test.ts @@ -0,0 +1,37 @@ +/* + * 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. + */ + +import { normalizePath } from './metrics'; + +describe('normalizePath', () => { + it('should normalize /path to /path', async () => { + const path = normalizePath({ url: 'http://server/path' }); + + expect(path).toBe('/path'); + }); + + it('should normalize /path/test to /path', async () => { + const path = normalizePath({ url: 'http://server/path/test' }); + + expect(path).toBe('/path'); + }); + + it('should normalize /api/plugin-name/test to /api/plugin-name', async () => { + const path = normalizePath({ url: 'http://server/api/plugin-name/test' }); + + expect(path).toBe('/api/plugin-name'); + }); +}); diff --git a/packages/backend-common/src/service/lib/metrics.ts b/packages/backend-common/src/service/lib/metrics.ts index d7b544765b..37d441f53c 100644 --- a/packages/backend-common/src/service/lib/metrics.ts +++ b/packages/backend-common/src/service/lib/metrics.ts @@ -16,6 +16,22 @@ import prom from 'prom-client'; import promBundle from 'express-prom-bundle'; import { RequestHandler } from 'express'; +import * as url from 'url'; + +const rootRegEx = new RegExp('^/([^/]*)/.*'); +const apiRegEx = new RegExp('^/api/([^/]*)/.*'); + +export function normalizePath(req: any): string { + const path = url.parse(req.originalUrl || req.url).pathname || '/'; + + // Capture /api/ and the plugin name + if (apiRegEx.test(path)) { + return path.replace(apiRegEx, '/api/$1'); + } + + // Only the first path segment at root level + return path.replace(rootRegEx, '/$1'); +} /** * Adds a /metrics endpoint, register default runtime metrics and instrument the router. @@ -31,7 +47,7 @@ export function metricsHandler(): RequestHandler { // cardinality (e.g. path params). Instead we would have to template them. However, this // is difficult, as every backend plugin might use different routes. Instead we only take // the first directory of the path, to have at least an idea how each plugin performs: - normalizePath: [['^/([^/]*)/.*', '/$1']], + normalizePath, promClient: { collectDefaultMetrics: {} }, }); } diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md new file mode 100644 index 0000000000..a3e5535e40 --- /dev/null +++ b/packages/backend/CHANGELOG.md @@ -0,0 +1,97 @@ +# example-backend + +## 0.2.0 + +### Patch Changes + +- 440a17b39: Bump @backstage/catalog-backend and pass the now required UrlReader interface to the plugin +- 6840a68df: Pass GitHub token into Scaffolder GitHub Preparer +- 8c2b76e45: **BREAKING CHANGE** + + The existing loading of additional config files like `app-config.development.yaml` using APP_ENV or NODE_ENV has been removed. + Instead, the CLI and backend process now accept one or more `--config` flags to load config files. + + Without passing any flags, `app-config.yaml` and, if it exists, `app-config.local.yaml` will be loaded. + If passing any `--config ` flags, only those files will be loaded, **NOT** the default `app-config.yaml` one. + + The old behaviour of for example `APP_ENV=development` can be replicated using the following flags: + + ```bash + --config ../../app-config.yaml --config ../../app-config.development.yaml + ``` + +- 7bbeb049f: Change loadBackendConfig to return the config directly +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [3e254503d] +- Updated dependencies [6d29605db] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [b4e5466e1] +- Updated dependencies [6f1768c0f] +- Updated dependencies [e37c0a005] +- Updated dependencies [3472c8be7] +- Updated dependencies [57d555eb2] +- Updated dependencies [61db1ddc6] +- Updated dependencies [81cb94379] +- Updated dependencies [1687b8fbb] +- Updated dependencies [a768a07fb] +- Updated dependencies [a768a07fb] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [0c370c979] +- Updated dependencies [ce1f55398] +- Updated dependencies [e6b00e3af] +- Updated dependencies [9226c2aaa] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [99710b102] +- Updated dependencies [6579769df] +- Updated dependencies [002860e7a] +- Updated dependencies [5adfc005e] +- Updated dependencies [33454c0f2] +- Updated dependencies [183e2a30d] +- Updated dependencies [948052cbb] +- Updated dependencies [65d722455] +- Updated dependencies [b652bf2cc] +- Updated dependencies [4036ff59d] +- Updated dependencies [991a950e0] +- Updated dependencies [512d70973] +- Updated dependencies [8c2b76e45] +- Updated dependencies [8bdf0bcf5] +- Updated dependencies [c926765a2] +- Updated dependencies [5a920c6e4] +- Updated dependencies [2f62e1804] +- Updated dependencies [440a17b39] +- Updated dependencies [fa56f4615] +- Updated dependencies [8afce088a] +- Updated dependencies [4c4eab81b] +- Updated dependencies [22ff8fba5] +- Updated dependencies [36a71d278] +- Updated dependencies [b3d57961c] +- Updated dependencies [6840a68df] +- Updated dependencies [a5cb46bac] +- Updated dependencies [49d70ccab] +- Updated dependencies [1c8c43756] +- Updated dependencies [26e69ab1a] +- Updated dependencies [5e4551e3a] +- Updated dependencies [e142a2767] +- Updated dependencies [e7f5471fd] +- Updated dependencies [e3d063ffa] +- Updated dependencies [440a17b39] +- Updated dependencies [7bbeb049f] + - @backstage/plugin-app-backend@0.2.0 + - @backstage/plugin-auth-backend@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/plugin-scaffolder-backend@0.2.0 + - @backstage/plugin-techdocs-backend@0.2.0 + - @backstage/plugin-catalog-backend@0.2.0 + - @backstage/plugin-proxy-backend@0.2.0 + - @backstage/backend-common@0.2.0 + - example-app@0.2.0 + - @backstage/plugin-graphql-backend@0.1.2 + - @backstage/plugin-kubernetes-backend@0.1.2 + - @backstage/plugin-rollbar-backend@0.1.2 + - @backstage/plugin-sentry-backend@0.1.2 diff --git a/packages/backend/README.md b/packages/backend/README.md index c45a0d28d9..d458268846 100644 --- a/packages/backend/README.md +++ b/packages/backend/README.md @@ -55,9 +55,9 @@ in `app-config.yaml` under `catalog.locations`. For local development you can ov We chose [Passport](http://www.passportjs.org/) as authentication platform due to its comprehensive set of supported authentication [strategies](http://www.passportjs.org/packages/). -Read more about the [auth-backend](https://github.com/spotify/backstage/blob/master/plugins/auth-backend/README.md) and [how to add a new provider](https://github.com/spotify/backstage/blob/master/docs/auth/add-auth-provider.md) +Read more about the [auth-backend](https://github.com/backstage/backstage/blob/master/plugins/auth-backend/README.md) and [how to add a new provider](https://github.com/backstage/backstage/blob/master/docs/auth/add-auth-provider.md) ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/backend/package.json b/packages/backend/package.json index 0d066d1139..051b83a146 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "dist/index.cjs.js", "types": "src/index.ts", "private": true, @@ -18,24 +18,24 @@ "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/plugin-app-backend": "^0.1.1-alpha.26", - "@backstage/plugin-auth-backend": "^0.1.1-alpha.26", - "@backstage/plugin-catalog-backend": "^0.1.1-alpha.26", - "@backstage/plugin-graphql-backend": "^0.1.1-alpha.26", - "@backstage/plugin-kubernetes-backend": "^0.1.1-alpha.26", - "@backstage/plugin-proxy-backend": "^0.1.1-alpha.26", - "@backstage/plugin-rollbar-backend": "^0.1.1-alpha.26", - "@backstage/plugin-scaffolder-backend": "^0.1.1-alpha.26", - "@backstage/plugin-sentry-backend": "^0.1.1-alpha.26", - "@backstage/plugin-techdocs-backend": "^0.1.1-alpha.26", - "@gitbeaker/node": "^23.5.0", + "@backstage/backend-common": "^0.2.0", + "@backstage/catalog-model": "^0.2.0", + "@backstage/config": "^0.1.1", + "@backstage/plugin-app-backend": "^0.2.0", + "@backstage/plugin-auth-backend": "^0.2.0", + "@backstage/plugin-catalog-backend": "^0.2.0", + "@backstage/plugin-graphql-backend": "^0.1.2", + "@backstage/plugin-kubernetes-backend": "^0.1.2", + "@backstage/plugin-proxy-backend": "^0.2.0", + "@backstage/plugin-rollbar-backend": "^0.1.2", + "@backstage/plugin-scaffolder-backend": "^0.2.0", + "@backstage/plugin-sentry-backend": "^0.1.2", + "@backstage/plugin-techdocs-backend": "^0.2.0", + "@gitbeaker/node": "^25.2.0", "@octokit/rest": "^18.0.0", "azure-devops-node-api": "^10.1.1", "dockerode": "^3.2.0", - "example-app": "^0.1.1-alpha.26", + "example-app": "^0.2.0", "express": "^4.17.1", "express-promise-router": "^3.0.3", "knex": "^0.21.6", @@ -45,7 +45,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "@types/dockerode": "^2.5.32", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5", diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index 6eacd143c1..5d36d508a5 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -21,7 +21,9 @@ import { Publishers, CreateReactAppTemplater, Templaters, + CatalogEntityClient, } from '@backstage/plugin-scaffolder-backend'; +import { SingleHostDiscovery } from '@backstage/backend-common'; import type { PluginEnvironment } from '../types'; import Docker from 'dockerode'; @@ -40,6 +42,9 @@ export default async function createPlugin({ const dockerClient = new Docker(); + const discovery = SingleHostDiscovery.fromConfig(config); + const entityClient = new CatalogEntityClient({ discovery }); + return await createRouter({ preparers, templaters, @@ -47,5 +52,6 @@ export default async function createPlugin({ logger, config, dockerClient, + entityClient, }); } diff --git a/packages/catalog-client/.eslintrc.js b/packages/catalog-client/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/packages/catalog-client/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/packages/catalog-client/README.md b/packages/catalog-client/README.md new file mode 100644 index 0000000000..574e23cf62 --- /dev/null +++ b/packages/catalog-client/README.md @@ -0,0 +1,17 @@ +# Catalog Client + +Contains a frontend and backend compatible client for communicating with the +Backstage Catalog. + +Backend code may import and use this package directly. + +However, frontend code will not want to import this package directly - use the +`@backstage/plugin-catalog` package instead, which re-exports all of the types +and classes from this package. Thereby, you will also gain access to its +`catalogApiRef`. + +## Links + +- [Default frontend part of the catalog](https://github.com/spotify/backstage/tree/master/plugins/catalog) +- [Default backend part of the catalog](https://github.com/spotify/backstage/tree/master/plugins/catalog-backend) +- [The Backstage homepage](https://backstage.io) diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json new file mode 100644 index 0000000000..c4aa632ca9 --- /dev/null +++ b/packages/catalog-client/package.json @@ -0,0 +1,35 @@ +{ + "name": "@backstage/catalog-client", + "version": "0.2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": false, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "scripts": { + "build": "backstage-cli build", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/catalog-model": "^0.2.0", + "@backstage/config": "^0.1.1", + "cross-fetch": "^3.0.6" + }, + "devDependencies": { + "@backstage/cli": "^0.2.0", + "@types/jest": "^26.0.7", + "msw": "^0.21.2" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/catalog/src/api/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts similarity index 87% rename from plugins/catalog/src/api/CatalogClient.test.ts rename to packages/catalog-client/src/CatalogClient.test.ts index 927e8dd52c..65625c11b8 100644 --- a/plugins/catalog/src/api/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -18,17 +18,22 @@ import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { CatalogClient } from './CatalogClient'; import { Entity } from '@backstage/catalog-model'; -import { UrlPatternDiscovery } from '@backstage/core'; -import { msw } from '@backstage/test-utils'; +import { DiscoveryApi } from './types'; const server = setupServer(); const mockBaseUrl = 'http://backstage:9191/i-am-a-mock-base'; -const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); +const discoveryApi: DiscoveryApi = { + async getBaseUrl(_pluginId) { + return mockBaseUrl; + }, +}; describe('CatalogClient', () => { - let client = new CatalogClient({ discoveryApi }); + let client: CatalogClient; - msw.setupDefaultHandlers(server); + beforeAll(() => server.listen({ onUnhandledRequest: 'error' })); + afterAll(() => server.close()); + afterEach(() => server.resetHandlers()); beforeEach(() => { client = new CatalogClient({ discoveryApi }); diff --git a/plugins/catalog/src/api/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts similarity index 96% rename from plugins/catalog/src/api/CatalogClient.ts rename to packages/catalog-client/src/CatalogClient.ts index 85fd44cf01..e39759a88d 100644 --- a/plugins/catalog/src/api/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -16,16 +16,17 @@ import { Entity, + EntityName, Location, LOCATION_ANNOTATION, } from '@backstage/catalog-model'; +import fetch from 'cross-fetch'; import { AddLocationRequest, AddLocationResponse, CatalogApi, - EntityCompoundName, + DiscoveryApi, } from './types'; -import { DiscoveryApi } from '@backstage/core'; export class CatalogClient implements CatalogApi { private readonly discoveryApi: DiscoveryApi; @@ -85,9 +86,7 @@ export class CatalogClient implements CatalogApi { return await this.getRequired(path); } - async getEntityByName( - compoundName: EntityCompoundName, - ): Promise { + async getEntityByName(compoundName: EntityName): Promise { const { kind, namespace = 'default', name } = compoundName; return this.getOptional(`/entities/by-name/${kind}/${namespace}/${name}`); } diff --git a/packages/catalog-client/src/index.ts b/packages/catalog-client/src/index.ts new file mode 100644 index 0000000000..9bd13f9b7c --- /dev/null +++ b/packages/catalog-client/src/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +export { CatalogClient } from './CatalogClient'; +export type { CatalogApi } from './types'; diff --git a/packages/catalog-client/src/setupTests.ts b/packages/catalog-client/src/setupTests.ts new file mode 100644 index 0000000000..ba33cf996b --- /dev/null +++ b/packages/catalog-client/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export {}; diff --git a/plugins/catalog/src/api/types.ts b/packages/catalog-client/src/types.ts similarity index 70% rename from plugins/catalog/src/api/types.ts rename to packages/catalog-client/src/types.ts index 06030e6ac5..575b8d6ca2 100644 --- a/plugins/catalog/src/api/types.ts +++ b/packages/catalog-client/src/types.ts @@ -14,26 +14,11 @@ * limitations under the License. */ -import { createApiRef } from '@backstage/core'; -import { Entity, Location } from '@backstage/catalog-model'; - -export const catalogApiRef = createApiRef({ - id: 'plugin.catalog.service', - description: - 'Used by the Catalog plugin to make requests to accompanying backend', -}); - -export type EntityCompoundName = { - kind: string; - namespace?: string; - name: string; -}; +import { Entity, EntityName, Location } from '@backstage/catalog-model'; export interface CatalogApi { getLocationById(id: String): Promise; - getEntityByName( - compoundName: EntityCompoundName, - ): Promise; + getEntityByName(name: EntityName): Promise; getEntities(filter?: Record): Promise; addLocation(location: AddLocationRequest): Promise; getLocationByEntity(entity: Entity): Promise; @@ -50,3 +35,10 @@ export type AddLocationResponse = { location: Location; entities: Entity[]; }; + +/** + * This is a copy of the core DiscoveryApi, to avoid importing core. + */ +export type DiscoveryApi = { + getBaseUrl(pluginId: string): Promise; +}; diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md new file mode 100644 index 0000000000..051aa82c80 --- /dev/null +++ b/packages/catalog-model/CHANGELOG.md @@ -0,0 +1,28 @@ +# @backstage/catalog-model + +## 0.2.0 + +### Minor Changes + +- 3a4236570: Add handling and docs for entity references +- e0be86b6f: Entirely case insensitive read path of entities +- f70a52868: Add the User & Group entities + + A user describes a person, such as an employee, a contractor, or similar. Users belong to Group entities in the catalog. + + A group describes an organizational entity, such as for example a team, a business unit, or a loose collection of people in an interest group. Members of these groups are modeled in the catalog as kind User. + +- 12b5fe940: Add ApiDefinitionAtLocationProcessor that allows to load a API definition from another location +- a768a07fb: Add the ability to import users from GitHub Organization into the catalog. +- 5adfc005e: Changes the various kind policies into a new type `KindValidator`. + + Adds `CatalogProcessor#validateEntityKind` that makes use of the above + validators. This moves entity schema validity checking away from entity + policies and into processors, centralizing the extension points into the + processor chain. + +- b3d57961c: Enable adding locations for config files that does not yet exist by adding a flag to api request + +### Patch Changes + +- fa56f4615: Fix documentation and validation message for tags diff --git a/packages/catalog-model/README.md b/packages/catalog-model/README.md index 6dab6e7cae..8218508be9 100644 --- a/packages/catalog-model/README.md +++ b/packages/catalog-model/README.md @@ -7,6 +7,6 @@ as well as by others that want to consume catalog data. ## Links -- [Default frontend part of the catalog](https://github.com/spotify/backstage/tree/master/plugins/catalog) -- [Default backend part of the catalog](https://github.com/spotify/backstage/tree/master/plugins/catalog-backend) +- [Default frontend part of the catalog](https://github.com/backstage/backstage/tree/master/plugins/catalog) +- [Default backend part of the catalog](https://github.com/backstage/backstage/tree/master/plugins/catalog-backend) - [The Backstage homepage](https://backstage.io) diff --git a/packages/catalog-model/examples/acme-corp.yaml b/packages/catalog-model/examples/acme-corp.yaml index 7e5c5ebc61..e8047fc143 100644 --- a/packages/catalog-model/examples/acme-corp.yaml +++ b/packages/catalog-model/examples/acme-corp.yaml @@ -6,4 +6,4 @@ metadata: spec: type: github targets: - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme/org.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/org.yaml diff --git a/packages/catalog-model/examples/acme/org.yaml b/packages/catalog-model/examples/acme/org.yaml index 2d6a6a2666..8c562aaf89 100644 --- a/packages/catalog-model/examples/acme/org.yaml +++ b/packages/catalog-model/examples/acme/org.yaml @@ -18,10 +18,10 @@ metadata: spec: type: github targets: - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme/infrastructure-group.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme/boxoffice-group.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme/backstage-group.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme/team-a-group.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme/team-b-group.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme/team-c-group.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme/team-d-group.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/infrastructure-group.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/boxoffice-group.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/backstage-group.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/team-a-group.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/team-b-group.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/team-c-group.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/team-d-group.yaml diff --git a/packages/catalog-model/examples/all-apis.yaml b/packages/catalog-model/examples/all-apis.yaml index 64586fdddd..0278fc3078 100644 --- a/packages/catalog-model/examples/all-apis.yaml +++ b/packages/catalog-model/examples/all-apis.yaml @@ -6,8 +6,8 @@ metadata: spec: type: github targets: - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/apis/hello-world-api.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/apis/petstore-api.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/apis/spotify-api.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/apis/streetlights-api.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/apis/swapi-graphql.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/hello-world-api.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/petstore-api.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/spotify-api.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/streetlights-api.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/swapi-graphql.yaml diff --git a/packages/catalog-model/examples/all-components.yaml b/packages/catalog-model/examples/all-components.yaml index bef38df0b1..06c44b59d7 100644 --- a/packages/catalog-model/examples/all-components.yaml +++ b/packages/catalog-model/examples/all-components.yaml @@ -6,12 +6,12 @@ metadata: spec: type: github targets: - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/components/artist-lookup-component.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/components/petstore-component.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/components/playback-order-component.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/components/podcast-api-component.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/components/queue-proxy-component.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/components/searcher-component.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/components/playback-lib-component.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/components/www-artist-component.yaml - - https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/components/shuffle-api-component.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/artist-lookup-component.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/petstore-component.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/playback-order-component.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/podcast-api-component.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/queue-proxy-component.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/searcher-component.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/playback-lib-component.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/www-artist-component.yaml + - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/shuffle-api-component.yaml diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index c97aea9572..47d047fe9a 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-model", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,7 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1", "@types/json-schema": "^7.0.5", "@types/yup": "^0.29.8", "json-schema": "^0.2.5", @@ -29,7 +29,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "@types/express": "^4.17.6", "@types/jest": "^26.0.7", "@types/lodash": "^4.14.151", diff --git a/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.ts b/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.ts index acd4469fcb..0aabbd9e48 100644 --- a/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.ts +++ b/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.ts @@ -94,7 +94,7 @@ export class FieldFormatEntityPolicy implements EntityPolicy { : ''; throw new Error( - `"${field}" is not valid;${message} To learn more about catalog file format, visit: https://github.com/spotify/backstage/blob/master/docs/architecture-decisions/adr002-default-catalog-file-format.md`, + `"${field}" is not valid;${message} To learn more about catalog file format, visit: https://github.com/backstage/backstage/blob/master/docs/architecture-decisions/adr002-default-catalog-file-format.md`, ); } } diff --git a/packages/catalog-model/src/kinds/LocationEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/LocationEntityV1alpha1.test.ts index daa18b00cc..d9c1e9185f 100644 --- a/packages/catalog-model/src/kinds/LocationEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/LocationEntityV1alpha1.test.ts @@ -71,7 +71,7 @@ describe('LocationV1alpha1Validator', () => { it('accepts good target', async () => { (entity as any).spec.target = - 'https://github.com/spotify/backstage/blob/master/plugins/catalog-backend/examples/artist-lookup-component.yaml'; + 'https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/examples/artist-lookup-component.yaml'; await expect(validator.check(entity)).resolves.toBe(true); }); @@ -87,8 +87,8 @@ describe('LocationV1alpha1Validator', () => { it('accepts good targets', async () => { (entity as any).spec.targets = [ - 'https://github.com/spotify/backstage/blob/master/plugins/catalog-backend/examples/artist-lookup-component.yaml', - 'https://github.com/spotify/backstage/blob/master/plugins/catalog-backend/examples/playback-order-component.yaml', + 'https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/examples/artist-lookup-component.yaml', + 'https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/examples/playback-order-component.yaml', ]; await expect(validator.check(entity)).resolves.toBe(true); }); diff --git a/packages/cli-common/README.md b/packages/cli-common/README.md index 3488003a76..91b774145e 100644 --- a/packages/cli-common/README.md +++ b/packages/cli-common/README.md @@ -8,5 +8,5 @@ Do not install this package directly, it is an internal package used by [@backst ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index 56fb0d3417..0d929e53e2 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-common", "description": "Common functionality used by cli, backend, and create-app", - "version": "0.1.1-alpha.26", + "version": "0.1.1", "private": false, "main": "src/index.ts", "types": "src/index.ts", @@ -13,7 +13,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/cli-common" }, "keywords": [ diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md new file mode 100644 index 0000000000..387f5e416f --- /dev/null +++ b/packages/cli/CHANGELOG.md @@ -0,0 +1,46 @@ +# @backstage/cli + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 1d0aec70f: Upgrade dependency `esbuild@0.7.7` +- 72f6cda35: Adds a new `BACKSTAGE_CLI_BUILD_PARELLEL` environment variable to control + parallelism for some build steps. + + This is useful in CI to help avoid out of memory issues when using `terser`. The + `BACKSTAGE_CLI_BUILD_PARELLEL` environment variable can be set to + `true | false | [integer]` to override the default behaviour. See + [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin#parallel) + for more details. + +- 8c2b76e45: **BREAKING CHANGE** + + The existing loading of additional config files like `app-config.development.yaml` using APP_ENV or NODE_ENV has been removed. + Instead, the CLI and backend process now accept one or more `--config` flags to load config files. + + Without passing any flags, `app-config.yaml` and, if it exists, `app-config.local.yaml` will be loaded. + If passing any `--config ` flags, only those files will be loaded, **NOT** the default `app-config.yaml` one. + + The old behaviour of for example `APP_ENV=development` can be replicated using the following flags: + + ```bash + --config ../../app-config.yaml --config ../../app-config.development.yaml + ``` + +- 8afce088a: Use APP_ENV before NODE_ENV for determining what config to load + +### Patch Changes + +- 3472c8be7: Add codeowners processor + + - Include ESNext.Promise in TypeScript compilation + +- a3840bed2: Upgrade dependency rollup-plugin-typescript2 to ^0.27.3 +- cba4e4d97: Including source maps with all packages +- 9a3b3dbf1: Fixed duplicate help output, and print help on invalid command +- 7bbeb049f: Change loadBackendConfig to return the config directly +- Updated dependencies [8c2b76e45] +- Updated dependencies [ce5512bc0] + - @backstage/config-loader@0.2.0 diff --git a/packages/cli/README.md b/packages/cli/README.md index 8868e699c8..9eac5cdfe4 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -30,5 +30,5 @@ To try out the command locally, you can execute the following from the parent di ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/cli/config/eslint.backend.js b/packages/cli/config/eslint.backend.js index 2c0b05c196..67f0a49b9f 100644 --- a/packages/cli/config/eslint.backend.js +++ b/packages/cli/config/eslint.backend.js @@ -37,6 +37,10 @@ module.exports = { }, ignorePatterns: ['.eslintrc.js', '**/dist/**', '**/dist-types/**'], rules: { + // TODO(Rugvip): We need to bump @typescript-eslint to v4 to enable these + '@typescript-eslint/no-shadow': 0, + '@typescript-eslint/no-redeclare': 0, + 'no-console': 0, // Permitted in console programs 'new-cap': ['error', { capIsNew: false }], // Because Express constructs things e.g. like 'const r = express.Router()' 'import/newline-after-import': 'error', diff --git a/packages/cli/config/eslint.js b/packages/cli/config/eslint.js index 3e171d1f82..9b1880c1db 100644 --- a/packages/cli/config/eslint.js +++ b/packages/cli/config/eslint.js @@ -41,6 +41,10 @@ module.exports = { }, ignorePatterns: ['.eslintrc.js', '**/dist/**', '**/dist-types/**'], rules: { + // TODO(Rugvip): We need to bump @typescript-eslint to v4 to enable these + '@typescript-eslint/no-shadow': 0, + '@typescript-eslint/no-redeclare': 0, + 'import/newline-after-import': 'error', 'import/no-duplicates': 'warn', 'import/no-extraneous-dependencies': [ diff --git a/packages/cli/package.json b/packages/cli/package.json index 9f8ad850e0..7ae244866d 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.1.1-alpha.26", + "version": "0.2.0", "private": false, "publishConfig": { "access": "public" @@ -9,7 +9,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/cli" }, "keywords": [ @@ -28,9 +28,9 @@ "backstage-cli": "bin/backstage-cli" }, "dependencies": { - "@backstage/cli-common": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/config-loader": "^0.1.1-alpha.26", + "@backstage/cli-common": "^0.1.1", + "@backstage/config": "^0.1.1", + "@backstage/config-loader": "^0.2.0", "@hot-loader/react-dom": "^16.13.0", "@lerna/package-graph": "^3.18.5", "@lerna/project": "^3.18.0", @@ -38,9 +38,9 @@ "@rollup/plugin-json": "^4.0.2", "@rollup/plugin-node-resolve": "^9.0.0", "@rollup/plugin-yaml": "^2.1.1", - "@spotify/eslint-config-base": "^8.0.0", - "@spotify/eslint-config-react": "^8.0.0", - "@spotify/eslint-config-typescript": "^8.0.0", + "@spotify/eslint-config-base": "^9.0.0", + "@spotify/eslint-config-react": "^9.0.0", + "@spotify/eslint-config-typescript": "^9.0.0", "@sucrase/webpack-loader": "^2.0.0", "@svgr/plugin-jsx": "5.4.x", "@svgr/plugin-svgo": "5.4.x", @@ -108,12 +108,12 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/config": "^0.1.1", + "@backstage/core": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", + "@backstage/theme": "^0.2.0", "@types/diff": "^4.0.2", "@types/fs-extra": "^9.0.1", "@types/html-webpack-plugin": "^3.2.2", diff --git a/packages/cli/src/commands/create-plugin/createPlugin.ts b/packages/cli/src/commands/create-plugin/createPlugin.ts index c9f8b3a81d..a2005c5580 100644 --- a/packages/cli/src/commands/create-plugin/createPlugin.ts +++ b/packages/cli/src/commands/create-plugin/createPlugin.ts @@ -140,15 +140,21 @@ async function buildPlugin(pluginFolder: string) { 'yarn build', ]; for (const command of commands) { - await Task.forItem('executing', command, async () => { - process.chdir(pluginFolder); - - await exec(command).catch(error => { + try { + await Task.forItem('executing', command, async () => { + process.chdir(pluginFolder); + await exec(command); + }).catch(error => { process.stdout.write(error.stderr); process.stdout.write(error.stdout); - throw new Error(`Could not execute command ${chalk.cyan(command)}`); + throw new Error( + `Warning: Could not execute command ${chalk.cyan(command)}`, + ); }); - }); + } catch (error) { + Task.error(error.message); + break; + } } } diff --git a/packages/cli/src/lib/codeowners/codeowners.ts b/packages/cli/src/lib/codeowners/codeowners.ts index 91b0e19782..aa24f91aac 100644 --- a/packages/cli/src/lib/codeowners/codeowners.ts +++ b/packages/cli/src/lib/codeowners/codeowners.ts @@ -20,7 +20,7 @@ import path from 'path'; const TEAM_ID_RE = /^@[-\w]+\/[-\w]+$/; const USER_ID_RE = /^@[-\w]+$/; const EMAIL_RE = /^[^@]+@[-.\w]+\.[-\w]+$/i; -const DEFAULT_OWNER = '@spotify/backstage-core'; +const DEFAULT_OWNER = '@backstage/maintainers'; type CodeownersEntry = { ownedPath: string; diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md new file mode 100644 index 0000000000..9c6bee077f --- /dev/null +++ b/packages/config-loader/CHANGELOG.md @@ -0,0 +1,21 @@ +# @backstage/config-loader + +## 0.2.0 + +### Minor Changes + +- 8c2b76e45: **BREAKING CHANGE** + + The existing loading of additional config files like `app-config.development.yaml` using APP_ENV or NODE_ENV has been removed. + Instead, the CLI and backend process now accept one or more `--config` flags to load config files. + + Without passing any flags, `app-config.yaml` and, if it exists, `app-config.local.yaml` will be loaded. + If passing any `--config ` flags, only those files will be loaded, **NOT** the default `app-config.yaml` one. + + The old behaviour of for example `APP_ENV=development` can be replicated using the following flags: + + ```bash + --config ../../app-config.yaml --config ../../app-config.development.yaml + ``` + +- ce5512bc0: Added support for new shorthand when defining secrets, where `$env: ENV` can be used instead of `$secret: { env: ENV }` etc. diff --git a/packages/config-loader/README.md b/packages/config-loader/README.md index 595241e0d5..261394a6a5 100644 --- a/packages/config-loader/README.md +++ b/packages/config-loader/README.md @@ -8,5 +8,5 @@ Do not install this package directly, it is an internal package used by [@backst ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 2eef7db027..2d3474f3af 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "private": false, "publishConfig": { "access": "public", @@ -12,7 +12,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/config-loader" }, "keywords": [ @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1", "fs-extra": "^9.0.0", "yaml": "^1.9.2", "yup": "^0.29.3" diff --git a/packages/config/README.md b/packages/config/README.md index f532c682be..9866b1bce9 100644 --- a/packages/config/README.md +++ b/packages/config/README.md @@ -8,5 +8,5 @@ Do not install this package directly, it is an internal package used by [@backst ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/config/package.json b/packages/config/package.json index d8ee50e97c..f1ae07ef64 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config", "description": "Config API used by Backstage core, backend, and CLI", - "version": "0.1.1-alpha.26", + "version": "0.1.1", "private": false, "publishConfig": { "access": "public", @@ -12,7 +12,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/config" }, "keywords": [ diff --git a/packages/core-api/CHANGELOG.md b/packages/core-api/CHANGELOG.md new file mode 100644 index 0000000000..0e84d14aea --- /dev/null +++ b/packages/core-api/CHANGELOG.md @@ -0,0 +1,90 @@ +# @backstage/core-api + +## 0.2.0 + +### Minor Changes + +- 819a70229: Add SAML login to backstage + + ![](https://user-images.githubusercontent.com/872486/92251660-bb9e3400-eeff-11ea-86fe-1f2a0262cd31.png) + + ![](https://user-images.githubusercontent.com/872486/93851658-1a76f200-fce3-11ea-990b-26ca1a327a15.png) + +- b79017fd3: Updated the `GithubAuth.create` method to configure the default scope of the Github Auth Api. As a result the + default scope is configurable when overwriting the Core Api in the app. + + ``` + GithubAuth.create({ + discoveryApi, + oauthRequestApi, + defaultScopes: ['read:user', 'repo'], + }), + ``` + +- cbab5bbf8: Refactored the FeatureFlagsApi to make it easier to re-implement. Existing usage of particularly getUserFlags can be replaced with isActive() or save(). + +### Patch Changes + +- cbbd271c4: Add initial RouteRefRegistry + + Starting out some work to bring routing back and working as part of the work towards finalizing #1536 + + This is some of the groundwork of an experiment we're working on to enable routing via RouteRefs, while letting the app itself look something like this: + + ```jsx + const App = () => ( + + + + {' '} + // catalogRouteRef + + + + + + + // statusRouteRef + + + + + + + + + + // sentryRouteRef + + + + + + + + + + + + + + + + ); + ``` + + As part of inverting the composition of the app, route refs and routing in general was somewhat broken, intentionally. Right now it's not really possible to easily route to different parts of the app from a plugin, or even different parts of the plugin that are not within the same router. + + The core part of the experiment is to construct a map of ApiRef[] -> path overrides. Each key in the map is the list of route refs to traversed to reach a leaf in the routing tree, and the value is the path override at that point. For example, the above tree would add entries like [techDocsRouteRef] -> '/docs', and [entityRouteRef, apiDocsRouteRef] -> '/api'. By mapping out the entire app in this structure, the idea is that we can navigate to any point in the app using RouteRefs. + + The RouteRefRegistry is an implementation of such a map, and the idea is to add it in master to make it a bit easier to experiment and iterate. This is not an exposed API at this point. + + We've explored a couple of alternatives for how to enable routing, but it's boiled down to either a solution centred around the route map mentioned above, or treating all routes as static and globally unique, with no room for flexibility, customization or conflicts between different plugins. We're starting out pursuing this options 😁. We also expect that a the app-wide routing table will make things like dynamic loading a lot cleaner, as there would be a much more clear handoff between the main chunk and dynamic chunks. + +- 26e69ab1a: Remove cost insights example client from demo app and export from plugin + Create cost insights dev plugin using example client + Make PluginConfig and dependent types public +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] + - @backstage/theme@0.2.0 + - @backstage/test-utils@0.1.2 diff --git a/packages/core-api/README.md b/packages/core-api/README.md index 5732b5ef23..f7b8b6c337 100644 --- a/packages/core-api/README.md +++ b/packages/core-api/README.md @@ -18,5 +18,5 @@ $ yarn add @backstage/core ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/core-api/package.json b/packages/core-api/package.json index 34949e4315..42ba1c2080 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.1.1-alpha.26", + "version": "0.2.0", "private": false, "publishConfig": { "access": "public", @@ -11,7 +11,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/core-api" }, "keywords": [ @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1", + "@backstage/test-utils": "^0.1.2", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@types/react": "^16.9", @@ -42,8 +42,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/test-utils-core": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/test-utils-core": "^0.1.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/packages/core-api/src/apis/definitions/auth.ts b/packages/core-api/src/apis/definitions/auth.ts index 946baeabd9..c538065f3a 100644 --- a/packages/core-api/src/apis/definitions/auth.ts +++ b/packages/core-api/src/apis/definitions/auth.ts @@ -320,3 +320,14 @@ export const samlAuthApiRef: ApiRef< id: 'core.auth.saml', description: 'Example of how to use SAML custom provider', }); + +export const oneloginAuthApiRef: ApiRef< + OAuthApi & + OpenIdConnectApi & + ProfileInfoApi & + BackstageIdentityApi & + SessionApi +> = createApiRef({ + id: 'core.auth.onelogin', + description: 'Provides authentication towards OneLogin APIs and identities', +}); diff --git a/packages/core-api/src/apis/implementations/auth/auth0/Auth0Auth.ts b/packages/core-api/src/apis/implementations/auth/auth0/Auth0Auth.ts index 40e537169c..b41e705726 100644 --- a/packages/core-api/src/apis/implementations/auth/auth0/Auth0Auth.ts +++ b/packages/core-api/src/apis/implementations/auth/auth0/Auth0Auth.ts @@ -16,20 +16,8 @@ import Auth0Icon from '@material-ui/icons/AcUnit'; import { auth0AuthApiRef } from '../../../definitions/auth'; -import { - OAuthRequestApi, - AuthProvider, - DiscoveryApi, -} from '../../../definitions'; import { OAuth2 } from '../oauth2'; - -type CreateOptions = { - discoveryApi: DiscoveryApi; - oauthRequestApi: OAuthRequestApi; - - environment?: string; - provider?: AuthProvider & { id: string }; -}; +import { OAuthApiCreateOptions } from '../types'; const DEFAULT_PROVIDER = { id: 'auth0', @@ -43,13 +31,14 @@ class Auth0Auth { environment = 'development', provider = DEFAULT_PROVIDER, oauthRequestApi, - }: CreateOptions): typeof auth0AuthApiRef.T { + defaultScopes = ['openid', `email`, `profile`], + }: OAuthApiCreateOptions): typeof auth0AuthApiRef.T { return OAuth2.create({ discoveryApi, oauthRequestApi, provider, environment, - defaultScopes: ['openid', `email`, `profile`], + defaultScopes, }); } } diff --git a/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts b/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts index eb2f375ab0..532bff3480 100644 --- a/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts @@ -25,26 +25,13 @@ import { BackstageIdentity, AuthRequestOptions, } from '../../../definitions/auth'; -import { - OAuthRequestApi, - AuthProvider, - DiscoveryApi, -} from '../../../definitions'; import { SessionManager } from '../../../../lib/AuthSessionManager/types'; import { AuthSessionStore, StaticAuthSessionManager, } from '../../../../lib/AuthSessionManager'; import { Observable } from '../../../../types'; - -type CreateOptions = { - discoveryApi: DiscoveryApi; - oauthRequestApi: OAuthRequestApi; - - defaultScopes?: string[]; - environment?: string; - provider?: AuthProvider & { id: string }; -}; +import { OAuthApiCreateOptions } from '../types'; export type GithubAuthResponse = { providerInfo: { @@ -69,7 +56,7 @@ class GithubAuth implements OAuthApi, SessionApi { provider = DEFAULT_PROVIDER, oauthRequestApi, defaultScopes = ['read:user'], - }: CreateOptions) { + }: OAuthApiCreateOptions) { const connector = new DefaultAuthConnector({ discoveryApi, environment, diff --git a/packages/core-api/src/apis/implementations/auth/gitlab/GitlabAuth.ts b/packages/core-api/src/apis/implementations/auth/gitlab/GitlabAuth.ts index 9e2acd4537..8669dff022 100644 --- a/packages/core-api/src/apis/implementations/auth/gitlab/GitlabAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/gitlab/GitlabAuth.ts @@ -16,20 +16,8 @@ import GitlabIcon from '@material-ui/icons/AcUnit'; import { gitlabAuthApiRef } from '../../../definitions/auth'; -import { - OAuthRequestApi, - AuthProvider, - DiscoveryApi, -} from '../../../definitions'; import { OAuth2 } from '../oauth2'; - -type CreateOptions = { - discoveryApi: DiscoveryApi; - oauthRequestApi: OAuthRequestApi; - - environment?: string; - provider?: AuthProvider & { id: string }; -}; +import { OAuthApiCreateOptions } from '../types'; const DEFAULT_PROVIDER = { id: 'gitlab', @@ -43,13 +31,14 @@ class GitlabAuth { environment = 'development', provider = DEFAULT_PROVIDER, oauthRequestApi, - }: CreateOptions): typeof gitlabAuthApiRef.T { + defaultScopes = ['read_user'], + }: OAuthApiCreateOptions): typeof gitlabAuthApiRef.T { return OAuth2.create({ discoveryApi, oauthRequestApi, provider, environment, - defaultScopes: ['read_user'], + defaultScopes, }); } } diff --git a/packages/core-api/src/apis/implementations/auth/google/GoogleAuth.ts b/packages/core-api/src/apis/implementations/auth/google/GoogleAuth.ts index 7e84226508..fbc902cdd8 100644 --- a/packages/core-api/src/apis/implementations/auth/google/GoogleAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/google/GoogleAuth.ts @@ -16,20 +16,8 @@ import GoogleIcon from '@material-ui/icons/AcUnit'; import { googleAuthApiRef } from '../../../definitions/auth'; -import { - OAuthRequestApi, - AuthProvider, - DiscoveryApi, -} from '../../../definitions'; import { OAuth2 } from '../oauth2'; - -type CreateOptions = { - discoveryApi: DiscoveryApi; - oauthRequestApi: OAuthRequestApi; - - environment?: string; - provider?: AuthProvider & { id: string }; -}; +import { OAuthApiCreateOptions } from '../types'; const DEFAULT_PROVIDER = { id: 'google', @@ -37,25 +25,26 @@ const DEFAULT_PROVIDER = { icon: GoogleIcon, }; +const SCOPE_PREFIX = 'https://www.googleapis.com/auth/'; + class GoogleAuth { static create({ discoveryApi, oauthRequestApi, environment = 'development', provider = DEFAULT_PROVIDER, - }: CreateOptions): typeof googleAuthApiRef.T { - const SCOPE_PREFIX = 'https://www.googleapis.com/auth/'; - + defaultScopes = [ + 'openid', + `${SCOPE_PREFIX}userinfo.email`, + `${SCOPE_PREFIX}userinfo.profile`, + ], + }: OAuthApiCreateOptions): typeof googleAuthApiRef.T { return OAuth2.create({ discoveryApi, oauthRequestApi, provider, environment, - defaultScopes: [ - 'openid', - `${SCOPE_PREFIX}userinfo.email`, - `${SCOPE_PREFIX}userinfo.profile`, - ], + defaultScopes, scopeTransform(scopes: string[]) { return scopes.map(scope => { if (scope === 'openid') { diff --git a/packages/core-api/src/apis/implementations/auth/index.ts b/packages/core-api/src/apis/implementations/auth/index.ts index 39223e8e15..7ef78d19cf 100644 --- a/packages/core-api/src/apis/implementations/auth/index.ts +++ b/packages/core-api/src/apis/implementations/auth/index.ts @@ -22,3 +22,4 @@ export * from './okta'; export * from './saml'; export * from './auth0'; export * from './microsoft'; +export * from './onelogin'; diff --git a/packages/core-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts b/packages/core-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts index 241ac7b802..3e2711db3b 100644 --- a/packages/core-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts @@ -16,21 +16,8 @@ import MicrosoftIcon from '@material-ui/icons/AcUnit'; import { microsoftAuthApiRef } from '../../../definitions/auth'; - -import { - OAuthRequestApi, - AuthProvider, - DiscoveryApi, -} from '../../../definitions'; import { OAuth2 } from '../oauth2'; - -type CreateOptions = { - discoveryApi: DiscoveryApi; - oauthRequestApi: OAuthRequestApi; - - environment?: string; - provider?: AuthProvider & { id: string }; -}; +import { OAuthApiCreateOptions } from '../types'; const DEFAULT_PROVIDER = { id: 'microsoft', @@ -44,19 +31,20 @@ class MicrosoftAuth { provider = DEFAULT_PROVIDER, oauthRequestApi, discoveryApi, - }: CreateOptions): typeof microsoftAuthApiRef.T { + defaultScopes = [ + 'openid', + 'offline_access', + 'profile', + 'email', + 'User.Read', + ], + }: OAuthApiCreateOptions): typeof microsoftAuthApiRef.T { return OAuth2.create({ discoveryApi, oauthRequestApi, provider, environment, - defaultScopes: [ - 'openid', - 'offline_access', - 'profile', - 'email', - 'User.Read', - ], + defaultScopes, }); } } diff --git a/packages/core-api/src/apis/implementations/auth/oauth2/OAuth2.ts b/packages/core-api/src/apis/implementations/auth/oauth2/OAuth2.ts index d088ca9798..73ad3dcf14 100644 --- a/packages/core-api/src/apis/implementations/auth/oauth2/OAuth2.ts +++ b/packages/core-api/src/apis/implementations/auth/oauth2/OAuth2.ts @@ -19,11 +19,6 @@ import { DefaultAuthConnector } from '../../../../lib/AuthConnector'; import { RefreshingAuthSessionManager } from '../../../../lib/AuthSessionManager'; import { SessionManager } from '../../../../lib/AuthSessionManager/types'; import { Observable } from '../../../../types'; -import { - AuthProvider, - OAuthRequestApi, - DiscoveryApi, -} from '../../../definitions'; import { AuthRequestOptions, BackstageIdentity, @@ -36,19 +31,14 @@ import { BackstageIdentityApi, } from '../../../definitions/auth'; import { OAuth2Session } from './types'; +import { OAuthApiCreateOptions } from '../types'; type Options = { sessionManager: SessionManager; scopeTransform: (scopes: string[]) => string[]; }; -type CreateOptions = { - discoveryApi: DiscoveryApi; - oauthRequestApi: OAuthRequestApi; - - environment?: string; - provider?: AuthProvider & { id: string }; - defaultScopes?: string[]; +type CreateOptions = OAuthApiCreateOptions & { scopeTransform?: (scopes: string[]) => string[]; }; diff --git a/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.ts b/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.ts index 7e9ff77678..2df908e9fb 100644 --- a/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.ts @@ -16,20 +16,8 @@ import OktaIcon from '@material-ui/icons/AcUnit'; import { oktaAuthApiRef } from '../../../definitions/auth'; -import { - OAuthRequestApi, - AuthProvider, - DiscoveryApi, -} from '../../../definitions'; import { OAuth2 } from '../oauth2'; - -type CreateOptions = { - discoveryApi: DiscoveryApi; - oauthRequestApi: OAuthRequestApi; - - environment?: string; - provider?: AuthProvider & { id: string }; -}; +import { OAuthApiCreateOptions } from '../types'; const DEFAULT_PROVIDER = { id: 'okta', @@ -55,13 +43,14 @@ class OktaAuth { environment = 'development', provider = DEFAULT_PROVIDER, oauthRequestApi, - }: CreateOptions): typeof oktaAuthApiRef.T { + defaultScopes = ['openid', 'email', 'profile', 'offline_access'], + }: OAuthApiCreateOptions): typeof oktaAuthApiRef.T { return OAuth2.create({ discoveryApi, oauthRequestApi, provider, environment, - defaultScopes: ['openid', 'email', 'profile', 'offline_access'], + defaultScopes, scopeTransform(scopes) { return scopes.map(scope => { if (OKTA_OIDC_SCOPES.has(scope)) { diff --git a/packages/core-api/src/apis/implementations/auth/onelogin/OneLoginAuth.ts b/packages/core-api/src/apis/implementations/auth/onelogin/OneLoginAuth.ts new file mode 100644 index 0000000000..ff5c7c1990 --- /dev/null +++ b/packages/core-api/src/apis/implementations/auth/onelogin/OneLoginAuth.ts @@ -0,0 +1,82 @@ +/* + * 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. + */ + +import OneLoginIcon from '@material-ui/icons/AcUnit'; +import { oneloginAuthApiRef } from '../../../definitions/auth'; +import { + OAuthRequestApi, + AuthProvider, + DiscoveryApi, +} from '../../../definitions'; +import { OAuth2 } from '../oauth2'; + +type CreateOptions = { + discoveryApi: DiscoveryApi; + oauthRequestApi: OAuthRequestApi; + + environment?: string; + provider?: AuthProvider & { id: string }; +}; + +const DEFAULT_PROVIDER = { + id: 'onelogin', + title: 'onelogin', + icon: OneLoginIcon, +}; + +const OIDC_SCOPES: Set = new Set([ + 'openid', + 'profile', + 'email', + 'phone', + 'address', + 'groups', + 'offline_access', +]); + +const SCOPE_PREFIX: string = 'onelogin.'; + +class OneLoginAuth { + static create({ + discoveryApi, + environment = 'development', + provider = DEFAULT_PROVIDER, + oauthRequestApi, + }: CreateOptions): typeof oneloginAuthApiRef.T { + return OAuth2.create({ + discoveryApi, + oauthRequestApi, + provider, + environment, + defaultScopes: ['openid', 'email', 'profile', 'offline_access'], + scopeTransform(scopes) { + return scopes.map(scope => { + if (OIDC_SCOPES.has(scope)) { + return scope; + } + + if (scope.startsWith(SCOPE_PREFIX)) { + return scope; + } + + return `${SCOPE_PREFIX}${scope}`; + }); + }, + }); + } +} + +export default OneLoginAuth; diff --git a/packages/core-api/src/apis/implementations/auth/onelogin/index.ts b/packages/core-api/src/apis/implementations/auth/onelogin/index.ts new file mode 100644 index 0000000000..1d163207db --- /dev/null +++ b/packages/core-api/src/apis/implementations/auth/onelogin/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export { default as OneLoginAuth } from './OneLoginAuth'; diff --git a/packages/core-api/src/apis/implementations/auth/saml/SamlAuth.ts b/packages/core-api/src/apis/implementations/auth/saml/SamlAuth.ts index 973b402756..da5f082c9b 100644 --- a/packages/core-api/src/apis/implementations/auth/saml/SamlAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/saml/SamlAuth.ts @@ -27,18 +27,12 @@ import { BackstageIdentityApi, SessionApi, } from '../../../definitions/auth'; -import { AuthProvider, DiscoveryApi } from '../../../definitions'; import { SamlSession } from './types'; import { AuthSessionStore, StaticAuthSessionManager, } from '../../../../lib/AuthSessionManager'; - -type CreateOptions = { - discoveryApi: DiscoveryApi; - environment?: string; - provider?: AuthProvider & { id: string }; -}; +import { AuthApiCreateOptions } from '../types'; export type SamlAuthResponse = { profile: ProfileInfo; @@ -56,7 +50,7 @@ class SamlAuth implements ProfileInfoApi, BackstageIdentityApi, SessionApi { discoveryApi, environment = 'development', provider = DEFAULT_PROVIDER, - }: CreateOptions) { + }: AuthApiCreateOptions) { const connector = new DirectAuthConnector({ discoveryApi, environment, diff --git a/packages/core-api/src/apis/implementations/auth/types.ts b/packages/core-api/src/apis/implementations/auth/types.ts new file mode 100644 index 0000000000..db3b718d25 --- /dev/null +++ b/packages/core-api/src/apis/implementations/auth/types.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +import { AuthProvider, DiscoveryApi, OAuthRequestApi } from '../../definitions'; + +export type OAuthApiCreateOptions = AuthApiCreateOptions & { + oauthRequestApi: OAuthRequestApi; + defaultScopes?: string[]; +}; + +export type AuthApiCreateOptions = { + discoveryApi: DiscoveryApi; + environment?: string; + provider?: AuthProvider & { id: string }; +}; diff --git a/packages/core-api/src/apis/system/ApiRegistry.ts b/packages/core-api/src/apis/system/ApiRegistry.ts index 14f58268b4..b105633c51 100644 --- a/packages/core-api/src/apis/system/ApiRegistry.ts +++ b/packages/core-api/src/apis/system/ApiRegistry.ts @@ -27,7 +27,7 @@ class ApiRegistryBuilder { } build(): ApiRegistry { - // eslint-disable-next-line no-use-before-define + // eslint-disable-next-line @typescript-eslint/no-use-before-define return new ApiRegistry(new Map(this.apis)); } } diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md new file mode 100644 index 0000000000..10110a7b24 --- /dev/null +++ b/packages/core/CHANGELOG.md @@ -0,0 +1,70 @@ +# @backstage/core + +## 0.2.0 + +### Minor Changes + +- 819a70229: Add SAML login to backstage + + ![](https://user-images.githubusercontent.com/872486/92251660-bb9e3400-eeff-11ea-86fe-1f2a0262cd31.png) + + ![](https://user-images.githubusercontent.com/872486/93851658-1a76f200-fce3-11ea-990b-26ca1a327a15.png) + +- 482b6313d: Fix dense in Structured Metadata Table +- 1c60f716e: Added EmptyState component +- b79017fd3: Updated the `GithubAuth.create` method to configure the default scope of the Github Auth Api. As a result the + default scope is configurable when overwriting the Core Api in the app. + + ``` + GithubAuth.create({ + discoveryApi, + oauthRequestApi, + defaultScopes: ['read:user', 'repo'], + }), + ``` + +- 6d97d2d6f: The InfoCard variant `'height100'` is deprecated. Use variant `'gridItem'` instead. + + When the InfoCard is displayed as a grid item within a grid, you may want items to have the same height for all items. + Set to the `'gridItem'` variant to display the InfoCard with full height suitable for Grid: + `...` + + Changed the InfoCards in '@backstage/plugin-github-actions', '@backstage/plugin-jenkins', '@backstage/plugin-lighthouse' + to pass an optional variant to the corresponding card of the plugin. + + As a result the overview content of the EntityPage shows cards with full height suitable for Grid. + +### Patch Changes + +- ae5983387: Fix banner position and color + + This PR closes: #2245 + + The "fixed" props added to control the position of the banner. When it is set to true the banner will be shown in bottom of that page and the width will be based on the content of the message. + + ![](https://user-images.githubusercontent.com/15106494/93765685-999df480-fc15-11ea-8fa5-11cac5836cf1.png) + + ![](https://user-images.githubusercontent.com/15106494/93765697-9e62a880-fc15-11ea-92af-b6a7fee4bb21.png) + +- 144c66d50: Fixed banner component position in DismissableBanner component +- 93a3fa3ae: Add forwardRef to the SidebarItem +- 782f3b354: add test case for Progress component +- 2713f28f4: fix the warning of all the core components test cases +- 406015b0d: Update ItemCard headers to pass color contrast standards. +- 82759d3e4: rename stories folder top Chip +- ac8d5d5c7: update the test cases of CodeSnippet component +- ebca83d48: add test cases for Status components +- aca79334f: update ItemCard component and it's story +- c0d5242a0: Proper render boolean values on StructuredMetadataTable component +- 3beb5c9fc: make ErrorPage responsive + fix the test case +- 754e31db5: give aria-label attribute to Status Ok, Warning and Error +- 1611c6dbc: fix the responsive of page story +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [cbbd271c4] +- Updated dependencies [b79017fd3] +- Updated dependencies [26e69ab1a] +- Updated dependencies [cbab5bbf8] + - @backstage/core-api@0.2.0 + - @backstage/theme@0.2.0 diff --git a/packages/core/README.md b/packages/core/README.md index a22f66ecd9..0d0063c9fd 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -18,5 +18,5 @@ $ yarn add @backstage/core ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/core/package.json b/packages/core/package.json index ec4411b390..0ddc77f1e4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core", "description": "Core API used by Backstage plugins and apps", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "private": false, "publishConfig": { "access": "public", @@ -11,7 +11,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/core" }, "keywords": [ @@ -29,16 +29,21 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/core-api": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1", + "@backstage/core-api": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", + "@types/dagre": "^0.7.44", "@types/react": "^16.9", "@types/react-sparklines": "^1.7.0", "classnames": "^2.2.6", "clsx": "^1.1.0", + "d3-selection": "^2.0.0", + "d3-shape": "^2.0.0", + "d3-zoom": "^2.0.0", + "dagre": "^0.8.5", "immer": "^7.0.9", "lodash": "^4.17.15", "material-table": "^1.69.1", @@ -48,19 +53,24 @@ "react-dom": "^16.12.0", "react-helmet": "6.1.0", "react-hook-form": "^6.6.0", + "react-markdown": "^5.0.2", "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", "react-sparklines": "^1.7.0", "react-syntax-highlighter": "^13.5.1", - "react-use": "^15.3.3" + "react-use": "^15.3.3", + "remark-gfm": "^1.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/classnames": "^2.2.9", + "@types/d3-selection": "^2.0.0", + "@types/d3-shape": "^2.0.0", + "@types/d3-zoom": "^2.0.0", "@types/google-protobuf": "^3.7.2", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", diff --git a/packages/core/src/api-wrappers/createApp.test.tsx b/packages/core/src/api-wrappers/createApp.test.tsx index a1655b88dd..31f584b68c 100644 --- a/packages/core/src/api-wrappers/createApp.test.tsx +++ b/packages/core/src/api-wrappers/createApp.test.tsx @@ -18,10 +18,12 @@ import { defaultConfigLoader } from './createApp'; (process as any).env = { NODE_ENV: 'test' }; const anyEnv = process.env as any; +const anyWindow = window as any; describe('defaultConfigLoader', () => { afterEach(() => { delete anyEnv.APP_CONFIG; + delete anyWindow.__APP_CONFIG__; }); it('loads static config', async () => { @@ -73,4 +75,20 @@ describe('defaultConfigLoader', () => { 'Failed to load runtime configuration, SyntaxError: Unexpected token } in JSON at position 0', ); }); + + it('loads config from window.__APP_CONFIG__', async () => { + anyEnv.APP_CONFIG = [ + { data: { my: 'config' }, context: 'a' }, + { data: { my: 'override-config' }, context: 'b' }, + ]; + const windowConfig = { app: { configKey: 'config-value' } }; + anyWindow.__APP_CONFIG__ = windowConfig; + + const configs = await defaultConfigLoader(); + + expect(configs).toEqual([ + ...anyEnv.APP_CONFIG, + { context: 'window', data: windowConfig }, + ]); + }); }); diff --git a/packages/core/src/api-wrappers/createApp.tsx b/packages/core/src/api-wrappers/createApp.tsx index c7d0f5ce01..592a2417ca 100644 --- a/packages/core/src/api-wrappers/createApp.tsx +++ b/packages/core/src/api-wrappers/createApp.tsx @@ -67,6 +67,13 @@ export const defaultConfigLoader: AppConfigLoader = async ( } } + const windowAppConfig = (window as any).__APP_CONFIG__; + if (windowAppConfig) { + configs.push({ + context: 'window', + data: windowAppConfig, + }); + } return configs; }; diff --git a/packages/core/src/api-wrappers/defaultApis.ts b/packages/core/src/api-wrappers/defaultApis.ts index d0a777dc94..61d4f3a7e1 100644 --- a/packages/core/src/api-wrappers/defaultApis.ts +++ b/packages/core/src/api-wrappers/defaultApis.ts @@ -44,6 +44,8 @@ import { UrlPatternDiscovery, samlAuthApiRef, SamlAuth, + oneloginAuthApiRef, + OneLoginAuth, } from '@backstage/core-api'; export const defaultApis = [ @@ -142,4 +144,13 @@ export const defaultApis = [ }, factory: ({ discoveryApi }) => SamlAuth.create({ discoveryApi }), }), + createApiFactory({ + api: oneloginAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + OneLoginAuth.create({ discoveryApi, oauthRequestApi }), + }), ]; diff --git a/packages/core/src/components/Chip/Chip.stories.tsx b/packages/core/src/components/Chip/Chip.stories.tsx index a605666482..87d904ad0e 100644 --- a/packages/core/src/components/Chip/Chip.stories.tsx +++ b/packages/core/src/components/Chip/Chip.stories.tsx @@ -39,3 +39,5 @@ export const SmallDeletable = () => ( export const SmallNotDeletable = () => ( ); + +export const Outline = () => ; diff --git a/packages/core/src/components/DependencyGraph/DefaultLabel.tsx b/packages/core/src/components/DependencyGraph/DefaultLabel.tsx new file mode 100644 index 0000000000..0679d1dae0 --- /dev/null +++ b/packages/core/src/components/DependencyGraph/DefaultLabel.tsx @@ -0,0 +1,35 @@ +/* + * 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. + */ + +import React from 'react'; +import makeStyles from '@material-ui/core/styles/makeStyles'; +import { BackstageTheme } from '@backstage/theme'; +import { RenderLabelProps } from './types'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + text: { + fill: theme.palette.textContrast, + }, +})); + +export function DefaultLabel({ edge: { label } }: RenderLabelProps) { + const classes = useStyles(); + return ( + + {label} + + ); +} diff --git a/packages/core/src/components/DependencyGraph/DefaultNode.tsx b/packages/core/src/components/DependencyGraph/DefaultNode.tsx new file mode 100644 index 0000000000..9656c860ae --- /dev/null +++ b/packages/core/src/components/DependencyGraph/DefaultNode.tsx @@ -0,0 +1,79 @@ +/* + * 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. + */ + +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import { BackstageTheme } from '@backstage/theme'; +import { RenderNodeProps } from './types'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + node: { + fill: theme.palette.background.paper, + stroke: theme.palette.border, + }, + text: { + fill: theme.palette.textContrast, + }, +})); + +export function DefaultNode({ node: { id } }: RenderNodeProps) { + const classes = useStyles(); + const [width, setWidth] = React.useState(0); + const [height, setHeight] = React.useState(0); + const idRef = React.useRef(null); + + React.useLayoutEffect(() => { + // set the width to the length of the ID + if (idRef.current) { + let { + height: renderedHeight, + width: renderedWidth, + } = idRef.current.getBBox(); + renderedHeight = Math.round(renderedHeight); + renderedWidth = Math.round(renderedWidth); + + if (renderedHeight !== height || renderedWidth !== width) { + setWidth(renderedWidth); + setHeight(renderedHeight); + } + } + }, [width, height]); + + const padding = 10; + const paddedWidth = width + padding * 2; + const paddedHeight = height + padding * 2; + + return ( + + + + {id} + + + ); +} diff --git a/packages/core/src/components/DependencyGraph/DependencyGraph.stories.tsx b/packages/core/src/components/DependencyGraph/DependencyGraph.stories.tsx new file mode 100644 index 0000000000..e39ecfc5da --- /dev/null +++ b/packages/core/src/components/DependencyGraph/DependencyGraph.stories.tsx @@ -0,0 +1,178 @@ +/* + * 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. + */ + +import React from 'react'; +import { DependencyGraph } from './DependencyGraph'; +import { Direction, LabelPosition } from './types'; + +export default { + title: 'Data Display/DependencyGraph', + component: DependencyGraph, +}; + +const containerStyle = { width: '100%' }; +const graphStyle = { border: '1px solid grey' }; + +const exampleNodes = [ + { id: 'source' }, + { id: 'downstream' }, + { id: 'second-downstream' }, + { id: 'third-downstream' }, +]; + +const exampleEdges = [ + { from: 'source', to: 'downstream' }, + { from: 'downstream', to: 'second-downstream' }, + { from: 'downstream', to: 'third-downstream' }, +]; + +export const Default = () => ( +

+ +
+); + +export const BottomToTop = () => ( +
+ +
+); + +export const LeftToRight = () => ( +
+ +
+); + +export const RightToLeft = () => ( +
+ +
+); + +export const WithLabels = () => { + const edges = exampleEdges.map(edge => ({ ...edge, label: 'label' })); + return ( +
+ +
+ ); +}; + +export const CustomNodes = () => { + const colors = ['pink', 'coral', 'yellowgreen', 'aquamarine']; + const nodes = exampleNodes.map((node, index) => ({ + ...node, + description: 'Description text', + color: colors[index], + })); + return ( +
+ ( + + + + {props.node.id} + + + {props.node.description} + + + )} + /> +
+ ); +}; + +export const CustomLabels = () => { + const colors = ['pink', 'coral', 'aqua']; + const edges = exampleEdges.map((edge, index) => ({ + ...edge, + label: colors[index], + color: colors[index], + })); + return ( +
+ ( + + + + {props.edge.label} + + + )} + /> +
+ ); +}; diff --git a/packages/core/src/components/DependencyGraph/DependencyGraph.test.tsx b/packages/core/src/components/DependencyGraph/DependencyGraph.test.tsx new file mode 100644 index 0000000000..526dc6d7dd --- /dev/null +++ b/packages/core/src/components/DependencyGraph/DependencyGraph.test.tsx @@ -0,0 +1,106 @@ +/* + * 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. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { DependencyGraph } from './DependencyGraph'; +import { RenderLabelProps, RenderNodeProps } from './types'; +import { EDGE_TEST_ID, LABEL_TEST_ID, NODE_TEST_ID } from './constants'; + +describe('', () => { + beforeAll(() => { + Object.defineProperty(window.SVGElement.prototype, 'getBBox', { + value: () => ({ width: 100, height: 100 }), + configurable: true, + }); + }); + + const nodes = [{ id: 'a' }, { id: 'b' }, { id: 'c' }]; + const edges = [ + { from: nodes[0].id, to: nodes[1].id }, + { from: nodes[1].id, to: nodes[2].id }, + ]; + + const CUSTOM_TEST_ID = 'custom-test-id'; + + it('renders each node and edge supplied', async () => { + const { getByText, queryAllByTestId, findAllByTestId } = render( + , + ); + const renderedNodes = await findAllByTestId(NODE_TEST_ID); + expect(renderedNodes).toHaveLength(3); + expect(getByText(nodes[0].id)).toBeInTheDocument(); + expect(getByText(nodes[1].id)).toBeInTheDocument(); + expect(getByText(nodes[2].id)).toBeInTheDocument(); + expect(queryAllByTestId(EDGE_TEST_ID)).toHaveLength(2); + expect(queryAllByTestId(LABEL_TEST_ID)).toHaveLength(0); + }); + + it('renders edge labels if present', async () => { + const labeledEdges = [ + { ...edges[0], label: 'first' }, + { ...edges[1], label: 'second' }, + ]; + const { getByText, getAllByTestId, findAllByTestId } = render( + , + ); + const renderedEdges = await findAllByTestId(EDGE_TEST_ID); + expect(renderedEdges).toHaveLength(2); + expect(getAllByTestId(LABEL_TEST_ID)).toHaveLength(2); + expect(getByText(labeledEdges[0].label)).toBeInTheDocument(); + expect(getByText(labeledEdges[1].label)).toBeInTheDocument(); + }); + + it('renders nodes according to renderNode prop', async () => { + const singleNode = [nodes[0]]; + + const renderNode = (props: RenderNodeProps) => ( + + {props.node.id} + + + ); + const { getByText, findByTestId, container } = render( + , + ); + const node = await findByTestId(CUSTOM_TEST_ID); + expect(node).toBeInTheDocument(); + expect(container.querySelector('circle')).toBeInTheDocument(); + expect(getByText(singleNode[0].id)).toBeInTheDocument(); + }); + + it('renders labels according to renderLabel prop', async () => { + const labeledEdge = [{ ...edges[0], label: 'label' }]; + + const renderLabel = (props: RenderLabelProps) => ( + + {props.edge.label} + + + ); + const { getByText, findByTestId, container } = render( + , + ); + const node = await findByTestId(CUSTOM_TEST_ID); + expect(node).toBeInTheDocument(); + expect(container.querySelector('circle')).toBeInTheDocument(); + expect(getByText(labeledEdge[0].label)).toBeInTheDocument(); + }); +}); diff --git a/packages/core/src/components/DependencyGraph/DependencyGraph.tsx b/packages/core/src/components/DependencyGraph/DependencyGraph.tsx new file mode 100644 index 0000000000..ced0bdf276 --- /dev/null +++ b/packages/core/src/components/DependencyGraph/DependencyGraph.tsx @@ -0,0 +1,324 @@ +/* + * 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. + */ + +import React from 'react'; +import * as d3Zoom from 'd3-zoom'; +import * as d3Selection from 'd3-selection'; +import useTheme from '@material-ui/core/styles/useTheme'; +import dagre from 'dagre'; +import debounce from 'lodash/debounce'; +import { BackstageTheme } from '@backstage/theme'; +import { + DependencyEdge, + DependencyNode, + Direction, + Alignment, + Ranker, + RenderNodeFunction, + RenderLabelFunction, + GraphEdge, + GraphNode, + LabelPosition, +} from './types'; +import { Node } from './Node'; +import { Edge } from './Edge'; +import { ARROW_MARKER_ID } from './constants'; + +export type DependencyGraphProps = React.SVGProps & { + edges: DependencyEdge[]; + nodes: DependencyNode[]; + direction?: Direction; + align?: Alignment; + nodeMargin?: number; + edgeMargin?: number; + rankMargin?: number; + paddingX?: number; + paddingY?: number; + acyclicer?: 'greedy'; + ranker?: Ranker; + labelPosition?: LabelPosition; + labelOffset?: number; + edgeRanks?: number; + edgeWeight?: number; + renderNode?: RenderNodeFunction; + renderLabel?: RenderLabelFunction; + defs?: SVGDefsElement | SVGDefsElement[]; +}; + +const WORKSPACE_ID = 'workspace'; + +export function DependencyGraph({ + edges, + nodes, + renderNode, + direction = Direction.TOP_BOTTOM, + align, + nodeMargin = 50, + edgeMargin = 10, + rankMargin = 50, + paddingX = 0, + paddingY = 0, + acyclicer, + ranker = Ranker.NETWORK_SIMPLEX, + labelPosition = LabelPosition.RIGHT, + labelOffset = 10, + edgeRanks = 1, + edgeWeight = 1, + renderLabel, + defs, + ...svgProps +}: DependencyGraphProps) { + const theme: BackstageTheme = useTheme(); + const [containerWidth, setContainerWidth] = React.useState(100); + const [containerHeight, setContainerHeight] = React.useState(100); + + const graph = React.useRef>( + new dagre.graphlib.Graph(), + ); + const [graphWidth, setGraphWidth] = React.useState( + graph.current.graph()?.width || 0, + ); + const [graphHeight, setGraphHeight] = React.useState( + graph.current.graph()?.height || 0, + ); + const [graphNodes, setGraphNodes] = React.useState([]); + const [graphEdges, setGraphEdges] = React.useState([]); + + const maxWidth = Math.max(graphWidth, containerWidth); + const maxHeight = Math.max(graphHeight, containerHeight); + + const containerRef = React.useMemo( + () => + debounce((node: SVGSVGElement) => { + if (!node) { + return; + } + // Set up zooming + panning + const container = d3Selection.select(node); + const workspace = d3Selection.select(node.getElementById(WORKSPACE_ID)); + const zoom = d3Zoom + .zoom() + .scaleExtent([1, 10]) + .on('zoom', event => { + event.transform.x = Math.min( + 0, + Math.max( + event.transform.x, + maxWidth - maxWidth * event.transform.k, + ), + ); + event.transform.y = Math.min( + 0, + Math.max( + event.transform.y, + maxHeight - maxHeight * event.transform.k, + ), + ); + workspace.attr('transform', event.transform); + }); + + container.call(zoom); + + const { + width: newContainerWidth, + height: newContainerHeight, + } = node.getBoundingClientRect(); + if (containerWidth !== newContainerWidth) { + setContainerWidth(newContainerWidth); + } + if (containerHeight !== newContainerHeight) { + setContainerHeight(newContainerHeight); + } + }, 100), + [containerHeight, containerWidth, maxWidth, maxHeight], + ); + + const setNodesAndEdges = React.useCallback(() => { + // Cleaning up lingering nodes and edges + const currentGraphNodes = graph.current.nodes(); + const currentGraphEdges = graph.current.edges(); + + currentGraphNodes.forEach(nodeId => { + const remainingNode = nodes.some(node => node.id === nodeId); + if (!remainingNode) { + graph.current.removeNode(nodeId); + } + }); + + currentGraphEdges.forEach(e => { + const remainingEdge = edges.some( + edge => edge.from === e.v && edge.to === e.w, + ); + if (!remainingEdge) { + graph.current.removeEdge(e.v, e.w); + } + }); + + // Adding/updating nodes and edges + nodes.forEach(node => { + const existingNode = graph.current + .nodes() + .find(nodeId => node.id === nodeId); + + if (existingNode) { + const { width, height, x, y } = graph.current.node(existingNode); + graph.current.setNode(existingNode, { ...node, width, height, x, y }); + } else { + graph.current.setNode(node.id, { ...node, width: 0, height: 0 }); + } + }); + + edges.forEach(e => { + graph.current.setEdge(e.from, e.to, { + ...e, + label: e.label, + width: 0, + height: 0, + labelpos: labelPosition, + labeloffset: labelOffset, + weight: edgeWeight, + minlen: edgeRanks, + }); + }); + }, [edges, nodes, labelPosition, labelOffset, edgeWeight, edgeRanks]); + + const updateGraph = React.useMemo( + () => + debounce( + () => { + dagre.layout(graph.current); + const { height, width } = graph.current.graph(); + const newHeight = Math.max(0, height || 0); + const newWidth = Math.max(0, width || 0); + setGraphWidth(newWidth); + setGraphHeight(newHeight); + + setGraphNodes(graph.current.nodes()); + setGraphEdges(graph.current.edges()); + }, + 250, + { leading: true }, + ), + [], + ); + + React.useEffect(() => { + graph.current.setGraph({ + rankdir: direction, + align, + nodesep: nodeMargin, + edgesep: edgeMargin, + ranksep: rankMargin, + marginx: paddingX, + marginy: paddingY, + acyclicer, + ranker, + }); + + setNodesAndEdges(); + updateGraph(); + + return updateGraph.cancel; + }, [ + acyclicer, + align, + direction, + edgeMargin, + paddingX, + paddingY, + nodeMargin, + rankMargin, + ranker, + setNodesAndEdges, + updateGraph, + ]); + + function setNode(id: string, node: DependencyNode) { + graph.current.setNode(id, node); + updateGraph(); + return graph.current; + } + + function setEdge(id: dagre.Edge, edge: DependencyEdge) { + graph.current.setEdge(id, edge); + updateGraph(); + return graph.current; + } + + return ( + + + + + + {defs} + + + + {graphEdges.map(e => { + const edge = graph.current.edge(e) as GraphEdge; + if (!edge) return null; + return ( + + ); + })} + {graphNodes.map((id: string) => { + const node = graph.current.node(id) as GraphNode; + if (!node) return null; + return ( + + ); + })} + + + + ); +} diff --git a/packages/core/src/components/DependencyGraph/Edge.test.tsx b/packages/core/src/components/DependencyGraph/Edge.test.tsx new file mode 100644 index 0000000000..b651c17bf0 --- /dev/null +++ b/packages/core/src/components/DependencyGraph/Edge.test.tsx @@ -0,0 +1,100 @@ +/* + * 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. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { Edge } from './Edge'; +import { RenderLabelProps } from './types'; + +const fromNode = 'node'; +const toNode = 'other-node'; + +const edge = { + from: fromNode, + to: toNode, +}; + +const id = { + v: fromNode, + w: toNode, +}; + +const setEdge = jest.fn(); +const renderElement = jest.fn((props: RenderLabelProps) => ( + {props.edge.label} +)); + +const minProps = { + points: [ + { x: 10, y: 20 }, + { x: 20, y: 20 }, + ], + id, + setEdge, + renderElement, + edge, +}; + +const label = 'label'; +const edgeWithLabel = { ...edge, label }; + +describe('', () => { + beforeEach(() => { + // jsdom does not support SVG elements so we have to fall back to HTMLUnknownElement + Object.defineProperty(window.HTMLUnknownElement.prototype, 'getBBox', { + value: () => ({ width: 100, height: 100 }), + configurable: true, + }); + }); + + afterEach(jest.clearAllMocks); + + it('does not render the supplied label element if label is missing', () => { + const { container } = render(); + expect(container.getElementsByTagName('g')).toHaveLength(0); + }); + + it('renders the supplied label element if label is present', () => { + const { getByText } = render(); + expect(getByText(label)).toBeInTheDocument(); + }); + + it('passes down edge properties to the render method if label is present', () => { + const edgeWithRandomProp = { ...edge, label, randomProp: true }; + render( + , + ); + + expect(renderElement).toHaveBeenCalledWith({ edge: edgeWithRandomProp }); + }); + + it('calls setEdge with edge ID and actual label size after rendering', () => { + const { getByText } = render(); + expect(getByText(label)).toBeInTheDocument(); + + // Updates the edge in the graph + expect(setEdge).toHaveBeenCalledWith(id, { + height: 100, + width: 100, + ...edgeWithLabel, + }); + + // Does not pass down width/height to label + expect(renderElement).not.toHaveBeenCalledWith( + expect.objectContaining({ height: 100, width: 100 }), + ); + }); +}); diff --git a/packages/core/src/components/DependencyGraph/Edge.tsx b/packages/core/src/components/DependencyGraph/Edge.tsx new file mode 100644 index 0000000000..5e67aca63f --- /dev/null +++ b/packages/core/src/components/DependencyGraph/Edge.tsx @@ -0,0 +1,122 @@ +/* + * 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. + */ + +import React from 'react'; +import * as d3Shape from 'd3-shape'; +import isFinite from 'lodash/isFinite'; +import makeStyles from '@material-ui/core/styles/makeStyles'; +import { BackstageTheme } from '@backstage/theme'; +import { + GraphEdge, + RenderLabelProps, + RenderLabelFunction, + DependencyEdge, +} from './types'; +import { ARROW_MARKER_ID, EDGE_TEST_ID, LABEL_TEST_ID } from './constants'; +import { DefaultLabel } from './DefaultLabel'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + path: { + strokeWidth: 2, + stroke: theme.palette.textSubtle, + fill: 'none', + transition: `${theme.transitions.duration.shortest}ms`, + }, + label: { + transition: `${theme.transitions.duration.shortest}ms`, + }, +})); + +type EdgePoint = dagre.GraphEdge['points'][0]; + +export type EdgeComponentProps = { + id: dagre.Edge; + edge: GraphEdge; + render?: RenderLabelFunction; + setEdge: (id: dagre.Edge, edge: DependencyEdge) => dagre.graphlib.Graph<{}>; +}; + +const renderDefault = (props: RenderLabelProps) => ; + +const createPath = d3Shape + .line() + .x(d => d.x) + .y(d => d.y) + .curve(d3Shape.curveMonotoneX); + +export function Edge({ + render = renderDefault, + setEdge, + id, + edge, +}: EdgeComponentProps) { + const { x = 0, y = 0, width, height, points, ...labelProps } = edge; + const classes = useStyles(); + + const labelRef = React.useRef(null); + + React.useLayoutEffect(() => { + // set the label width to the actual rendered width to properly layout graph + if (labelRef.current) { + let { + height: renderedHeight, + width: renderedWidth, + } = labelRef.current.getBBox(); + renderedHeight = Math.round(renderedHeight); + renderedWidth = Math.round(renderedWidth); + + if (renderedHeight !== height || renderedWidth !== width) { + setEdge(id, { + ...edge, + height: renderedHeight, + width: renderedWidth, + }); + } + } + }, [edge, height, width, setEdge, id]); + + let path: string = ''; + + if (points) { + const finitePoints = points.filter( + (point: EdgePoint) => isFinite(point.x) && isFinite(point.y), + ); + path = createPath(finitePoints) || ''; + } + + return ( + <> + {path && ( + + )} + {labelProps.label ? ( + + {render({ edge: labelProps })} + + ) : null} + + ); +} diff --git a/packages/core/src/components/DependencyGraph/Node.test.tsx b/packages/core/src/components/DependencyGraph/Node.test.tsx new file mode 100644 index 0000000000..9f9f7c693a --- /dev/null +++ b/packages/core/src/components/DependencyGraph/Node.test.tsx @@ -0,0 +1,79 @@ +/* + * 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. + */ + +import React from 'react'; +import dagre from 'dagre'; +import { render } from '@testing-library/react'; +import { Node } from './Node'; +import { RenderNodeProps } from './types'; + +const node = { id: 'abc' }; +const setNode = jest.fn(() => new dagre.graphlib.Graph()); +const renderElement = jest.fn((props: RenderNodeProps) => ( + {props.node.id} +)); + +const minProps = { + id: node.id, + node, + setNode, + render: renderElement, + x: 0, + y: 0, + width: 0, + height: 0, +}; + +describe('', () => { + beforeEach(() => { + // jsdom does not support SVG elements so we have to fall back to HTMLUnknownElement + Object.defineProperty(window.HTMLUnknownElement.prototype, 'getBBox', { + value: () => ({ width: 100, height: 100 }), + configurable: true, + }); + }); + + afterEach(jest.clearAllMocks); + + it('renders the supplied element', () => { + const { getByText } = render(); + expect(getByText(minProps.id)).toBeInTheDocument(); + }); + + it('passes down node properties to the render method', () => { + const nodeWithRandomProp = { ...node, randomProp: true }; + render(); + + expect(renderElement).toHaveBeenCalledWith({ node: nodeWithRandomProp }); + }); + + it('calls setNode with node ID and actual size after rendering', () => { + const { getByText } = render(); + expect(getByText(minProps.id)).toBeInTheDocument(); + + // Updates the node in the graph + expect(setNode).toHaveBeenCalledWith(node.id, { + height: 100, + width: 100, + ...node, + }); + + // Does not pass down width/height to node + expect(renderElement).not.toHaveBeenCalledWith( + expect.objectContaining({ height: 100, width: 100 }), + ); + }); +}); diff --git a/packages/core/src/components/DependencyGraph/Node.tsx b/packages/core/src/components/DependencyGraph/Node.tsx new file mode 100644 index 0000000000..4d64e31335 --- /dev/null +++ b/packages/core/src/components/DependencyGraph/Node.tsx @@ -0,0 +1,76 @@ +/* + * 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. + */ + +import React from 'react'; +import makeStyles from '@material-ui/core/styles/makeStyles'; +import { DefaultNode } from './DefaultNode'; +import { RenderNodeFunction, RenderNodeProps, GraphNode } from './types'; +import { NODE_TEST_ID } from './constants'; + +const useStyles = makeStyles(theme => ({ + node: { + transition: `${theme.transitions.duration.shortest}ms`, + }, +})); + +export type NodeComponentProps = { + node: GraphNode; + render?: RenderNodeFunction; + setNode: dagre.graphlib.Graph['setNode']; +}; + +const renderDefault = (props: RenderNodeProps) => ; + +export function Node({ + render = renderDefault, + setNode, + node, +}: NodeComponentProps) { + const { width, height, x = 0, y = 0, ...nodeProps } = node; + const classes = useStyles(); + const nodeRef = React.useRef(null); + + React.useLayoutEffect(() => { + // set the node width to the actual rendered width to properly layout graph + if (nodeRef.current) { + let { + height: renderedHeight, + width: renderedWidth, + } = nodeRef.current.getBBox(); + renderedHeight = Math.round(renderedHeight); + renderedWidth = Math.round(renderedWidth); + + if (renderedHeight !== height || renderedWidth !== width) { + setNode(node.id, { + ...node, + height: renderedHeight, + width: renderedWidth, + }); + } + } + }, [node, width, height, setNode]); + + return ( + + {render({ node: nodeProps })} + + ); +} diff --git a/packages/core/src/components/DependencyGraph/constants.ts b/packages/core/src/components/DependencyGraph/constants.ts new file mode 100644 index 0000000000..412a677f87 --- /dev/null +++ b/packages/core/src/components/DependencyGraph/constants.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +export const ARROW_MARKER_ID = 'arrow-marker'; + +export const NODE_TEST_ID = 'node'; +export const EDGE_TEST_ID = 'edge'; +export const LABEL_TEST_ID = 'label'; diff --git a/packages/core/src/components/DependencyGraph/index.ts b/packages/core/src/components/DependencyGraph/index.ts new file mode 100644 index 0000000000..9a4f0071e3 --- /dev/null +++ b/packages/core/src/components/DependencyGraph/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +import * as DependencyGraphTypes from './types'; + +export { DependencyGraph } from './DependencyGraph'; +export { DependencyGraphTypes }; diff --git a/packages/core/src/components/DependencyGraph/types.ts b/packages/core/src/components/DependencyGraph/types.ts new file mode 100644 index 0000000000..19173db4b3 --- /dev/null +++ b/packages/core/src/components/DependencyGraph/types.ts @@ -0,0 +1,88 @@ +/* + * 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. + */ + +import dagre from 'dagre'; + +type CustomType = { [customKey: string]: any }; + +/* Edges */ +export type DependencyEdge = T & { + from: string; + to: string; + label?: string; +}; + +export type GraphEdge = DependencyEdge & + dagre.GraphEdge & + EdgeProperties; + +export type RenderLabelProps = { edge: DependencyEdge }; + +export type RenderLabelFunction = ( + props: RenderLabelProps, +) => React.ReactNode; + +/* Nodes */ +export type DependencyNode = T & { + id: string; +}; + +export type GraphNode = dagre.Node>; + +export type RenderNodeProps = { node: DependencyNode }; + +export type RenderNodeFunction = ( + props: RenderNodeProps, +) => React.ReactNode; + +/* Based on: https://github.com/dagrejs/dagre/wiki#configuring-the-layout */ + +export type EdgeProperties = { + label?: string; + width?: number; + height?: number; + labeloffset?: number; + labelpos?: LabelPosition; + minlen?: number; + weight?: number; + [customKey: string]: any; +}; + +export enum Direction { + TOP_BOTTOM = 'TB', + BOTTOM_TOP = 'BT', + LEFT_RIGHT = 'LR', + RIGHT_LEFT = 'RL', +} + +export enum Alignment { + UP_LEFT = 'UL', + UP_RIGHT = 'UR', + DOWN_LEFT = 'DL', + DOWN_RIGHT = 'DR', +} + +export enum Ranker { + NETWORK_SIMPLEX = 'network-simplex', + TIGHT_TREE = 'tight-tree', + LONGEST_PATH = 'longest-path', +} + +export enum LabelPosition { + LEFT = 'l', + RIGHT = 'r', + CENTER = 'c', +} diff --git a/packages/core/src/components/Link/Link.tsx b/packages/core/src/components/Link/Link.tsx index 8e7e3f179e..59a9604fa7 100644 --- a/packages/core/src/components/Link/Link.tsx +++ b/packages/core/src/components/Link/Link.tsx @@ -25,6 +25,13 @@ type Props = ComponentProps & * Thin wrapper on top of material-ui's Link component * Makes the Link to utilise react-router */ -export const Link = React.forwardRef((props, ref) => ( - -)); +export const Link = React.forwardRef((props, ref) => { + const to = String(props.to); + return /^https?:\/\//.test(to) ? ( + // External links + + ) : ( + // Interact with React Router for internal links + + ); +}); diff --git a/packages/core/src/components/MarkdownContent/MarkdownContent.stories.tsx b/packages/core/src/components/MarkdownContent/MarkdownContent.stories.tsx new file mode 100644 index 0000000000..eb15aa92d3 --- /dev/null +++ b/packages/core/src/components/MarkdownContent/MarkdownContent.stories.tsx @@ -0,0 +1,120 @@ +/* + * 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. + */ + +import React from 'react'; +import { MarkdownContent } from './MarkdownContent'; + +export default { + title: 'Data Display/MarkdownContent', + component: MarkdownContent, +}; + +const markdownGithubFlavored = + '# GFM\n' + + '\n' + + '## Autolink literals\n' + + '\n' + + 'www.example.com, https://example.com, and contact@example.com.\n' + + '\n' + + '## Strikethrough\n' + + '\n' + + '~one~ or ~~two~~ tildes.\n' + + '\n' + + '## Table\n' + + '\n' + + '| foo | bar |\n' + + '| --- | --- |\n' + + '| baz | bim |\n' + + '| buz | bum |\n' + + '| biz | bim |\n' + + '\n' + + '## Tasklist\n' + + '\n' + + '* [ ] to do\n' + + '* [x] done'; + +const markdown = + '# Choreas Iovis\n' + + '\n' + + '## Incedere retenta\n' + + '\n' + + 'Lorem markdownum velamina [nupta amici aequoreis](http://est-quae.org/sic)\n' + + 'desertum factum premunt: falcato parvos nihil. Facietque vulnus tum dumque\n' + + 'reserato Maeandros insignia solidis, tot longi causa et nimium arcuerat altera\n' + + 'unus, in quis.\n' + + '\n' + + '1. Est qui dixere nullus\n' + + '2. Fuit obicit\n' + + '3. Vim patrem portae materiem ulla quod crater\n' + + '4. Rigido est magis raptor quid crepitante aequa\n' + + '5. Imago quis ignis tamen\n' + + '\n' + + '## Vix posse vestem\n' + + '\n' + + 'Nec deos robora visa pater toris remittit *crimina* utque, ora ego lacerae quae\n' + + 'laboris laturus silvas audax terrae. Qua fuisse patrio inlaesas [sine\n' + + 'seque](http://ambitvictore.org/), nondum et tamen annis, nec. Poscimur magnum,\n' + + 'Hesperium dedisti, ait ipse et fides terras scalas.\n' + + '\n' + + '- Quas superis satyri adloquitur natura hausimus\n' + + '- Dux suspicere siccare\n' + + '- Cape huc quid videor\n' + + '- Foret vivit concolor\n' + + '- Occupat morte oblectamina minuunt quaeque placidis nate\n' + + '- Non posset' + + '\n' + + 'Licet movitque dederat potest in sorores in sola pendere luce pro quod, sit.\n' + + 'Inpia ut in opibus flores uno quam quo multifidasque fera anhelitus retorsit.\n' + + 'Sustinui premebat puppe somnos. Dicit genu sic qualia excussit facunde parvae in\n' + + 'robur, Ianthe Interea. Superis victorque ponat puta cum: est enim.\n' + + '\n' + + '## Tacetve est in nullis Cerberus silvani luminibus\n' + + '\n' + + 'Divulsere *summissoque esse manes*; artus ausus conatoque utque: illo\n' + + 'Phaestiadas quod pascat et referentem, nec. In seris, iubebat iam nomina:\n' + + 'tergoque occidit ingenii.\n' + + '\n' + + ' mouseDdl(tablet_definition * phishing_icann_mamp);\n' + + ' vector += 20 + key_ram.source_isa(hard_tunneling_zone(w_wireless_page));\n' + + ' if (rate_client_direct) {\n' + + ' textXDpi += sql_cloud_class.sdk.speakers_wired_warm(pcZettabyteGis(\n' + + ' market_bezel, 1), 1);\n' + + ' tag_scraping = format_ppi;\n' + + ' }\n' + + '\n' + + 'Per quem, nec formosior qui cum Peliden me interea **ornatos**! Te facit\n' + + 'instimulat sequentia in flumina exilium te vulnere, sola. Coetum nec amnes.\n' + + 'Protinus nam Caras cava, *a* vocantem dicta inevitabile, nata nulla.\n' + + '\n' + + '## Piscem Iunoni maius\n' + + '\n' + + 'Prece fallere arduus, *ad Athamantis laticem* simillima in ante Temesesque opus!\n' + + 'Ausim quoslibet crede Tyria: Medusa [muneris Aeneaden\n' + + 'tutaque](http://cragon-aequoribus.io/) genitor fistula cogeris abstrahere nati,\n' + + 'relevare videri *non*.\n' + + '\n' + + '> Promissas ulterius senectae Desinet his ait pedum! Libet *sublime* vibrantia\n' + + '> si *dicta quod* pectora cupidine hastam dominoque.\n' + + '\n' + + 'Pedis hic, est bis quod, adhaeret et reditum. Fixa sic vel pugnare **forte est**\n' + + 'parte in quaerite generisque repugnat; de quod, creatos.'; +export const MarkdownContentCommonMark = () => ( + +); + +export const MarkdownContentGithubFlavoredCommonMark = () => ( + +); diff --git a/packages/core/src/components/MarkdownContent/MarkdownContent.test.tsx b/packages/core/src/components/MarkdownContent/MarkdownContent.test.tsx new file mode 100644 index 0000000000..dcbe421dcb --- /dev/null +++ b/packages/core/src/components/MarkdownContent/MarkdownContent.test.tsx @@ -0,0 +1,65 @@ +/* + * 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. + */ + +import React from 'react'; +import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { MarkdownContent } from './MarkdownContent'; + +describe('', () => { + it('render MarkdownContent component', async () => { + const rendered = await renderWithEffects( + wrapInTestApp( + , + ), + ); + expect(rendered.getByText('H1', { selector: 'h1' })).toBeInTheDocument(); + expect(rendered.getByText('H2', { selector: 'h2' })).toBeInTheDocument(); + expect(rendered.getByText('H3', { selector: 'h3' })).toBeInTheDocument(); + }); + + it('render MarkdownContent component with GitHub flavored Markdown dialect', async () => { + const rendered = await renderWithEffects( + wrapInTestApp(), + ); + expect( + rendered.getByText('https://example.com', { selector: 'a' }), + ).toBeInTheDocument(); + }); + + it('Render MarkdownContent component with common mark dialect', async () => { + const rendered = await renderWithEffects( + wrapInTestApp( + , + ), + ); + expect( + rendered.getByText('https://example.com', { selector: 'p' }), + ).toBeInTheDocument(); + }); + + it('render MarkdownContent component with CodeSnippet for code blocks', async () => { + const rendered = await renderWithEffects( + wrapInTestApp(), + ); + const fp1 = rendered.getByText('jest', { selector: 'span' }); + expect(fp1).toBeInTheDocument(); + expect(fp1.className).toEqual('hljs-function'); + const fp2 = rendered.getByText('(test: string)', { selector: 'span' }); + expect(fp2).toBeInTheDocument(); + expect(fp2.className).toEqual('hljs-function'); + expect(rendered.getByText(';', { selector: 'span' })).toBeInTheDocument(); + }); +}); diff --git a/packages/core/src/components/MarkdownContent/MarkdownContent.tsx b/packages/core/src/components/MarkdownContent/MarkdownContent.tsx new file mode 100644 index 0000000000..0000e54a5f --- /dev/null +++ b/packages/core/src/components/MarkdownContent/MarkdownContent.tsx @@ -0,0 +1,89 @@ +/* + * 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. + */ + +import { makeStyles } from '@material-ui/core'; +import ReactMarkdown from 'react-markdown'; +import gfm from 'remark-gfm'; +import React from 'react'; +import { BackstageTheme } from '@backstage/theme'; +import { CodeSnippet } from '../CodeSnippet'; + +const useStyles = makeStyles(theme => ({ + markdown: { + '& table': { + borderCollapse: 'collapse', + border: `1px solid ${theme.palette.border}`, + }, + '& th, & td': { + border: `1px solid ${theme.palette.border}`, + padding: theme.spacing(1), + }, + '& td': { + wordBreak: 'break-word', + overflow: 'hidden', + verticalAlign: 'middle', + lineHeight: '1', + margin: 0, + padding: theme.spacing(3, 2, 3, 2.5), + borderBottom: 0, + }, + '& th': { + backgroundColor: theme.palette.background.paper, + }, + '& tr': { + backgroundColor: theme.palette.background.paper, + }, + '& tr:nth-child(odd)': { + backgroundColor: theme.palette.background.default, + }, + + '& a': { + color: theme.palette.link, + }, + '& img': { + maxWidth: '100%', + }, + }, +})); + +type Props = { + content: string; + dialect?: 'gfm' | 'common-mark'; +}; + +const renderers = { + code: ({ language, value }: { language: string; value: string }) => { + return ; + }, +}; + +/** + * MarkdownContent + * -- + * Renders markdown with the default dialect [gfm - GitHub flavored Markdown](https://github.github.com/gfm/) to backstage theme styled HTML. + * If you just want to render to plain [CommonMark](https://commonmark.org/), set the dialect to `'common-mark'` + */ +export const MarkdownContent = ({ content, dialect = 'gfm' }: Props) => { + const classes = useStyles(); + return ( + + ); +}; diff --git a/packages/core/src/components/MarkdownContent/index.ts b/packages/core/src/components/MarkdownContent/index.ts new file mode 100644 index 0000000000..7267ff191c --- /dev/null +++ b/packages/core/src/components/MarkdownContent/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export { MarkdownContent } from './MarkdownContent'; diff --git a/packages/core/src/components/index.ts b/packages/core/src/components/index.ts index 4f085ffd6a..bcc56debea 100644 --- a/packages/core/src/components/index.ts +++ b/packages/core/src/components/index.ts @@ -18,6 +18,7 @@ export * from './AlertDisplay'; export * from './Button'; export * from './CodeSnippet'; export * from './CopyTextButton'; +export * from './DependencyGraph'; export * from './DismissableBanner'; export * from './FeatureDiscovery'; export * from './HorizontalScrollGrid'; @@ -35,3 +36,4 @@ export * from './Tabs'; export * from './TrendLine'; export * from './WarningPanel'; export * from './EmptyState'; +export * from './MarkdownContent'; diff --git a/packages/core/src/layout/BottomLink/BottomLink.test.tsx b/packages/core/src/layout/BottomLink/BottomLink.test.tsx index 92ae2ecb3b..8bea00e35d 100644 --- a/packages/core/src/layout/BottomLink/BottomLink.test.tsx +++ b/packages/core/src/layout/BottomLink/BottomLink.test.tsx @@ -22,7 +22,6 @@ const minProps = { title: 'A deepLink title', link: '/mocked', }; - describe('', () => { it('renders without exploding', async () => { const rendered = await renderInTestApp(); diff --git a/packages/core/src/layout/BottomLink/BottomLink.tsx b/packages/core/src/layout/BottomLink/BottomLink.tsx index b3f7b4aa11..e768ffd9e4 100644 --- a/packages/core/src/layout/BottomLink/BottomLink.tsx +++ b/packages/core/src/layout/BottomLink/BottomLink.tsx @@ -16,7 +16,6 @@ import React, { FC } from 'react'; import { - Link, ListItem, ListItemIcon, Divider, @@ -26,6 +25,7 @@ import { import ArrowIcon from '@material-ui/icons/ArrowForward'; import { BackstageTheme } from '@backstage/theme'; import Box from '@material-ui/core/Box'; +import { Link } from '../../components/Link'; const useStyles = makeStyles(theme => ({ root: { @@ -53,7 +53,7 @@ export const BottomLink: FC = ({ link, title, onClick }) => { return (
- + diff --git a/packages/core/src/layout/ErrorPage/ErrorPage.tsx b/packages/core/src/layout/ErrorPage/ErrorPage.tsx index b41308dd6d..776ed41614 100644 --- a/packages/core/src/layout/ErrorPage/ErrorPage.tsx +++ b/packages/core/src/layout/ErrorPage/ErrorPage.tsx @@ -73,7 +73,7 @@ export const ErrorPage = ({ ... or if you think this is a bug, please file an{' '} issue. diff --git a/packages/core/src/layout/HeaderTabs/HeaderTabs.tsx b/packages/core/src/layout/HeaderTabs/HeaderTabs.tsx new file mode 100644 index 0000000000..b509cae14f --- /dev/null +++ b/packages/core/src/layout/HeaderTabs/HeaderTabs.tsx @@ -0,0 +1,90 @@ +/* + * 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. + */ + +// TODO(blam): Remove this implementation when the Tabs are ready +// This is just a temporary solution to implementing tabs for now + +import React, { useState, useEffect } from 'react'; +import { makeStyles, Tabs, Tab } from '@material-ui/core'; + +const useStyles = makeStyles(theme => ({ + tabsWrapper: { + gridArea: 'pageSubheader', + backgroundColor: theme.palette.background.paper, + paddingLeft: theme.spacing(3), + }, + defaultTab: { + padding: theme.spacing(3, 3), + ...theme.typography.caption, + textTransform: 'uppercase', + fontWeight: 'bold', + color: theme.palette.text.secondary, + }, + selected: { + color: theme.palette.text.primary, + }, +})); + +export type Tab = { + id: string; + label: string; +}; + +export const HeaderTabs: React.FC<{ + tabs: Tab[]; + onChange?: (index: number) => void; + selectedIndex?: number; +}> = ({ tabs, onChange, selectedIndex }) => { + const [selectedTab, setSelectedTab] = useState(selectedIndex ?? 0); + const styles = useStyles(); + + const handleChange = (_: React.ChangeEvent<{}>, index: number) => { + if (selectedIndex === undefined) { + setSelectedTab(index); + } + if (onChange) onChange(index); + }; + + useEffect(() => { + if (selectedIndex !== undefined) { + setSelectedTab(selectedIndex); + } + }, [selectedIndex]); + + return ( +
+ + {tabs.map((tab, index) => ( + + ))} + +
+ ); +}; diff --git a/packages/core/src/layout/HeaderTabs/index.tsx b/packages/core/src/layout/HeaderTabs/index.tsx index b509cae14f..1097698265 100644 --- a/packages/core/src/layout/HeaderTabs/index.tsx +++ b/packages/core/src/layout/HeaderTabs/index.tsx @@ -14,77 +14,5 @@ * limitations under the License. */ -// TODO(blam): Remove this implementation when the Tabs are ready -// This is just a temporary solution to implementing tabs for now - -import React, { useState, useEffect } from 'react'; -import { makeStyles, Tabs, Tab } from '@material-ui/core'; - -const useStyles = makeStyles(theme => ({ - tabsWrapper: { - gridArea: 'pageSubheader', - backgroundColor: theme.palette.background.paper, - paddingLeft: theme.spacing(3), - }, - defaultTab: { - padding: theme.spacing(3, 3), - ...theme.typography.caption, - textTransform: 'uppercase', - fontWeight: 'bold', - color: theme.palette.text.secondary, - }, - selected: { - color: theme.palette.text.primary, - }, -})); - -export type Tab = { - id: string; - label: string; -}; - -export const HeaderTabs: React.FC<{ - tabs: Tab[]; - onChange?: (index: number) => void; - selectedIndex?: number; -}> = ({ tabs, onChange, selectedIndex }) => { - const [selectedTab, setSelectedTab] = useState(selectedIndex ?? 0); - const styles = useStyles(); - - const handleChange = (_: React.ChangeEvent<{}>, index: number) => { - if (selectedIndex === undefined) { - setSelectedTab(index); - } - if (onChange) onChange(index); - }; - - useEffect(() => { - if (selectedIndex !== undefined) { - setSelectedTab(selectedIndex); - } - }, [selectedIndex]); - - return ( -
- - {tabs.map((tab, index) => ( - - ))} - -
- ); -}; +export type { Tab } from './HeaderTabs'; +export { HeaderTabs } from './HeaderTabs'; diff --git a/packages/core/src/layout/InfoCard/InfoCard.tsx b/packages/core/src/layout/InfoCard/InfoCard.tsx index d13a94375f..5d77f4f34a 100644 --- a/packages/core/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core/src/layout/InfoCard/InfoCard.tsx @@ -143,7 +143,7 @@ type Props = { export const InfoCard = ({ title, subheader, - divider, + divider = true, deepLink, slackChannel = '#backstage', variant, @@ -190,23 +190,20 @@ export const InfoCard = ({ {title && ( - <> - - - + )} {actionsTopRight && ( {actionsTopRight} diff --git a/packages/core/src/layout/Page/Page.stories.tsx b/packages/core/src/layout/Page/Page.stories.tsx index 3b1dd07c7a..1d3aaea412 100644 --- a/packages/core/src/layout/Page/Page.stories.tsx +++ b/packages/core/src/layout/Page/Page.stories.tsx @@ -185,7 +185,7 @@ const ExampleContentHeader = ({ selectedTab }: { selectedTab?: number }) => ( title={selectedTab !== undefined ? tabs[selectedTab].label : 'Header'} > - This Plugin is an example. This text could provide usefull information for + This Plugin is an example. This text could provide useful information for the user. diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md new file mode 100644 index 0000000000..fa0d8f817b --- /dev/null +++ b/packages/create-app/CHANGELOG.md @@ -0,0 +1,132 @@ +# @backstage/create-app + +## 0.2.0 + +### Minor Changes + +- 6d29605db: Change the default backend plugin mount point to /api +- 5249594c5: Add service discovery interface and implement for single host deployments + + Fixes #1847, #2596 + + Went with an interface similar to the frontend DiscoveryApi, since it's dead simple but still provides a lot of flexibility in the implementation. + + Also ended up with two different methods, one for internal endpoint discovery and one for external. The two use-cases are explained a bit more in the docs, but basically it's service-to-service vs callback URLs. + + This did get me thinking about uniqueness and that we're heading towards a global namespace for backend plugin IDs. That's probably fine, but if we're happy with that we should leverage it a bit more to simplify the backend setup. For example we'd have each plugin provide its own ID and not manually mount on paths in the backend. + + Draft until we're happy with the implementation, then I can add more docs and changelog entry. Also didn't go on a thorough hunt for places where discovery can be used, but I don't think there are many since it's been pretty awkward to do service-to-service communication. + +- 56e4eb589: Make CSP configurable to fix app-backend served app not being able to fetch + + See discussion [here on discord](https://discordapp.com/channels/687207715902193673/687235481154617364/758721460163575850) + +- d7873e1aa: Default to using internal scope for new plugins +- 6f447b3fc: Remove identity-backend + + Not used, and we're heading down the route of identities in the catalog + +- 61db1ddc6: Allow node v14 and add to master build matrix + + - Upgrade sqlite3@^5.0.0 in @backstage/plugin-catalog-backend + - Add Node 14 to engines in @backstage/create-app + +- a768a07fb: Add the ability to import users from GitHub Organization into the catalog. + + The token needs to have the scopes `user:email`, `read:user`, and `read:org`. + +- f00ca3cb8: Auto-create plugin databases + + Relates to #1598. + + This creates databases for plugins before handing off control to plugins. + + The list of plugins currently need to be hard-coded depending on the installed plugins. A later PR will properly refactor the code to provide a factory pattern where plugins specify what they need, and Knex instances will be provided based on the input. + +- 6d97d2d6f: The InfoCard variant `'height100'` is deprecated. Use variant `'gridItem'` instead. + + When the InfoCard is displayed as a grid item within a grid, you may want items to have the same height for all items. + Set to the `'gridItem'` variant to display the InfoCard with full height suitable for Grid: + `...` + + Changed the InfoCards in '@backstage/plugin-github-actions', '@backstage/plugin-jenkins', '@backstage/plugin-lighthouse' + to pass an optional variant to the corresponding card of the plugin. + + As a result the overview content of the EntityPage shows cards with full height suitable for Grid. + +- 7aff112af: The default mount point for backend plugins have been changed to /api. These changes are done in the backend package itself, so it is recommended that you sync up existing backend packages with this new pattern. + +### Patch Changes + +- e67d49bf5: Sync scaffolded backend with example +- 961414d55: Remove discovery api override +- 440a17b39: Bump @backstage/catalog-backend and pass the now required UrlReader interface to the plugin +- 8c2b76e45: **BREAKING CHANGE** + + The existing loading of additional config files like `app-config.development.yaml` using APP_ENV or NODE_ENV has been removed. + Instead, the CLI and backend process now accept one or more `--config` flags to load config files. + + Without passing any flags, `app-config.yaml` and, if it exists, `app-config.local.yaml` will be loaded. + If passing any `--config ` flags, only those files will be loaded, **NOT** the default `app-config.yaml` one. + + The old behaviour of for example `APP_ENV=development` can be replicated using the following flags: + + ```bash + --config ../../app-config.yaml --config ../../app-config.development.yaml + ``` + +- 5a920c6e4: Updated naming of environment variables. New pattern [NAME]\_TOKEN for Github, Gitlab, Azure & Github enterprise access tokens. + + ### Detail: + + - Previously we have to export same token for both, catalog & scaffolder + + ```bash + export GITHUB_ACCESS_TOKEN=foo + export GITHUB_PRIVATE_TOKEN=foo + ``` + + with latest changes, only single export is sufficient. + + ```bash + export GITHUB_TOKEN=foo + export GITLAB_TOKEN=foo + export GHE_TOKEN=foo + export AZURE_TOKEN=foo + ``` + + ### list: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Old nameNew name
GITHUB_ACCESS_TOKENGITHUB_TOKEN
GITHUB_PRIVATE_TOKENGITHUB_TOKEN
GITLAB_ACCESS_TOKENGITLAB_TOKEN
GITLAB_PRIVATE_TOKENGITLAB_TOKEN
AZURE_PRIVATE_TOKENAZURE_TOKEN
GHE_PRIVATE_TOKENGHE_TOKEN
+ +- 67d76b419: Fix for configured templates using 'url' locations even though it's not supported yet +- 7bbeb049f: Change loadBackendConfig to return the config directly diff --git a/packages/create-app/README.md b/packages/create-app/README.md index b5f231a326..7533110372 100644 --- a/packages/create-app/README.md +++ b/packages/create-app/README.md @@ -13,5 +13,5 @@ $ npx @backstage/create-app ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/create-app/package.json b/packages/create-app/package.json index bb321dc504..2653185c32 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.1.1-alpha.26", + "version": "0.2.0", "private": false, "publishConfig": { "access": "public" @@ -9,7 +9,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/create-app" }, "keywords": [ @@ -27,7 +27,7 @@ "start": "nodemon --" }, "dependencies": { - "@backstage/cli-common": "^0.1.1-alpha.26", + "@backstage/cli-common": "^0.1.1", "chalk": "^4.0.0", "commander": "^6.1.0", "fs-extra": "^9.0.0", @@ -37,30 +37,30 @@ "recursive-readdir": "^2.2.2" }, "devDependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-api-docs": "^0.1.1-alpha.26", - "@backstage/plugin-auth-backend": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/plugin-catalog-backend": "^0.1.1-alpha.26", - "@backstage/plugin-circleci": "^0.1.1-alpha.26", - "@backstage/plugin-explore": "^0.1.1-alpha.26", - "@backstage/plugin-github-actions": "^0.1.1-alpha.26", - "@backstage/plugin-lighthouse": "^0.1.1-alpha.26", - "@backstage/plugin-proxy-backend": "^0.1.1-alpha.26", - "@backstage/plugin-register-component": "^0.1.1-alpha.26", - "@backstage/plugin-rollbar-backend": "^0.1.1-alpha.26", - "@backstage/plugin-scaffolder": "^0.1.1-alpha.26", - "@backstage/plugin-scaffolder-backend": "^0.1.1-alpha.26", - "@backstage/plugin-tech-radar": "^0.1.1-alpha.26", - "@backstage/plugin-techdocs": "^0.1.1-alpha.26", - "@backstage/plugin-techdocs-backend": "^0.1.1-alpha.26", - "@backstage/plugin-user-settings": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/catalog-model": "^0.2.0", + "@backstage/cli": "^0.2.0", + "@backstage/config": "^0.1.1", + "@backstage/core": "^0.2.0", + "@backstage/plugin-api-docs": "^0.2.0", + "@backstage/plugin-auth-backend": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/plugin-catalog-backend": "^0.2.0", + "@backstage/plugin-circleci": "^0.2.0", + "@backstage/plugin-explore": "^0.2.0", + "@backstage/plugin-github-actions": "^0.2.0", + "@backstage/plugin-lighthouse": "^0.2.0", + "@backstage/plugin-proxy-backend": "^0.2.0", + "@backstage/plugin-register-component": "^0.2.0", + "@backstage/plugin-rollbar-backend": "^0.1.2", + "@backstage/plugin-scaffolder": "^0.2.0", + "@backstage/plugin-scaffolder-backend": "^0.2.0", + "@backstage/plugin-tech-radar": "^0.2.0", + "@backstage/plugin-techdocs": "^0.2.0", + "@backstage/plugin-techdocs-backend": "^0.2.0", + "@backstage/plugin-user-settings": "^0.2.0", + "@backstage/test-utils": "^0.1.2", + "@backstage/theme": "^0.2.0", "@types/fs-extra": "^9.0.1", "@types/inquirer": "^7.3.1", "@types/ora": "^3.2.0", diff --git a/packages/create-app/templates/default-app/app-config.yaml.hbs b/packages/create-app/templates/default-app/app-config.yaml.hbs index 3c7bc40c2b..595812dec3 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -81,23 +81,23 @@ catalog: locations: # Backstage example components - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/all-components.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-components.yaml # Backstage example APIs - type: url - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/all-apis.yaml + target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-apis.yaml # Backstage example templates - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml rules: - allow: [Template] - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml rules: - allow: [Template] - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml rules: - allow: [Template] - type: github @@ -105,6 +105,6 @@ catalog: rules: - allow: [Template] - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml + target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml rules: - allow: [Template] diff --git a/packages/create-app/templates/default-app/catalog-info.yaml.hbs b/packages/create-app/templates/default-app/catalog-info.yaml.hbs index a370902020..0f8e4f5aeb 100644 --- a/packages/create-app/templates/default-app/catalog-info.yaml.hbs +++ b/packages/create-app/templates/default-app/catalog-info.yaml.hbs @@ -1,13 +1,13 @@ -apiVersion: backstage.io/v1alpha1 +apiVersion: backstage.io/v1alpha1 kind: Component metadata: - name: {{name}} + name: {{name}} description: An example of a Backstage application. # Example for optional annotations - # annotations: - # github.com/project-slug: spotify/backstage - # backstage.io/techdocs-ref: github:https://github.com/spotify/backstage.git + # annotations: + # github.com/project-slug: backstage/backstage + # backstage.io/techdocs-ref: github:https://github.com/backstage/backstage.git spec: type: website owner: john@example.com - lifecycle: experimental \ No newline at end of file + lifecycle: experimental diff --git a/packages/create-app/templates/default-app/packages/app/src/plugins.ts b/packages/create-app/templates/default-app/packages/app/src/plugins.ts index c787ac2166..b719594a0b 100644 --- a/packages/create-app/templates/default-app/packages/app/src/plugins.ts +++ b/packages/create-app/templates/default-app/packages/app/src/plugins.ts @@ -1,3 +1,4 @@ +export { plugin as ApiDocs } from '@backstage/plugin-api-docs'; export { plugin as CatalogPlugin } from '@backstage/plugin-catalog'; export { plugin as RegisterComponent } from '@backstage/plugin-register-component'; export { plugin as ScaffolderPlugin } from '@backstage/plugin-scaffolder'; diff --git a/packages/create-app/templates/default-app/packages/backend/README.md b/packages/create-app/templates/default-app/packages/backend/README.md index 5583bff625..81e0f80535 100644 --- a/packages/create-app/templates/default-app/packages/backend/README.md +++ b/packages/create-app/templates/default-app/packages/backend/README.md @@ -56,11 +56,11 @@ to its comprehensive set of supported authentication [strategies](http://www.passportjs.org/packages/). Read more about the -[auth-backend](https://github.com/spotify/backstage/blob/master/plugins/auth-backend/README.md) +[auth-backend](https://github.com/backstage/backstage/blob/master/plugins/auth-backend/README.md) and -[how to add a new provider](https://github.com/spotify/backstage/blob/master/docs/auth/add-auth-provider.md) +[how to add a new provider](https://github.com/backstage/backstage/blob/master/docs/auth/add-auth-provider.md) ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) 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 bf887dc014..df9ac28739 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,7 +27,7 @@ "@backstage/plugin-scaffolder-backend": "^{{version '@backstage/plugin-scaffolder-backend'}}", "@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}", "@octokit/rest": "^18.0.0", - "@gitbeaker/node": "^23.5.0", + "@gitbeaker/node": "^25.2.0", "dockerode": "^3.2.0", "express": "^4.17.1", "express-promise-router": "^3.0.3", diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts index 8de15920e9..2dc69feb45 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts @@ -11,7 +11,9 @@ import { CreateReactAppTemplater, Templaters, RepoVisibilityOptions, + CatalogEntityClient, } from '@backstage/plugin-scaffolder-backend'; +import { SingleHostDiscovery } from '@backstage/backend-common'; import { Octokit } from '@octokit/rest'; import { Gitlab } from '@gitbeaker/node'; import type { PluginEnvironment } from '../types'; @@ -97,6 +99,10 @@ export default async function createPlugin({ } const dockerClient = new Docker(); + + const discovery = SingleHostDiscovery.fromConfig(config); + const entityClient = new CatalogEntityClient({ discovery }); + return await createRouter({ preparers, templaters, @@ -104,5 +110,6 @@ export default async function createPlugin({ logger, config, dockerClient, + entityClient, }); } diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md new file mode 100644 index 0000000000..20152c16ef --- /dev/null +++ b/packages/dev-utils/CHANGELOG.md @@ -0,0 +1,40 @@ +# @backstage/dev-utils + +## 0.1.2 + +### Patch Changes + +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [3472c8be7] +- Updated dependencies [1d0aec70f] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a3840bed2] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [72f6cda35] +- Updated dependencies [8c2b76e45] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [cba4e4d97] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [8afce088a] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [9a3b3dbf1] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] +- Updated dependencies [7bbeb049f] + - @backstage/cli@0.2.0 + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 + - @backstage/test-utils@0.1.2 diff --git a/packages/dev-utils/README.md b/packages/dev-utils/README.md index 04f8404f64..1aa86ba51c 100644 --- a/packages/dev-utils/README.md +++ b/packages/dev-utils/README.md @@ -20,5 +20,5 @@ $ yarn add -D @backstage/dev-utils ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index d61336465f..60cb5adfd5 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "0.1.1-alpha.26", + "version": "0.1.2", "private": false, "publishConfig": { "access": "public", @@ -11,7 +11,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/dev-utils" }, "keywords": [ @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/test-utils": "^0.1.2", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 18f26d6941..67486710f3 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,12 +1,12 @@ { "name": "docgen", "description": "Tool for generating API Documentation for itself", - "version": "0.1.1-alpha.26", + "version": "0.1.1", "private": true, "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/docgen" }, "keywords": [ diff --git a/packages/docgen/src/docgen/ApiDocsPrinter.ts b/packages/docgen/src/docgen/ApiDocsPrinter.ts index fdd53afc8e..6f6528ec12 100644 --- a/packages/docgen/src/docgen/ApiDocsPrinter.ts +++ b/packages/docgen/src/docgen/ApiDocsPrinter.ts @@ -40,7 +40,7 @@ export default class ApiDocPrinter { 'The following is a list of all Utility APIs defined by `@backstage/core`.', 'They are available to use by plugins and components, and can be accessed ', 'using the `useApi` hook, also provided by `@backstage/core`.', - 'For more information, see https://github.com/spotify/backstage/blob/master/docs/api/utility-apis.md.', + 'For more information, see https://github.com/backstage/backstage/blob/master/docs/api/utility-apis.md.', ); for (const api of apiDocs) { diff --git a/packages/docgen/src/docgen/GitHubMarkdownPrinter.ts b/packages/docgen/src/docgen/GitHubMarkdownPrinter.ts index 64d38d8b15..08e493600d 100644 --- a/packages/docgen/src/docgen/GitHubMarkdownPrinter.ts +++ b/packages/docgen/src/docgen/GitHubMarkdownPrinter.ts @@ -20,7 +20,7 @@ import { MarkdownPrinter, TypeLink } from './types'; import { execSync } from 'child_process'; // TODO(Rugvip): provide through options? -const GH_BASE_URL = 'https://github.com/spotify/backstage'; +const GH_BASE_URL = 'https://github.com/backstage/backstage'; const COMMIT_SHA = process.env.COMMIT_SHA || diff --git a/packages/docgen/src/docgen/TechdocsMarkdownPrinter.ts b/packages/docgen/src/docgen/TechdocsMarkdownPrinter.ts index f2453f314f..bd83699660 100644 --- a/packages/docgen/src/docgen/TechdocsMarkdownPrinter.ts +++ b/packages/docgen/src/docgen/TechdocsMarkdownPrinter.ts @@ -19,7 +19,7 @@ import { Highlighter, MarkdownPrinter, TypeLink } from './types'; import { execSync } from 'child_process'; // TODO(Rugvip): provide through options? -const GH_BASE_URL = 'https://github.com/spotify/backstage'; +const GH_BASE_URL = 'https://github.com/backstage/backstage'; const COMMIT_SHA = process.env.COMMIT_SHA || execSync('git rev-parse HEAD').toString('utf8'); diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md new file mode 100644 index 0000000000..d872d34664 --- /dev/null +++ b/packages/e2e-test/CHANGELOG.md @@ -0,0 +1,7 @@ +# e2e-test + +## 0.2.0 + +### Minor Changes + +- 7de1004f0: Converted into a CLI, use `yarn e2e-test run` to run diff --git a/packages/e2e-test/README.md b/packages/e2e-test/README.md index e3706b6131..139213c0c1 100644 --- a/packages/e2e-test/README.md +++ b/packages/e2e-test/README.md @@ -20,5 +20,5 @@ If you make changes to other packages you will need to rerun `yarn tsc && yarn b ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 9098b3cd07..ea1dcc8ea2 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,12 +1,12 @@ { "name": "e2e-test", "description": "E2E test for verifying Backstage packages", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "private": true, "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/e2e-test" }, "keywords": [ @@ -24,7 +24,7 @@ "e2e-test": "bin/e2e-test" }, "devDependencies": { - "@backstage/cli-common": "^0.1.1-alpha.26", + "@backstage/cli-common": "^0.1.1", "@types/fs-extra": "^9.0.1", "@types/node": "^13.7.2", "chalk": "^4.0.0", diff --git a/packages/storybook/.storybook/webpack-plugin-fail-build-on-warning.js b/packages/storybook/.storybook/webpack-plugin-fail-build-on-warning.js index b812b6bac9..04b6d62e03 100644 --- a/packages/storybook/.storybook/webpack-plugin-fail-build-on-warning.js +++ b/packages/storybook/.storybook/webpack-plugin-fail-build-on-warning.js @@ -16,7 +16,7 @@ /** * When building storybook, we can have warnings which may cause issues in the future. One of the example case is - * https://github.com/spotify/backstage/issues/718. To make sure new warnings are not introduced with new PRs, we + * https://github.com/backstage/backstage/issues/718. To make sure new warnings are not introduced with new PRs, we * want to fail CI builds if there are warnings when building storybook. * * This webpack plugin makes sure the CI builds fail on Webpack warnings. We also have an allowlist of warnings here diff --git a/packages/storybook/CHANGELOG.md b/packages/storybook/CHANGELOG.md new file mode 100644 index 0000000000..f5e44f780c --- /dev/null +++ b/packages/storybook/CHANGELOG.md @@ -0,0 +1,9 @@ +# storybook + +## 0.2.0 + +### Patch Changes + +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] + - @backstage/theme@0.2.0 diff --git a/packages/storybook/package.json b/packages/storybook/package.json index 9eefd85128..f143596a9a 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -1,6 +1,6 @@ { "name": "storybook", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "description": "Storybook build for core package", "private": true, "scripts": { @@ -14,7 +14,7 @@ ] }, "dependencies": { - "@backstage/theme": "^0.1.1-alpha.26" + "@backstage/theme": "^0.2.0" }, "devDependencies": { "@storybook/addon-actions": "^6.0.21", diff --git a/packages/techdocs-cli/.eslintrc.js b/packages/techdocs-cli/.eslintrc.js deleted file mode 100644 index 503c048748..0000000000 --- a/packages/techdocs-cli/.eslintrc.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint.backend')], - rules: { - 'no-console': 0, - }, -}; diff --git a/packages/techdocs-cli/README.md b/packages/techdocs-cli/README.md deleted file mode 100644 index 5d8a3869c7..0000000000 --- a/packages/techdocs-cli/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# TechDocs CLI - -Check out the [TechDocs README](https://github.com/spotify/backstage/blob/master/plugins/techdocs/README.md) to learn more. - -**WIP: This cli is a work in progress. It is not ready for use yet. Follow our progress on [the Backstage Discord](https://discord.gg/MUpMjP2) under #docs-like-code or on [our GitHub Milestone](https://github.com/spotify/backstage/milestone/15).** - -## Prerequisities - -Run the following command from the project root: - -```bash -yarn install -``` - -## Run TechDocs CLI - -You'll need Docker installed and running to use this. - -```bash -cd packages/techdocs-container/mock-docs - -# To get a view of your docs in Backstage, use: -npx techdocs-cli serve - -# To view the raw mkdocs site (without Backstage), use: -npx techdocs-cli serve:mkdocs -``` - -If you run `npx techdocs-cli serve` you should have a `localhost:3000` serving TechDocs in Backstage, as well as `localhost:8000` serving Mkdocs (which won't open up and be exposed to the user). - -If running `npx techdocs-cli serve:mkdocs` you will have `localhost:8000` exposed, serving Mkdocs. - -Happy hacking! - -## Deploying a new version - -Deploying the Node packages to NPM happens automatically on merge to `master` through GitHub Actions. The deployment happens through Lerna which determines which packages throughout the Backstage project have changed. In our case, the package is called `techdocs-cli` in the repository but `@techdocs/cli` in the NPM registry. - -> Note: Once a package is published under a version, any subsequent changes will not override that version. You will need to bump up the version across the entire Backstage repository, which can be done through Lerna (see the command below). - -In order to bump up all packages, go to the root of the Backstage repository. To see the current version see the `lerna.json` under the `version` key. To then update all the versions (locally on your machine), run the following: - -```bash -git checkout -b bump-up-version -yarn lerna version --no-push --allow-branch --yes -``` - -Upon being merged to master, Lerna will then automatically publish these packages as configured by the Backstage core team. diff --git a/packages/techdocs-cli/bin/build.sh b/packages/techdocs-cli/bin/build.sh deleted file mode 100755 index 0a3dfeb96d..0000000000 --- a/packages/techdocs-cli/bin/build.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# 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. - -set -e - -TECHDOCS_PREVIEW_SOURCE=../../plugins/techdocs/dist -TECHDOCS_PREVIEW_DEST=../../packages/techdocs-cli/dist/techdocs-preview-bundle - -# Build the CLI -yarn run backstage-cli -- build --outputs cjs - -# Create export of the TechDocs plugin -APP_CONFIG_techdocs_storageUrl='"http://localhost:3000/api"' yarn workspace @backstage/plugin-techdocs export - -# Copy over export to techdocs-cli dist/ folder -cp -r $TECHDOCS_PREVIEW_SOURCE $TECHDOCS_PREVIEW_DEST - -# Write to console -echo "[techdocs-cli]: Built the dist/ folder" -echo "[techdocs-cli]: Imported @backstage/plugin-techdocs dist/ folder into techdocs-preview-bundle/" diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json deleted file mode 100644 index c111a2973a..0000000000 --- a/packages/techdocs-cli/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "@techdocs/cli", - "description": "CLI for running TechDocs locally.", - "version": "0.1.1-alpha.26", - "private": false, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "https://github.com/spotify/backstage", - "directory": "packages/techdocs-cli" - }, - "keywords": [ - "backstage", - "techdocs" - ], - "license": "Apache-2.0", - "main": "dist/index.cjs.js", - "scripts": { - "build": "./bin/build.sh", - "lint": "backstage-cli lint", - "test": "backstage-cli test --passWithNoTests", - "clean": "backstage-cli clean", - "start": "nodemon --" - }, - "bin": { - "techdocs-cli": "bin/techdocs-cli" - }, - "devDependencies": { - "@types/serve-handler": "^6.1.0" - }, - "files": [ - "bin", - "dist" - ], - "nodemonConfig": { - "watch": "./src", - "exec": "bin/build && bin/techdocs-cli", - "ext": "ts" - }, - "dependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "commander": "^6.1.0", - "fs-extra": "^9.0.1", - "http-proxy": "^1.18.1", - "react-dev-utils": "^10.2.1", - "serve-handler": "^6.1.3" - } -} diff --git a/packages/techdocs-cli/src/index.ts b/packages/techdocs-cli/src/index.ts deleted file mode 100644 index 824bdb84fc..0000000000 --- a/packages/techdocs-cli/src/index.ts +++ /dev/null @@ -1,126 +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. - */ -import { spawn, ChildProcess } from 'child_process'; -import program from 'commander'; -import { version } from '../package.json'; -import path from 'path'; -import HTTPServer from './lib/httpServer'; -import openBrowser from 'react-dev-utils/openBrowser'; - -const run = (name: string, args: string[] = []): ChildProcess => { - const [stdin, stdout, stderr] = [ - 'inherit' as const, - 'pipe' as const, - 'inherit' as const, - ]; - - const childProcess = spawn(name, args, { - stdio: [stdin, stdout, stderr], - shell: true, - env: { - ...process.env, - FORCE_COLOR: 'true', - }, - }); - - childProcess.once('error', error => { - console.error(error); - childProcess.kill(); - }); - - childProcess.once('exit', () => { - process.exit(0); - }); - - return childProcess; -}; - -const runMkdocsServer = (options?: { - devAddr: string; -}): Promise => { - const devAddr = options?.devAddr ?? '0.0.0.0:8000'; - - return new Promise(resolve => { - const childProcess = run('docker', [ - 'run', - '-it', - '-w', - '/content', - '-v', - `${process.cwd()}:/content`, - '-p', - '8000:8000', - 'spotify/techdocs', - 'serve', - '-a', - devAddr, - ]); - - childProcess.stdout?.on('data', rawData => { - const data = rawData.toString().split('\n')[0]; - console.log('[mkdocs] ', data); - - if (data.includes(`Serving on http://${devAddr}`)) { - resolve(childProcess); - } - }); - }); -}; - -const main = (argv: string[]) => { - program.name('techdocs-cli').version(version); - - program - .command('serve:mkdocs') - .description('Serve a documentation project locally') - .action(() => { - runMkdocsServer().then(() => { - openBrowser('http://localhost:8000'); - }); - }); - - program - .command('serve') - .description('Serve a documentation project locally') - .action(() => { - // Mkdocs server - const mkdocsServer = runMkdocsServer(); - - // Local Backstage Preview - const techdocsPreviewBundlePath = path.join( - /* eslint-disable-next-line no-restricted-syntax */ - __dirname, - '..', - 'dist', - 'techdocs-preview-bundle', - ); - - const httpServer = new HTTPServer(techdocsPreviewBundlePath, 3000) - .serve() - .catch(err => { - console.error(err); - mkdocsServer.then(childProcess => childProcess.kill()); - }); - - Promise.all([mkdocsServer, httpServer]).then(() => { - openBrowser('http://localhost:3000/docs/local-dev/'); - }); - }); - - program.parse(argv); -}; - -main(process.argv); diff --git a/packages/techdocs-cli/src/lib/httpServer.ts b/packages/techdocs-cli/src/lib/httpServer.ts deleted file mode 100644 index 6e6578840e..0000000000 --- a/packages/techdocs-cli/src/lib/httpServer.ts +++ /dev/null @@ -1,79 +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. - */ - -import serveHandler from 'serve-handler'; -import http from 'http'; -import httpProxy from 'http-proxy'; - -export default class HTTPServer { - proxyEndpoint: string; - - constructor(public dir: string, public port: number) { - this.proxyEndpoint = '/api/'; - } - - private createProxy() { - const proxy = httpProxy.createProxyServer({ - target: 'http://localhost:8000', - }); - - return (request: http.IncomingMessage): [httpProxy, string] => { - const [, ...pathChunks] = - request.url?.substring(this.proxyEndpoint.length).split('/') ?? []; - const forwardPath = pathChunks.join('/'); - - return [proxy, forwardPath]; - }; - } - - public async serve(): Promise { - return new Promise((resolve, reject) => { - const proxyHandler = this.createProxy(); - - const server = http.createServer( - (request: http.IncomingMessage, response: http.ServerResponse) => { - if (request.url?.startsWith(this.proxyEndpoint)) { - const [proxy, forwardPath] = proxyHandler(request); - - proxy.on('error', (error: Error) => { - reject(error); - }); - - request.url = forwardPath; - return proxy.web(request, response); - } - - return serveHandler(request, response, { - public: this.dir, - trailingSlash: true, - rewrites: [{ source: '**', destination: 'index.html' }], - }); - }, - ); - - server.listen(this.port, () => { - console.log( - '[techdocs-preview-bundle] Running local version of Backstage at http://localhost:3000', - ); - resolve(server); - }); - - server.on('error', (error: Error) => { - reject(error); - }); - }); - } -} diff --git a/packages/techdocs-container/Dockerfile b/packages/techdocs-container/Dockerfile deleted file mode 100644 index 1c1ca264db..0000000000 --- a/packages/techdocs-container/Dockerfile +++ /dev/null @@ -1,28 +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. - -FROM python:3.8-alpine - - -RUN apk update && apk --no-cache add gcc musl-dev openjdk11-jdk curl graphviz ttf-dejavu fontconfig - -RUN curl -o plantuml.jar -L http://sourceforge.net/projects/plantuml/files/plantuml.1.2020.16.jar/download && echo "c789ace48347c43073232b1458badc5810c01fe8 plantuml.jar" | sha1sum -c - && mv plantuml.jar /opt/plantuml.jar -RUN pip install --upgrade pip && pip install mkdocs-techdocs-core==0.0.10 - -# Create script to call plantuml.jar from a location in path - -RUN echo $'#!/bin/sh\n\njava -jar '/opt/plantuml.jar' ${@}' >> /usr/local/bin/plantuml -RUN chmod 755 /usr/local/bin/plantuml - -ENTRYPOINT [ "mkdocs" ] diff --git a/packages/techdocs-container/README.md b/packages/techdocs-container/README.md deleted file mode 100644 index cc92071f5d..0000000000 --- a/packages/techdocs-container/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# techdocs-container - -This is the Docker container that powers the creation of static documentation sites that are supported by [TechDocs](https://github.com/spotify/backstage/blob/master/plugins/techdocs). - -## Getting Started - -Using the TechDocs CLI, we can invoke the latest version of `techdocs-container` via Docker Hub: - -```bash -npx techdocs-cli serve -``` - -## Local Development - -```bash -docker build . -t mkdocs:local-dev - -docker run -w /content -v $(pwd)/mock-docs:/content -p 8000:8000 -it mkdocs:local-dev serve -a 0.0.0.0:8000 -``` - -Then open up `http://localhost:8000` on your local machine. - -## Publishing - -This container is published on DockerHub - https://hub.docker.com/r/spotify/techdocs - -The publishing is configured by [Automated Builds](https://hub.docker.com/repository/docker/spotify/techdocs/builds/edit) feature on Docker Hub which is triggered from GitHub (on new commits and releases). @spotify/techdocs-core team has access to the settings. - -The `latest` tag on Docker Hub points to the recent commits in the `master` branch. The [version tags](https://hub.docker.com/r/spotify/techdocs/tags) (e.g. v0.1.1-alpha.24) point to the GitHub tags created from [releases](https://github.com/spotify/backstage/releases) of this GitHub repository. - -Note: We recommend using a specific version of the container instead of `latest` release for stability and avoiding unexpected changes. diff --git a/packages/techdocs-container/bin/scripts/plantuml b/packages/techdocs-container/bin/scripts/plantuml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/techdocs-container/mock-docs/.gitignore b/packages/techdocs-container/mock-docs/.gitignore deleted file mode 100644 index 45ddf0ae39..0000000000 --- a/packages/techdocs-container/mock-docs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -site/ diff --git a/packages/techdocs-container/mock-docs/docs/index.md b/packages/techdocs-container/mock-docs/docs/index.md deleted file mode 100644 index 94a53acfa3..0000000000 --- a/packages/techdocs-container/mock-docs/docs/index.md +++ /dev/null @@ -1,99 +0,0 @@ -## hello mock docs - -!!! test -Testing something - -Abbreviations: -Some text about MOCDOC - -This is a paragraph. -{: #test_id .test_class } - -Apple -: Pomaceous fruit of plants of the genus Malus in -the family Rosaceae. - -```javascript -import { test } from 'something'; - -const addThingToThing = (a, b) a + b; -``` - -- [abc](#abc) -- [xyz](#xyz) - -## abc - -This is a b c. - -## xyz - -This is x y z. - -# The attack plan - -{% dot attack_plan.svg - digraph G { - rankdir=LR - Earth [peripheries=2] - Mars - Earth -> Mars - } -%} - -```graphviz dot attack_plan.svg -digraph G { - rankdir=LR - Earth [peripheries=2] - Mars - Earth -> Mars -} -``` - -# PlantUML Samples - -```plantuml classes="uml myDiagram" alt="Diagram placeholder" title="My diagram" -@startuml - Goofy -> MickeyMouse: calls - Goofy <-- MickeyMouse: responds -@enduml -``` - -:bulb: - -=== "JavaScript" - - ```javascript - import { test } from 'something'; - - const addThingToThing = (a, b) a + b; - ``` - -=== "Java" - - ```java - public void function() { - test(); - } - ``` - -```java tab="java" - public void function() { - test(); - } -``` - -```java tab="java 2" - public void function() { - test(); - } -``` - -```javascript -import { test } from 'something'; - -const addThingToThing = (a, b) a + b; -``` - - -*[MOCDOC]: Mock Documentation diff --git a/packages/techdocs-container/mock-docs/mkdocs.yml b/packages/techdocs-container/mock-docs/mkdocs.yml deleted file mode 100644 index d769fddfcf..0000000000 --- a/packages/techdocs-container/mock-docs/mkdocs.yml +++ /dev/null @@ -1,9 +0,0 @@ -site_name: 'mock-docs' -site_description: 'mock-docs site description' - -nav: - - Home: index.md - - SubDocs: '!include ./sub-docs/mkdocs.yml' - -plugins: - - techdocs-core diff --git a/packages/techdocs-container/mock-docs/sub-docs/docs/index.md b/packages/techdocs-container/mock-docs/sub-docs/docs/index.md deleted file mode 100644 index 65c6644ef8..0000000000 --- a/packages/techdocs-container/mock-docs/sub-docs/docs/index.md +++ /dev/null @@ -1 +0,0 @@ -### This is an md file in another docs folder using the [MkDocs Monorepo Plugin](https://github.com/spotify/mkdocs-monorepo-plugin) diff --git a/packages/techdocs-container/mock-docs/sub-docs/mkdocs.yml b/packages/techdocs-container/mock-docs/sub-docs/mkdocs.yml deleted file mode 100644 index 4490ddbefa..0000000000 --- a/packages/techdocs-container/mock-docs/sub-docs/mkdocs.yml +++ /dev/null @@ -1,4 +0,0 @@ -site_name: subdocs - -nav: - - Home 2: 'index.md' diff --git a/packages/techdocs-container/techdocs-core/.gitignore b/packages/techdocs-container/techdocs-core/.gitignore deleted file mode 100644 index cd5c4a44f3..0000000000 --- a/packages/techdocs-container/techdocs-core/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.tox -*.egg-info diff --git a/packages/techdocs-container/techdocs-core/README.md b/packages/techdocs-container/techdocs-core/README.md deleted file mode 100644 index 423a076cbf..0000000000 --- a/packages/techdocs-container/techdocs-core/README.md +++ /dev/null @@ -1,145 +0,0 @@ -# techdocs-core - -This is the base [Mkdocs](https://mkdocs.org) plugin used when using Mkdocs with Spotify's TechDocs. It is written in Python and packages all of our Mkdocs defaults, such as theming, plugins, etc in a single plugin. - -[Python Package](https://pypi.org/project/mkdocs-techdocs-core/) - -## Usage - -```bash -$ pip install mkdocs-techdocs-core -``` - -Once you have installed the `mkdocs-techdocs-core` plugin, you'll need to add it to your `mkdocs.yml`. - -```yaml -site_name: Backstage Docs - -nav: - - Home: index.md - - Developing a Plugin: developing-a-plugin.md - -plugins: - - techdocs-core -``` - -## Running Locally - -You can install this package locally using `pip` and the `--editable` flag used for making developing Python packages. - -```bash -pip install --editable . -``` - -You'll then have the `techdocs-core` package available to use in Mkdocs and `pip` will point the dependency to this folder. - -## Running with Docker - -In the parent `Dockerfile` we add this folder to the build and install the package locally in the container. In the future, we'll probably move away from this approach and have it download directly from a Python registry (and this folder will publish to one). - -See the `README.md` located in the `techdocs-container/` folder for more details on how to build and run the Docker container. - -## Linting - -```bash -pip install -r requirements.txt -python -m black src/ -``` - -**Note:** This will write to all Python files in `src/` with the formatted code. If you would like to only check to see if it passes, simply append the `--check` flag. - -## MkDocs plugins and extensions - -The TechDocs Core MkDocs plugin comes with a set of extensions and plugins that mkdocs supports. Below you can find a list of all extensions and plugins that are included in the -TechDocs Core plugin: - -Plugins: - -- [search](https://www.mkdocs.org/user-guide/configuration/#search) -- [mkdocs-monorepo-plugin](https://github.com/spotify/mkdocs-monorepo-plugin) - -Extensions: - -- [admonition](https://squidfunk.github.io/mkdocs-material/reference/admonitions/#admonitions) -- [toc](https://python-markdown.github.io/extensions/toc/) -- [pymdown](https://facelessuser.github.io/pymdown-extensions/) - - caret - - critic - - details - - emoji - - superfences - - inlinehilite - - magiclink - - mark - - smartsymobls - - highlight - - extra - - tabbed - - tasklist - - tilde -- [markdown_inline_graphviz](https://pypi.org/project/markdown-inline-graphviz/) -- [plantuml_markdown](https://pypi.org/project/plantuml-markdown/) - -## Changelog - -### 0.0.10 - -- Pin Markdown version to fix issue with Graphviz - -### 0.0.9 - -- Change development status to 3 - Alpha - -### 0.0.8 - -- Superfences and Codehilite doesn't work very well together (squidfunk/mkdocs-material#1604) so therefore the codehilite extension is replaced by pymdownx.highlight - -* Uses pymdownx extensions v.7.1 instead of 8.0.0 to allow legacy_tab_classes config. This makes the techdocs core plugin compatible with the usage of tabs for grouping markdown with the following syntax: - -```` - ```java tab="java 2" - public void function() { - .... - } - ``` -```` - -as well as the new - -```` - === "Java" - - ```java - public void function() { - .... - } - ``` -```` - -The pymdownx extension will be bumped too 8.0.0 in the near future. - -- pymdownx.tabbed is added to support tabs to group markdown content, such as codeblocks. - -- "PyMdown Extensions includes three extensions that are meant to replace their counterpart in the default Python Markdown extensions." Therefore some extensions has been taken away in this version that comes by default from pymdownx.extra which is added now (https://facelessuser.github.io/pymdown-extensions/usage_notes/#incompatible-extensions) - -### 0.0.7 - -- Fix an issue with configuration of emoji support - -### 0.0.6 - -- Further adjustments to versions to find ones that are compatible - -### 0.0.5 - -- Downgrade some versions of markdown extensions to versions that are more stable - -### 0.0.4 - -- Added support for more mkdocs extensions - - mkdocs-material - - mkdocs-monorepo-plugin - - plantuml-markdown - - markdown_inline_graphviz_extension - - pygments - - pymdown-extensions diff --git a/packages/techdocs-container/techdocs-core/requirements.txt b/packages/techdocs-container/techdocs-core/requirements.txt deleted file mode 100644 index fc56ae6aee..0000000000 --- a/packages/techdocs-container/techdocs-core/requirements.txt +++ /dev/null @@ -1,16 +0,0 @@ -# The "base" version of the Mkdocs project. -# Note: if you update this, also update `install_requires` in setup.py -# https://github.com/mkdocs/mkdocs -mkdocs==1.1.2 -mkdocs-material==5.3.2 -mkdocs-monorepo-plugin==0.4.5 -plantuml-markdown==3.1.2 -markdown_inline_graphviz_extension==1.1 -pygments==2.6.1 -pymdown-extensions==7.1 -Markdown==3.2.2 - -# The linter using for Python -# Note: This requires Python 3.6+ to run, but can format Python 2 code too. -# https://github.com/psf/black -black==19.10b0 diff --git a/packages/techdocs-container/techdocs-core/setup.py b/packages/techdocs-container/techdocs-core/setup.py deleted file mode 100644 index 44ff653d72..0000000000 --- a/packages/techdocs-container/techdocs-core/setup.py +++ /dev/null @@ -1,57 +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. -""" -from setuptools import setup, find_packages -from os import path - -# read the contents of the README file in the current directory -this_dir = path.abspath(path.dirname(__file__)) -with open(path.join(this_dir, "README.md"), encoding="utf-8") as file: - long_description = file.read() - -setup( - name="mkdocs-techdocs-core", - version="0.0.10", - description="A Mkdocs package that contains TechDocs defaults", - long_description=long_description, - long_description_content_type="text/markdown", - keywords="mkdocs", - url="https://github.com/spotify/backstage", - author="TechDocs Core", - author_email="pulp-fiction@spotify.com", - license="Apache-2.0", - python_requires=">=3.7", - install_requires=[ - "mkdocs>=1.1.2", - "mkdocs-material==5.3.2", - "mkdocs-monorepo-plugin==0.4.5", - "plantuml-markdown==3.1.2", - "markdown_inline_graphviz_extension==1.1", - "pygments==2.6.1", - "pymdown-extensions==7.1", - "Markdown==3.2.2", - ], - classifiers=[ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Intended Audience :: Information Technology", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", - ], - packages=find_packages(), - entry_points={"mkdocs.plugins": ["techdocs-core = src.core:TechDocsCore"]}, -) diff --git a/packages/techdocs-container/techdocs-core/src/__init__.py b/packages/techdocs-container/techdocs-core/src/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/techdocs-container/techdocs-core/src/core.py b/packages/techdocs-container/techdocs-core/src/core.py deleted file mode 100644 index 7d32b69ad8..0000000000 --- a/packages/techdocs-container/techdocs-core/src/core.py +++ /dev/null @@ -1,105 +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. -""" - -from mkdocs.plugins import BasePlugin -from mkdocs.theme import Theme -from mkdocs.contrib.search import SearchPlugin -from mkdocs_monorepo_plugin.plugin import MonorepoPlugin -from pymdownx.emoji import to_svg -import tempfile -import os - - -class TechDocsCore(BasePlugin): - def on_config(self, config): - fp = open(os.path.join(tempfile.gettempdir(), "techdocs_metadata.json"), "w+") - fp.write( - '{\n "site_name": "{{ config.site_name }}",\n "site_description": "{{ config.site_description }}"\n}' - ) - - mdx_configs_override = {} - if "mdx_configs" in config: - mdx_configs_override = config["mdx_configs"].copy() - - # Theme - config["theme"] = Theme( - name="material", static_templates=["techdocs_metadata.json",], - ) - config["theme"].dirs.append(tempfile.gettempdir()) - - # Plugins - del config["plugins"]["techdocs-core"] - - search_plugin = SearchPlugin() - search_plugin.load_config({}) - - monorepo_plugin = MonorepoPlugin() - monorepo_plugin.load_config({}) - config["plugins"]["search"] = search_plugin - config["plugins"]["monorepo"] = monorepo_plugin - - # Markdown Extensions - if "markdown_extensions" not in config: - config["markdown_extensions"] = [] - - if "mdx_configs" not in config: - config["mdx_configs"] = {} - - config["markdown_extensions"].append("admonition") - config["markdown_extensions"].append("toc") - config["mdx_configs"]["toc"] = { - "permalink": True, - } - - config["markdown_extensions"].append("pymdownx.caret") - config["markdown_extensions"].append("pymdownx.critic") - config["markdown_extensions"].append("pymdownx.details") - config["markdown_extensions"].append("pymdownx.emoji") - config["mdx_configs"]["pymdownx.emoji"] = {"emoji_generator": to_svg} - config["markdown_extensions"].append("pymdownx.inlinehilite") - config["markdown_extensions"].append("pymdownx.magiclink") - config["markdown_extensions"].append("pymdownx.mark") - config["markdown_extensions"].append("pymdownx.smartsymbols") - config["markdown_extensions"].append("pymdownx.superfences") - config["mdx_configs"]["pymdownx.superfences"] = { - "legacy_tab_classes": True, - } - config["markdown_extensions"].append("pymdownx.highlight") - config["mdx_configs"]["pymdownx.highlight"] = { - "linenums": True, - } - config["markdown_extensions"].append("pymdownx.extra") - config["mdx_configs"]["pymdownx.betterem"] = { - "smart_enable": "all", - } - config["markdown_extensions"].append("pymdownx.tabbed") - config["markdown_extensions"].append("pymdownx.tasklist") - config["mdx_configs"]["pymdownx.tasklist"] = { - "custom_checkbox": True, - } - config["markdown_extensions"].append("pymdownx.tilde") - - config["markdown_extensions"].append("markdown_inline_graphviz") - config["markdown_extensions"].append("plantuml_markdown") - - # merge config supplied by user in the mkdocs.yml - for key in mdx_configs_override: - if key in config["mdx_configs"]: - default_config = config["mdx_configs"][key] - override_config = mdx_configs_override[key] - default_config.update(override_config) - - return config diff --git a/packages/techdocs-container/techdocs-core/src/test_core.py b/packages/techdocs-container/techdocs-core/src/test_core.py deleted file mode 100644 index 621570356c..0000000000 --- a/packages/techdocs-container/techdocs-core/src/test_core.py +++ /dev/null @@ -1,41 +0,0 @@ -import unittest -import mkdocs.config as config -import mkdocs.plugins as plugins -from .core import TechDocsCore - - -class DummyTechDocsCorePlugin(plugins.BasePlugin): - pass - - -class TestTechDocsCoreConfig(unittest.TestCase): - def setUp(self): - self.techdocscore = TechDocsCore() - self.plugin_collection = plugins.PluginCollection() - plugin = DummyTechDocsCorePlugin() - self.plugin_collection["techdocs-core"] = plugin - self.mkdocs_yaml_config = {"plugins": self.plugin_collection} - - def test_removes_techdocs_core_plugin_from_config(self): - final_config = self.techdocscore.on_config(self.mkdocs_yaml_config) - self.assertTrue("techdocs-core" not in final_config["plugins"]) - - def test_merge_default_config_and_user_config(self): - self.mkdocs_yaml_config["markdown_extension"] = [] - self.mkdocs_yaml_config["mdx_configs"] = {} - self.mkdocs_yaml_config["markdown_extension"].append(["toc"]) - self.mkdocs_yaml_config["mdx_configs"]["toc"] = {"toc_depth": 3} - final_config = self.techdocscore.on_config(self.mkdocs_yaml_config) - self.assertTrue("toc" in final_config["mdx_configs"]) - self.assertTrue("permalink" in final_config["mdx_configs"]["toc"]) - self.assertTrue("toc_depth" in final_config["mdx_configs"]["toc"]) - - def test_override_default_config_with_user_config(self): - self.mkdocs_yaml_config["markdown_extension"] = [] - self.mkdocs_yaml_config["mdx_configs"] = {} - self.mkdocs_yaml_config["markdown_extension"].append(["toc"]) - self.mkdocs_yaml_config["mdx_configs"]["toc"] = {"permalink": False} - final_config = self.techdocscore.on_config(self.mkdocs_yaml_config) - self.assertTrue("toc" in final_config["mdx_configs"]) - self.assertTrue("permalink" in final_config["mdx_configs"]["toc"]) - self.assertFalse(final_config["mdx_configs"]["toc"]["permalink"]) diff --git a/packages/test-utils-core/README.md b/packages/test-utils-core/README.md index b99250857d..63b6ece0a6 100644 --- a/packages/test-utils-core/README.md +++ b/packages/test-utils-core/README.md @@ -11,5 +11,5 @@ The reason this package exists is to allow the Backstage core packages to use th ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/test-utils-core/package.json b/packages/test-utils-core/package.json index 1db8f6f023..b35aef77d3 100644 --- a/packages/test-utils-core/package.json +++ b/packages/test-utils-core/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils-core", "description": "Utilities to test Backstage core", - "version": "0.1.1-alpha.26", + "version": "0.1.1", "private": false, "publishConfig": { "access": "public", @@ -11,7 +11,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/test-utils-core" }, "keywords": [ diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md new file mode 100644 index 0000000000..0d71e2ddd3 --- /dev/null +++ b/packages/test-utils/CHANGELOG.md @@ -0,0 +1,26 @@ +# @backstage/test-utils + +## 0.1.2 + +### Patch Changes + +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [cbbd271c4] +- Updated dependencies [3472c8be7] +- Updated dependencies [1d0aec70f] +- Updated dependencies [a3840bed2] +- Updated dependencies [b79017fd3] +- Updated dependencies [72f6cda35] +- Updated dependencies [8c2b76e45] +- Updated dependencies [cba4e4d97] +- Updated dependencies [8afce088a] +- Updated dependencies [9a3b3dbf1] +- Updated dependencies [26e69ab1a] +- Updated dependencies [cbab5bbf8] +- Updated dependencies [7bbeb049f] + - @backstage/cli@0.2.0 + - @backstage/core-api@0.2.0 + - @backstage/theme@0.2.0 diff --git a/packages/test-utils/README.md b/packages/test-utils/README.md index 46a2e2dab3..38bf1e83cf 100644 --- a/packages/test-utils/README.md +++ b/packages/test-utils/README.md @@ -18,5 +18,5 @@ $ yarn add -D @backstage/test-utils ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 74e0c8dcf7..9a7682c76b 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "0.1.1-alpha.26", + "version": "0.1.2", "private": false, "publishConfig": { "access": "public", @@ -11,7 +11,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/test-utils" }, "keywords": [ @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/core-api": "^0.1.1-alpha.26", - "@backstage/test-utils-core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/core-api": "^0.2.0", + "@backstage/test-utils-core": "^0.1.1", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md new file mode 100644 index 0000000000..d8ba8deeba --- /dev/null +++ b/packages/theme/CHANGELOG.md @@ -0,0 +1,19 @@ +# @backstage/theme + +## 0.2.0 + +### Minor Changes + +- 0d4459c08: Tweak dark mode colors + +### Patch Changes + +- ae5983387: Fix banner position and color + + This PR closes: #2245 + + The "fixed" props added to control the position of the banner. When it is set to true the banner will be shown in bottom of that page and the width will be based on the content of the message. + + ![](https://user-images.githubusercontent.com/15106494/93765685-999df480-fc15-11ea-8fa5-11cac5836cf1.png) + + ![](https://user-images.githubusercontent.com/15106494/93765697-9e62a880-fc15-11ea-92af-b6a7fee4bb21.png) diff --git a/packages/theme/README.md b/packages/theme/README.md index a1b6f81f92..4b29738193 100644 --- a/packages/theme/README.md +++ b/packages/theme/README.md @@ -18,5 +18,5 @@ $ yarn add @backstage/theme ## Documentation -- [Backstage Readme](https://github.com/spotify/backstage/blob/master/README.md) -- [Backstage Documentation](https://github.com/spotify/backstage/blob/master/docs/README.md) +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) diff --git a/packages/theme/package.json b/packages/theme/package.json index ddec0e7981..378bd9db57 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "private": false, "publishConfig": { "access": "public", @@ -11,7 +11,7 @@ "homepage": "https://backstage.io", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "packages/theme" }, "keywords": [ @@ -31,7 +31,7 @@ "@material-ui/core": "^4.11.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26" + "@backstage/cli": "^0.2.0" }, "files": [ "dist" diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/baseTheme.ts index b0797c6506..193f6961d6 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/baseTheme.ts @@ -209,9 +209,12 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { // By default there's no margin, but it's usually wanted, so we add some trailing margin marginRight: theme.spacing(1), marginBottom: theme.spacing(1), + color: theme.palette.grey[900], + }, + outlined: { + color: theme.palette.text.primary, }, label: { - color: theme.palette.grey[900], lineHeight: `${theme.spacing(2.5)}px`, fontWeight: theme.typography.fontWeightMedium, fontSize: `${theme.spacing(1.75)}px`, diff --git a/plugins/README.md b/plugins/README.md index d56758b8f0..6651ba079f 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -2,16 +2,16 @@ Backstage is a single-page application composed of a set of plugins. -Our goal for the plugin ecosystem is that the definition of a plugin is flexible enough to allow you to expose pretty much any kind of infrastructure or software development tool as a plugin in Backstage. By following strong [design guidelines](https://github.com/spotify/backstage/blob/master/docs/dls/design.md) we ensure the overall user experience stays consistent between plugins. +Our goal for the plugin ecosystem is that the definition of a plugin is flexible enough to allow you to expose pretty much any kind of infrastructure or software development tool as a plugin in Backstage. By following strong [design guidelines](https://github.com/backstage/backstage/blob/master/docs/dls/design.md) we ensure the overall user experience stays consistent between plugins. ![plugin](../docs/assets/my-plugin_screenshot.png) ## Creating a plugin -To create a plugin, follow the steps outlined [here](https://github.com/spotify/backstage/blob/master/docs/plugins/create-a-plugin.md). +To create a plugin, follow the steps outlined [here](https://github.com/backstage/backstage/blob/master/docs/plugins/create-a-plugin.md). ## Suggesting a plugin -If you start developing a plugin that you aim to release as open source, we suggest that you create a [new Issue](https://github.com/spotify/backstage/issues/new?template=plugin_template.md). This helps the community know what plugins are in development. +If you start developing a plugin that you aim to release as open source, we suggest that you create a [new Issue](https://github.com/backstage/backstage/issues/new?template=plugin_template.md). This helps the community know what plugins are in development. You can also use this process if you have an idea for a good plugin but you hope that someone else will pick up the work. diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md new file mode 100644 index 0000000000..73e6d6a941 --- /dev/null +++ b/plugins/api-docs/CHANGELOG.md @@ -0,0 +1,59 @@ +# @backstage/plugin-api-docs + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 339668995: There were some missing features and markdown was not rendered properly, but this is fixed now. + + Details: + + - [`asyncapi/asyncapi-react#149`](https://github.com/asyncapi/asyncapi-react/pull/149) - fix: improve markdown rendering of nested fields + - [`asyncapi/asyncapi-react#150`](https://github.com/asyncapi/asyncapi-react/pull/150) - feat: display the description of channels and operations + - [`asyncapi/asyncapi-react#153`](https://github.com/asyncapi/asyncapi-react/pull/153) - fix: let the list of `enums` break into multiple lines + +### Patch Changes + +- a73979d45: Resolve some dark mode styling issues in asyncAPI specs +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index baf574d5b5..308a2abc27 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,11 +20,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", - "@kyma-project/asyncapi-react": "^0.13.1", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/theme": "^0.2.0", + "@kyma-project/asyncapi-react": "^0.14.2", "@material-icons/font": "^1.0.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -39,9 +39,9 @@ "swagger-ui-react": "^3.31.1" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md new file mode 100644 index 0000000000..03ecafd574 --- /dev/null +++ b/plugins/app-backend/CHANGELOG.md @@ -0,0 +1,22 @@ +# @backstage/plugin-app-backend + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [8afce088a] +- Updated dependencies [ce5512bc0] +- Updated dependencies [7bbeb049f] + - @backstage/backend-common@0.2.0 + - @backstage/config-loader@0.2.0 diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 8297b466af..c9b82cf6f1 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-backend", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/config-loader": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/config-loader": "^0.2.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^3.0.3", @@ -30,7 +30,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "@types/supertest": "^2.0.8", "msw": "^0.20.5", "supertest": "^4.0.2" diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md new file mode 100644 index 0000000000..344ccd8312 --- /dev/null +++ b/plugins/auth-backend/CHANGELOG.md @@ -0,0 +1,61 @@ +# @backstage/plugin-auth-backend + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 819a70229: Add SAML login to backstage + + ![](https://user-images.githubusercontent.com/872486/92251660-bb9e3400-eeff-11ea-86fe-1f2a0262cd31.png) + + ![](https://user-images.githubusercontent.com/872486/93851658-1a76f200-fce3-11ea-990b-26ca1a327a15.png) + +- 6d29605db: Change the default backend plugin mount point to /api +- 5249594c5: Add service discovery interface and implement for single host deployments + + Fixes #1847, #2596 + + Went with an interface similar to the frontend DiscoveryApi, since it's dead simple but still provides a lot of flexibility in the implementation. + + Also ended up with two different methods, one for internal endpoint discovery and one for external. The two use-cases are explained a bit more in the docs, but basically it's service-to-service vs callback URLs. + + This did get me thinking about uniqueness and that we're heading towards a global namespace for backend plugin IDs. That's probably fine, but if we're happy with that we should leverage it a bit more to simplify the backend setup. For example we'd have each plugin provide its own ID and not manually mount on paths in the backend. + + Draft until we're happy with the implementation, then I can add more docs and changelog entry. Also didn't go on a thorough hunt for places where discovery can be used, but I don't think there are many since it's been pretty awkward to do service-to-service communication. + +- 6f1768c0f: Initial implementation of catalog user lookup + + This adds a basic catalog client + method for the Google provider to look up users in the catalog. It expects to find a single user entity in the catalog with a google.com/email annotation that matches the email of the Google profile. + + Right now it falls back to the old behavior of splitting the email, since I don't wanna break the sign-in flow for existing apps, not yet anyway x). + + - Added "@backstage/catalog-model@^0.1.1-alpha.23" as a dependency + - Added "node-fetch@^2.6.1" as a dependency + +- 1687b8fbb: Lookup user in Google Auth Provider + +### Patch Changes + +- b4e5466e1: Move auth provider router creation to router +- b652bf2cc: Add OneLogin Identity Provider to Auth Backend +- e142a2767: Better presentation of authentication errors +- Updated dependencies [3a4236570] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [a768a07fb] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [5adfc005e] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [fa56f4615] +- Updated dependencies [8afce088a] +- Updated dependencies [b3d57961c] +- Updated dependencies [7bbeb049f] + - @backstage/catalog-model@0.2.0 + - @backstage/backend-common@0.2.0 diff --git a/plugins/auth-backend/README.md b/plugins/auth-backend/README.md index 355fcc1536..e69bb5b86b 100644 --- a/plugins/auth-backend/README.md +++ b/plugins/auth-backend/README.md @@ -52,9 +52,38 @@ export AUTH_GITHUB_ENTERPRISE_INSTANCE_URL=https://x ### Gitlab +#### Creating a GitLab OAuth application + +Follow this link, [Add new application](https://gitlab.com/-/profile/applications). + +1. Set Application Name to `backstage-dev` or something along those lines. +1. The Authorization Callback URL should match the redirect URI set in Backstage. + 1. Set this to `http://localhost:7000/api/auth/gitlab/handler/frame` for local development. + 1. Set this to `http://{APP_FQDN}:{APP_BACKEND_PORT}/api/auth/gitlab/handler/frame` for non-local deployments. + 1. Select the following scopes from the list: + - [x] `read_user` Grants read-only access to the authenticated user's profile through the /user API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under /users. + - [x] `read_repository` Grants read-only access to repositories on private projects using Git-over-HTTP (not using the API). + - [x] `write_repository` Grants read-write access to repositories on private projects using Git-over-HTTP (not using the API). + - [x] `openid` Grants permission to authenticate with GitLab using OpenID Connect. Also gives read-only access to the user's profile and group memberships. + - [x] `profile` Grants read-only access to the user's profile data using OpenID Connect. + - [x] `email` Grants read-only access to the user's primary email address using OpenID Connect. + ```bash -export GITLAB_BASE_URL=x # default is https://gitlab.com -export AUTH_GITLAB_CLIENT_ID=x +export GITLAB_BASE_URL=https://gitlab.com +export AUTH_GITLAB_CLIENT_ID=x # Gitlab calls this the Application ID +export AUTH_GITLAB_CLIENT_SECRET=x +``` + +#### Creating a GitLab Enterprise OAuth application + +If you have GitLab Enterprise, perform the steps above, replacing `gitlab.example.com` in the following +with the domain of your GitLab Enterprise host: + +Create new application at: `https://gitlab.example.com/profile/applications`. + +```bash +export GITLAB_BASE_URL=https://gitlab.example.com +export AUTH_GITLAB_CLIENT_ID=x # GitLab calls this the Application ID export AUTH_GITLAB_CLIENT_SECRET=x ``` @@ -119,7 +148,7 @@ To try out SAML, you can use the mock identity provider: ## Authentication providers -[How to add an auth provider](https://github.com/spotify/backstage/blob/master/docs/auth/add-auth-provider.md) +[How to add an auth provider](https://github.com/backstage/backstage/blob/master/docs/auth/add-auth-provider.md) ## Links diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index caa20e361b..bfeacdf74b 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/catalog-model": "^0.2.0", + "@backstage/config": "^0.1.1", "@types/express": "^4.17.6", "compression": "^1.7.4", "cookie-parser": "^1.4.5", @@ -45,13 +45,14 @@ "passport-microsoft": "^0.1.0", "passport-oauth2": "^1.5.0", "passport-okta-oauth": "^0.0.1", + "passport-onelogin-oauth": "^0.0.1", "passport-saml": "^1.3.3", "uuid": "^8.0.0", "winston": "^3.2.1", "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/jwt-decode": "2.2.1", diff --git a/plugins/auth-backend/src/lib/passport/PassportStrategyHelper.ts b/plugins/auth-backend/src/lib/passport/PassportStrategyHelper.ts index 3264fd8faa..28f15ee9e8 100644 --- a/plugins/auth-backend/src/lib/passport/PassportStrategyHelper.ts +++ b/plugins/auth-backend/src/lib/passport/PassportStrategyHelper.ts @@ -116,7 +116,6 @@ export const executeFrameHandlerStrategy = async ( strategy.redirect = () => { reject(new Error('Unexpected redirect')); }; - strategy.authenticate(req, {}); }, ); diff --git a/plugins/auth-backend/src/providers/factories.ts b/plugins/auth-backend/src/providers/factories.ts index 37761c2305..a764d0b50e 100644 --- a/plugins/auth-backend/src/providers/factories.ts +++ b/plugins/auth-backend/src/providers/factories.ts @@ -22,6 +22,7 @@ import { createOktaProvider } from './okta'; import { createSamlProvider } from './saml'; import { createAuth0Provider } from './auth0'; import { createMicrosoftProvider } from './microsoft'; +import { createOneLoginProvider } from './onelogin'; import { AuthProviderFactory, AuthProviderFactoryOptions } from './types'; const factories: { [providerId: string]: AuthProviderFactory } = { @@ -33,6 +34,7 @@ const factories: { [providerId: string]: AuthProviderFactory } = { auth0: createAuth0Provider, microsoft: createMicrosoftProvider, oauth2: createOAuth2Provider, + onelogin: createOneLoginProvider, }; export function createAuthProvider( diff --git a/plugins/auth-backend/src/providers/onelogin/index.ts b/plugins/auth-backend/src/providers/onelogin/index.ts new file mode 100644 index 0000000000..79af226cd1 --- /dev/null +++ b/plugins/auth-backend/src/providers/onelogin/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export { createOneLoginProvider } from './provider'; diff --git a/plugins/auth-backend/src/providers/onelogin/provider.ts b/plugins/auth-backend/src/providers/onelogin/provider.ts new file mode 100644 index 0000000000..97cf182e5a --- /dev/null +++ b/plugins/auth-backend/src/providers/onelogin/provider.ts @@ -0,0 +1,173 @@ +/* + * 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. + */ + +import { Strategy as OneLoginStrategy } from 'passport-onelogin-oauth'; +import express from 'express'; +import { + OAuthAdapter, + OAuthProviderOptions, + OAuthHandlers, + OAuthResponse, + OAuthEnvironmentHandler, + OAuthStartRequest, + encodeState, + OAuthRefreshRequest, +} from '../../lib/oauth'; +import passport from 'passport'; +import { + executeFrameHandlerStrategy, + executeRedirectStrategy, + executeRefreshTokenStrategy, + makeProfileInfo, + executeFetchUserProfileStrategy, + PassportDoneCallback, +} from '../../lib/passport'; +import { RedirectInfo, AuthProviderFactory } from '../types'; + +type PrivateInfo = { + refreshToken: string; +}; + +export type OneLoginProviderOptions = OAuthProviderOptions & { + issuer: string; +}; + +export class OneLoginProvider implements OAuthHandlers { + private readonly _strategy: any; + + constructor(options: OneLoginProviderOptions) { + this._strategy = new OneLoginStrategy( + { + issuer: options.issuer, + clientID: options.clientId, + clientSecret: options.clientSecret, + callbackURL: options.callbackUrl, + passReqToCallback: false as true, + }, + ( + accessToken: any, + refreshToken: any, + params: any, + rawProfile: passport.Profile, + done: PassportDoneCallback, + ) => { + const profile = makeProfileInfo(rawProfile, params.id_token); + + done( + undefined, + { + providerInfo: { + idToken: params.id_token, + accessToken, + scope: params.scope, + expiresInSeconds: params.expires_in, + }, + profile, + }, + { + refreshToken, + }, + ); + }, + ); + } + async start(req: OAuthStartRequest): Promise { + return await executeRedirectStrategy(req, this._strategy, { + accessType: 'offline', + prompt: 'consent', + scope: 'openid', + state: encodeState(req.state), + }); + } + + async handler( + req: express.Request, + ): Promise<{ response: OAuthResponse; refreshToken: string }> { + const { response, privateInfo } = await executeFrameHandlerStrategy< + OAuthResponse, + PrivateInfo + >(req, this._strategy); + + return { + response: await this.populateIdentity(response), + refreshToken: privateInfo.refreshToken, + }; + } + + async refresh(req: OAuthRefreshRequest): Promise { + const { accessToken, params } = await executeRefreshTokenStrategy( + this._strategy, + req.refreshToken, + req.scope, + ); + + const profile = await executeFetchUserProfileStrategy( + this._strategy, + accessToken, + params.id_token, + ); + + return this.populateIdentity({ + providerInfo: { + accessToken, + idToken: params.id_token, + expiresInSeconds: params.expires_in, + scope: params.scope, + }, + profile, + }); + } + + private async populateIdentity( + response: OAuthResponse, + ): Promise { + const { profile } = response; + + if (!profile.email) { + throw new Error('OIDC profile contained no email'); + } + + const id = profile.email.split('@')[0]; + + return { ...response, backstageIdentity: { id } }; + } +} + +export const createOneLoginProvider: AuthProviderFactory = ({ + globalConfig, + config, + tokenIssuer, +}) => + OAuthEnvironmentHandler.mapConfig(config, envConfig => { + const providerId = 'onelogin'; + const clientId = envConfig.getString('clientId'); + const clientSecret = envConfig.getString('clientSecret'); + const issuer = envConfig.getString('issuer'); + const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + + const provider = new OneLoginProvider({ + clientId, + clientSecret, + callbackUrl, + issuer, + }); + + return OAuthAdapter.fromConfig(globalConfig, provider, { + disableRefresh: false, + providerId, + tokenIssuer, + }); + }); diff --git a/plugins/auth-backend/src/providers/onelogin/types.d.ts b/plugins/auth-backend/src/providers/onelogin/types.d.ts new file mode 100644 index 0000000000..d418f1bcd4 --- /dev/null +++ b/plugins/auth-backend/src/providers/onelogin/types.d.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ +declare module 'passport-onelogin-oauth' { + export class Strategy { + constructor(options: any, verify: any); + } +} diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md new file mode 100644 index 0000000000..e45da37691 --- /dev/null +++ b/plugins/catalog-backend/CHANGELOG.md @@ -0,0 +1,155 @@ +# @backstage/plugin-catalog-backend + +## 0.2.0 + +### Minor Changes + +- e0be86b6f: Entirely case insensitive read path of entities +- 12b5fe940: Add ApiDefinitionAtLocationProcessor that allows to load a API definition from another location +- 57d555eb2: This feature works the same as \$secret does in config - it allows programmatic substitution of values into a document. + + This is particularly useful e.g. for API type entities where you do not want to repeat your entire API spec document inside the catalog-info.yaml file. For those cases, you can instead do something like + + ``` + apiVersion: backstage.io/v1alpha1 + kind: API + metadata: + name: my-federated-service + spec: + type: graphql + definition: + $text: ./schema.graphql + ``` + + The textual content of that file will be injected as the value of definition, during each refresh loop. Both relative and absolute paths are supported, as well as any HTTP/HTTPS URL pointing to a service that returns the relevant data. + + The initial version supports injection of text file data, and structured data from JSON and YAML files. You can add any handler of your own in addition to these. + +- 61db1ddc6: Allow node v14 and add to master build matrix + + - Upgrade sqlite3@^5.0.0 in @backstage/plugin-catalog-backend + - Add Node 14 to engines in @backstage/create-app + +- 81cb94379: Simplify the read function in processors +- a768a07fb: Add the ability to import users from GitHub Organization into the catalog. + + The token needs to have the scopes `user:email`, `read:user`, and `read:org`. + +- ce1f55398: Use the new `UrlReader` in `PlaceholderProcessor`. + This allows to use the placeholder processor to include API definitions in API entities. + Previously it was only possible to do this if the definition comes from the same location type as the entity itself. +- e6b00e3af: Remove the backstage.io/definition-at-location annotation. + The annotation was superseded by the placeholder processor. + + ```yaml + apiVersion: backstage.io/v1alpha1 + kind: API + metadata: + name: spotify + description: The Spotify web API + tags: + - spotify + - rest + annotations: + # Don't use this annotation, but the placeholder $text instead (see below). + backstage.io/definition-at-location: 'url:https://raw.githubusercontent.com/APIs-guru/openapi-directory/master/APIs/spotify.com/v1/swagger.yaml' + spec: + type: openapi + lifecycle: production + owner: spotify@example.com + definition: + $text: https://raw.githubusercontent.com/APIs-guru/openapi-directory/master/APIs/spotify.com/v1/swagger.yaml + ``` + +- 99710b102: The way that wiring together a catalog happens, has changed drastically. Now + there is a new class `CatalogBuilder` that does almost all of the heavy lifting + of how to augment/replace pieces of catalog functionality, such as adding + support for custom entities or adding additional processors. + + As the builder was added, a lot of the static methods and builders for default + setups have been removed from classes deep in the hierarchy. Instead, the + builder contains the knowledge of what the defaults are. + +- 002860e7a: Filters passed to the `/entities` endpoint of the catalog has changed format. + + The old way was to pass things on the form `?a=b&c=d`; the new way is to pass + things on the form `?filter=a=b,c=d`. See discussion in + [#2910](https://github.com/backstage/backstage/issues/2910) for details. + + The comma separated items within a single filter have an AND between them. If + multiple such filters are passed, they have an OR between those item groups. + +- 5adfc005e: Changes the various kind policies into a new type `KindValidator`. + + Adds `CatalogProcessor#validateEntityKind` that makes use of the above + validators. This moves entity schema validity checking away from entity + policies and into processors, centralizing the extension points into the + processor chain. + +- 948052cbb: Add ability to dry run adding a new location to the catalog API. + + The location is now added in a transaction and afterwards rolled back. + This allows users to dry run this operation to see if there entity has issues. + This is probably done by automated tools in the CI/CD pipeline. + +- 4036ff59d: - The `CatalogProcessor` API was updated to have `preProcessEntity` and + `postProcessEntity` methods, instead of just one `processEntity`. This makes + it easier to make processors that have several stages in one, and to make + different processors more position independent in the list of processors. + - The `EntityPolicy` is now given directly to the `LocationReaders`, instead of + being enforced inside a policy. We have decided to separate out the act of + validating an entity to be outside of the processing flow, to make it + possible to apply more liberally and to evolve it as a separate concept. + - Because of the above, the `EntityPolicyProcessor` has been removed. +- 512d70973: Use the new `UrlReader` in the `CodeOwnersProcessor`. +- 2f62e1804: Removed the parseData step from catalog processors. Locations readers should emit full entities instead. +- 36a71d278: Removed support for deprecated `catalog.providers` config that have been moved to `integrations` +- a5cb46bac: Renamed the `LocationProcessor` class to `CatalogProcessor`. + + Likewise, renamed `LocationProcessorResult`, `LocationProcessorLocationResult`, + `LocationProcessorDataResult`, `LocationProcessorEntityResult`, + `LocationProcessorErrorResult`, and `LocationProcessorEmit` to their `Catalog*` + counterparts. + +- 49d70ccab: Remove the `read` argument of `LocationProcessor.processEntity`. + Instead, pass the `UrlReader` into the constructor of your `LocationProcessor`. +- 440a17b39: The catalog backend UrlReaderProcessor now uses a UrlReader from @backstage/backend-common, which must now be supplied to the constructor. + +### Patch Changes + +- 3472c8be7: Add codeowners processor + + - Add `codeowners-utils@^1.0.2` as a dependency + - Add `core-js@^3.6.5` as a dependency + - Added new CodeOwnersProcessor + +- 33454c0f2: Fix `CatalogBuilder#addProcessor`. +- 183e2a30d: Add support for `fields` sub-selection of just parts of an entity when listing + entities in the catalog backend. + + Example: `.../entities?fields=metadata.name,spec.type` will return partial + entity objects with only those exact fields present and the rest cut out. + Fields do not have to be simple scalars - you can for example do + `fields=metadata`. + +- 8bdf0bcf5: Fix CodeOwnersProcessor to handle non team users +- 4c4eab81b: The CodeOwnersProcessor now handles 'url' locations +- Updated dependencies [3a4236570] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [a768a07fb] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [5adfc005e] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [fa56f4615] +- Updated dependencies [8afce088a] +- Updated dependencies [b3d57961c] +- Updated dependencies [7bbeb049f] + - @backstage/catalog-model@0.2.0 + - @backstage/backend-common@0.2.0 diff --git a/plugins/catalog-backend/README.md b/plugins/catalog-backend/README.md index 1b4a653f4a..2f06b9c062 100644 --- a/plugins/catalog-backend/README.md +++ b/plugins/catalog-backend/README.md @@ -27,5 +27,5 @@ This will launch the full example backend, populated some example entities. ## Links -- [Frontend part of the plugin](https://github.com/spotify/backstage/tree/master/plugins/catalog) +- [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/catalog) - [The Backstage homepage](https://backstage.io) diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index d15779bf4e..390c91551f 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/catalog-model": "^0.2.0", + "@backstage/config": "^0.1.1", "@octokit/graphql": "^4.5.6", "@types/express": "^4.17.6", "codeowners-utils": "^1.0.2", @@ -45,8 +45,8 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/test-utils": "^0.1.2", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/ldapjs": "^1.0.9", diff --git a/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.test.ts b/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.test.ts index f3db4c8dc6..00898b33a6 100644 --- a/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.test.ts @@ -17,6 +17,7 @@ import { getVoidLogger } from '@backstage/backend-common'; import type { Entity } from '@backstage/catalog-model'; import { Database, DatabaseManager, Transaction } from '../database'; +import { EntityFilters } from '../service/EntityFilters'; import { DatabaseEntitiesCatalog } from './DatabaseEntitiesCatalog'; import { EntityUpsertRequest } from './types'; @@ -73,13 +74,12 @@ describe('DatabaseEntitiesCatalog', () => { ]); expect(db.entities).toHaveBeenCalledTimes(1); - expect(db.entities).toHaveBeenCalledWith(expect.anything(), [ - { - kind: 'b', - 'metadata.namespace': 'd', - 'metadata.name': ['c'], - }, - ]); + expect(db.entities).toHaveBeenCalledWith( + expect.anything(), + EntityFilters.ofFilterString( + 'kind=b,metadata.namespace=d,metadata.name=c', + ), + ); expect(db.setRelations).toHaveBeenCalledTimes(1); expect(db.setRelations).toHaveBeenCalledWith(expect.anything(), 'u', []); expect(db.addEntities).toHaveBeenCalledTimes(1); @@ -107,13 +107,12 @@ describe('DatabaseEntitiesCatalog', () => { ); expect(db.entities).toHaveBeenCalledTimes(1); - expect(db.entities).toHaveBeenCalledWith(expect.anything(), [ - { - kind: 'b', - 'metadata.namespace': 'd', - 'metadata.name': ['c'], - }, - ]); + expect(db.entities).toHaveBeenCalledWith( + expect.anything(), + EntityFilters.ofFilterString( + 'kind=b,metadata.namespace=d,metadata.name=c', + ), + ); expect(db.setRelations).toHaveBeenCalledTimes(1); expect(db.setRelations).toHaveBeenCalledWith(expect.anything(), 'u', []); expect(db.addEntities).toHaveBeenCalledTimes(1); @@ -204,13 +203,12 @@ describe('DatabaseEntitiesCatalog', () => { ]); expect(db.entities).toHaveBeenCalledTimes(1); - expect(db.entities).toHaveBeenCalledWith(expect.anything(), [ - { - kind: 'b', - 'metadata.namespace': 'd', - 'metadata.name': ['c'], - }, - ]); + expect(db.entities).toHaveBeenCalledWith( + expect.anything(), + EntityFilters.ofFilterString( + 'kind=b,metadata.namespace=d,metadata.name=c', + ), + ); expect(db.entityByName).not.toHaveBeenCalled(); expect(db.entityByUid).toHaveBeenCalledTimes(1); expect(db.entityByUid).toHaveBeenCalledWith(transaction, 'u'); @@ -280,13 +278,12 @@ describe('DatabaseEntitiesCatalog', () => { ]); expect(db.entities).toHaveBeenCalledTimes(1); - expect(db.entities).toHaveBeenCalledWith(expect.anything(), [ - { - kind: 'b', - 'metadata.namespace': 'd', - 'metadata.name': ['c'], - }, - ]); + expect(db.entities).toHaveBeenCalledWith( + expect.anything(), + EntityFilters.ofFilterString( + 'kind=b,metadata.namespace=d,metadata.name=c', + ), + ); expect(db.entityByName).toHaveBeenCalledTimes(1); expect(db.entityByName).toHaveBeenCalledWith(transaction, { kind: 'b', @@ -342,13 +339,12 @@ describe('DatabaseEntitiesCatalog', () => { ]); expect(db.entities).toHaveBeenCalledTimes(1); - expect(db.entities).toHaveBeenCalledWith(expect.anything(), [ - { - kind: 'b', - 'metadata.namespace': 'd', - 'metadata.name': ['c'], - }, - ]); + expect(db.entities).toHaveBeenCalledWith( + expect.anything(), + EntityFilters.ofFilterString( + 'kind=b,metadata.namespace=d,metadata.name=c', + ), + ); expect(db.entityByName).not.toHaveBeenCalled(); expect(db.entityByUid).not.toHaveBeenCalled(); expect(db.updateEntity).not.toHaveBeenCalled(); diff --git a/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.ts b/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.ts index c97ee023e6..5c55a30a55 100644 --- a/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/catalog/DatabaseEntitiesCatalog.ts @@ -16,13 +16,13 @@ import { ConflictError, NotFoundError } from '@backstage/backend-common'; import { + Entity, entityHasChanges, + EntityRelationSpec, generateUpdatedEntity, getEntityName, LOCATION_ANNOTATION, serializeEntityRef, - Entity, - EntityRelationSpec, } from '@backstage/catalog-model'; import { chunk, groupBy } from 'lodash'; import limiterFactory from 'p-limit'; @@ -30,9 +30,10 @@ import { Logger } from 'winston'; import type { Database, DbEntityResponse, - EntityFilters, + EntityFilter, Transaction, } from '../database'; +import { EntityFilters } from '../service/EntityFilters'; import { durationText } from '../util/timing'; import type { EntitiesCatalog, @@ -65,9 +66,9 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog { private readonly logger: Logger, ) {} - async entities(filters?: EntityFilters[]): Promise { + async entities(filter?: EntityFilter): Promise { const items = await this.database.transaction(tx => - this.database.entities(tx, filters), + this.database.entities(tx, filter), ); return items.map(i => i.entity); } @@ -113,9 +114,12 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog { const location = entityResponse.entity.metadata.annotations?.[LOCATION_ANNOTATION]; const colocatedEntities = location - ? await this.database.entities(tx, [ - { [`metadata.annotations.${LOCATION_ANNOTATION}`]: location }, - ]) + ? await this.database.entities( + tx, + EntityFilters.ofMatchers({ + [`metadata.annotations.${LOCATION_ANNOTATION}`]: location, + }), + ) : [entityResponse]; for (const dbResponse of colocatedEntities) { await this.database.removeEntityByUid( @@ -219,9 +223,12 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog { } if (options?.outputEntities) { - const writtenEntities = await this.database.entities(tx, [ - { 'metadata.uid': modifiedEntityIds.map(e => e.entityId) }, - ]); + const writtenEntities = await this.database.entities( + tx, + EntityFilters.ofMatchers({ + 'metadata.uid': modifiedEntityIds.map(e => e.entityId), + }), + ); modifiedEntityIds = writtenEntities.map(e => ({ entityId: e.entity.metadata.uid!, @@ -241,7 +248,7 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog { // If this is only a dry run, cancel the database transaction even if it was successful. await tx.rollback(); - this.logger.debug(`Perfomed successful dry run of adding entities`); + this.logger.debug(`Performed successful dry run of adding entities`); } return entityUpserts; @@ -273,13 +280,14 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog { const markTimestamp = process.hrtime(); const names = requests.map(({ entity }) => entity.metadata.name); - const oldEntities = await this.database.entities(tx, [ - { + const oldEntities = await this.database.entities( + tx, + EntityFilters.ofMatchers({ kind: kind, 'metadata.namespace': namespace, 'metadata.name': names, - }, - ]); + }), + ); const oldEntitiesByName = new Map( oldEntities.map(e => [e.entity.metadata.name, e.entity]), diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index edc6ed2772..52bb6e95ab 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -15,7 +15,7 @@ */ import { Entity, EntityRelationSpec, Location } from '@backstage/catalog-model'; -import type { EntityFilters } from '../database'; +import type { EntityFilter } from '../database'; // // Entities @@ -32,7 +32,7 @@ export type EntityUpsertResponse = { }; export type EntitiesCatalog = { - entities(filters?: EntityFilters[]): Promise; + entities(filter?: EntityFilter): Promise; removeEntityByUid(uid: string): Promise; /** diff --git a/plugins/catalog-backend/src/database/CommonDatabase.test.ts b/plugins/catalog-backend/src/database/CommonDatabase.test.ts index b2a238b111..ffffd85f04 100644 --- a/plugins/catalog-backend/src/database/CommonDatabase.test.ts +++ b/plugins/catalog-backend/src/database/CommonDatabase.test.ts @@ -16,6 +16,7 @@ import { ConflictError } from '@backstage/backend-common'; import { Entity, Location, parseEntityRef } from '@backstage/catalog-model'; +import { EntityFilters } from '../service/EntityFilters'; import { DatabaseManager } from './DatabaseManager'; import type { DbEntityRequest, @@ -348,7 +349,7 @@ describe('CommonDatabase', () => { await db.transaction(async tx => { await db.addEntities(tx, [{ entity: e1 }, { entity: e2 }]); }); - const result = await db.transaction(async tx => db.entities(tx, [])); + const result = await db.transaction(async tx => db.entities(tx)); expect(result.length).toEqual(2); expect(result).toEqual( expect.arrayContaining([ @@ -390,7 +391,7 @@ describe('CommonDatabase', () => { await expect( db.transaction(async tx => - db.entities(tx, [{ kind: 'k2', 'spec.c': 'some' }]), + db.entities(tx, EntityFilters.ofFilterString('kind=k2,spec.c=some')), ), ).resolves.toEqual([ { @@ -400,56 +401,14 @@ describe('CommonDatabase', () => { ]); }); - it('can get all specific entities for matching filters with nulls (both missing and literal null value)', async () => { + it('can get all specific entities for matching filters case insensitively', async () => { const entities: Entity[] = [ - { apiVersion: 'a', kind: 'k1', metadata: { name: 'n' } }, { - apiVersion: 'a', - kind: 'k2', - metadata: { name: 'n' }, - spec: { c: 'some' }, + apiVersion: 'A', + kind: 'K1', + metadata: { name: 'N' }, + spec: { c: 'SOME' }, }, - { - apiVersion: 'a', - kind: 'k3', - metadata: { name: 'n' }, - spec: { c: null }, - }, - ]; - - await db.transaction(async tx => { - await db.addEntities( - tx, - entities.map(entity => ({ entity })), - ); - }); - - const rows = await db.transaction(async tx => - db.entities(tx, [{ apiVersion: 'a', 'spec.c': [null, 'some'] }]), - ); - - expect(rows.length).toEqual(3); - expect(rows).toEqual( - expect.arrayContaining([ - { - locationId: undefined, - entity: expect.objectContaining({ kind: 'k1' }), - }, - { - locationId: undefined, - entity: expect.objectContaining({ kind: 'k2' }), - }, - { - locationId: undefined, - entity: expect.objectContaining({ kind: 'k3' }), - }, - ]), - ); - }); - - it('can get all specific entities for matching filters case insensitively)', async () => { - const entities: Entity[] = [ - { apiVersion: 'A', kind: 'K1', metadata: { name: 'N' } }, { apiVersion: 'a', kind: 'k2', @@ -460,7 +419,7 @@ describe('CommonDatabase', () => { apiVersion: 'a', kind: 'k3', metadata: { name: 'n' }, - spec: { c: null }, + spec: { c: 'somE' }, }, ]; @@ -472,7 +431,10 @@ describe('CommonDatabase', () => { }); const rows = await db.transaction(async tx => - db.entities(tx, [{ ApiVersioN: 'A', 'spEc.C': [null, 'some'] }]), + db.entities( + tx, + EntityFilters.ofFilterString('ApiVersioN=A,spEc.C=some'), + ), ); expect(rows.length).toEqual(3); diff --git a/plugins/catalog-backend/src/database/CommonDatabase.ts b/plugins/catalog-backend/src/database/CommonDatabase.ts index bd6dc29abc..f86ab9e598 100644 --- a/plugins/catalog-backend/src/database/CommonDatabase.ts +++ b/plugins/catalog-backend/src/database/CommonDatabase.ts @@ -45,7 +45,7 @@ import { DbEntityResponse, DbLocationsRow, DbLocationsRowWithStatus, - EntityFilters, + EntityFilter, Transaction, } from './types'; @@ -233,71 +233,36 @@ export class CommonDatabase implements Database { async entities( txOpaque: Transaction, - filters?: EntityFilters[], + filter?: EntityFilter, ): Promise { const tx = txOpaque as Knex.Transaction; let entitiesQuery = tx('entities'); - for (const singleFilter of filters ?? []) { + for (const singleFilter of filter?.anyOf ?? []) { entitiesQuery = entitiesQuery.orWhere(function singleFilterFn() { - for (const [matchKey, matchVal] of Object.entries(singleFilter)) { - const key = matchKey.toLowerCase().replace(/[*]/g, '%'); - const keyOp = key.includes('%') ? 'like' : '='; - const values = Array.isArray(matchVal) ? matchVal : [matchVal]; - - let matchNulls = false; - const matchIn: string[] = []; - const matchLike: string[] = []; - - for (const value of values) { - if (!value) { - matchNulls = true; - } else if (value.includes('*')) { - matchLike.push(value.toLowerCase().replace(/[*]/g, '%')); - } else { - matchIn.push(value.toLowerCase()); - } - } - + for (const { key, matchValueIn } of singleFilter.allOf) { // NOTE(freben): This used to be a set of OUTER JOIN, which may seem to // make a lot of sense. However, it had abysmal performance on sqlite // when datasets grew large, so we're using IN instead. const matchQuery = tx('entities_search') .select('entity_id') .where(function keyFilter() { - this.andWhere('key', keyOp, key); - this.andWhere(function valueFilter() { - if (matchIn.length === 1) { - this.orWhere({ value: matchIn[0] }); - } else if (matchIn.length > 1) { - this.orWhereIn('value', matchIn); + this.andWhere({ key: key.toLowerCase() }); + if (matchValueIn) { + if (matchValueIn.length === 1) { + this.andWhere({ value: matchValueIn[0].toLowerCase() }); + } else if (matchValueIn.length > 1) { + this.andWhere( + 'value', + 'in', + matchValueIn.map(v => v.toLowerCase()), + ); } - if (matchLike.length) { - for (const x of matchLike) { - this.orWhere('value', 'like', tx.raw('?', [x])); - } - } - if (matchNulls) { - // Match explicit nulls, and then handle absence separately - // below - this.orWhereNull('value'); - } - }); + } }); - // Handle absence as nulls as well - this.andWhere(function match() { - this.whereIn('id', matchQuery); - if (matchNulls) { - this.orWhereNotIn( - 'id', - tx('entities_search') - .select('entity_id') - .where('key', keyOp, key), - ); - } - }); + this.andWhere('id', 'in', matchQuery); } }); } diff --git a/plugins/catalog-backend/src/database/index.ts b/plugins/catalog-backend/src/database/index.ts index 0d84106815..c2cc07788a 100644 --- a/plugins/catalog-backend/src/database/index.ts +++ b/plugins/catalog-backend/src/database/index.ts @@ -20,7 +20,7 @@ export type { Database, DbEntityRequest, DbEntityResponse, + EntitiesSearchFilter, EntityFilter, - EntityFilters, Transaction, } from './types'; diff --git a/plugins/catalog-backend/src/database/types.ts b/plugins/catalog-backend/src/database/types.ts index 62b2d55b88..1307b063f2 100644 --- a/plugins/catalog-backend/src/database/types.ts +++ b/plugins/catalog-backend/src/database/types.ts @@ -17,8 +17,8 @@ import type { Entity, EntityName, - Location, EntityRelationSpec, + Location, } from '@backstage/catalog-model'; export type DbEntitiesRow = { @@ -80,26 +80,35 @@ export type DatabaseLocationUpdateLogEvent = { }; /** - * Filter matcher for a single entity field. - * - * Can be either null or a string, or an array of those. Null and the empty - * string are treated equally, and match both a present field with a null or - * empty value, as well as an absent field. - * - * A filter may contain asterisks (*) that are treated as wildcards for zero - * or more arbitrary characters. + * Matches rows in the entities_search table. */ -export type EntityFilter = null | string | (null | string)[]; +export type EntitiesSearchFilter = { + /** + * The key to match on. + * + * Matches are always case insensitive. + */ + key: string; + + /** + * Match on plain equality of values. + * + * If undefined, this factor is not taken into account. Otherwise, match on + * values that are equal to any of the given array items. Matches are always + * case insensitive. + */ + matchValueIn?: string[]; +}; /** - * A set of filter matchers used for filtering entities. + * A filter expression for entities. * - * The keys are full dot-separated paths into the structure of an entity, for - * example "metadata.name". You can also address any item in an array the same - * way, e.g. "a.b.c": "x" works if b is an array of objects that have a c field - * and any of those have the value x. + * Any (at least one) of the outer sets must match, within which all of the + * individual filters must match. */ -export type EntityFilters = Record; +export type EntityFilter = { + anyOf: { allOf: EntitiesSearchFilter[] }[]; +}; /** * An abstraction for transactions of the underlying database technology. @@ -160,10 +169,7 @@ export type Database = { matchingGeneration?: number, ): Promise; - entities( - tx: Transaction, - filters?: EntityFilters[], - ): Promise; + entities(tx: Transaction, filter?: EntityFilter): Promise; entityByName( tx: Transaction, diff --git a/plugins/catalog-backend/src/ingestion/HigherOrderOperations.ts b/plugins/catalog-backend/src/ingestion/HigherOrderOperations.ts index 902e26e0e3..f352e8d3fd 100644 --- a/plugins/catalog-backend/src/ingestion/HigherOrderOperations.ts +++ b/plugins/catalog-backend/src/ingestion/HigherOrderOperations.ts @@ -18,7 +18,7 @@ import { Location, LocationSpec } from '@backstage/catalog-model'; import { v4 as uuidv4 } from 'uuid'; import { Logger } from 'winston'; import { EntitiesCatalog, LocationsCatalog } from '../catalog'; -import { durationText } from '../util/timing'; +import { durationText } from '../util'; import { AddLocationResult, HigherOrderOperation, diff --git a/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.test.ts index b0e857b2bb..e4ddb249d6 100644 --- a/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.test.ts @@ -29,7 +29,7 @@ import { describe('CodeOwnersProcessor', () => { const mockUrl = ({ basePath = '' } = {}): string => - `https://github.com/spotify/backstage/blob/master/${basePath}catalog-info.yaml`; + `https://github.com/backstage/backstage/blob/master/${basePath}catalog-info.yaml`; const mockLocation = ({ basePath = '', type = 'github', @@ -39,12 +39,12 @@ describe('CodeOwnersProcessor', () => { }); const mockReadUrl = (basePath = '') => - `https://github.com/spotify/backstage/blob/master/${basePath}CODEOWNERS`; + `https://github.com/backstage/backstage/blob/master/${basePath}CODEOWNERS`; const mockGitUri = (codeOwnersPath: string = '') => { return { source: 'github.com', - owner: 'spotify', + owner: 'backstage', name: 'backstage', codeOwnersPath, }; @@ -94,7 +94,7 @@ describe('CodeOwnersProcessor', () => { codeOwnersPath: '/.github/CODEOWNERS', }), ).toBe( - 'https://github.com/spotify/backstage/blob/master/.github/CODEOWNERS', + 'https://github.com/backstage/backstage/blob/master/.github/CODEOWNERS', ); }); }); @@ -102,7 +102,7 @@ describe('CodeOwnersProcessor', () => { describe('buildCodeOwnerUrl', () => { it('should build a location spec to the codeowners', () => { expect(buildCodeOwnerUrl(mockUrl(), '/docs/CODEOWNERS')).toEqual( - 'https://github.com/spotify/backstage/blob/master/docs/CODEOWNERS', + 'https://github.com/backstage/backstage/blob/master/docs/CODEOWNERS', ); }); @@ -112,7 +112,9 @@ describe('CodeOwnersProcessor', () => { mockUrl({ basePath: 'packages/foo/' }), '/CODEOWNERS', ), - ).toEqual('https://github.com/spotify/backstage/blob/master/CODEOWNERS'); + ).toEqual( + 'https://github.com/backstage/backstage/blob/master/CODEOWNERS', + ); }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts index bef57a6e5c..9aecb8b86e 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts @@ -182,7 +182,7 @@ export function readConfig(config: Config): ProviderConfig[] { export function parseUrl(urlString: string): { org: string } { const path = new URL(urlString).pathname.substr(1).split('/'); - // /spotify + // /backstage if (path.length === 1 && path[0].length) { return { org: decodeURIComponent(path[0]) }; } diff --git a/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.test.ts index 44f3163a97..48cd2dae01 100644 --- a/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.test.ts @@ -152,7 +152,8 @@ describe('PlaceholderProcessor', () => { }, { type: 'github', - target: 'https://github.com/spotify/backstage/a/b/catalog-info.yaml', + target: + 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', }, ), ).resolves.toEqual({ @@ -163,7 +164,7 @@ describe('PlaceholderProcessor', () => { }); expect(read).toBeCalledWith( - 'https://github.com/spotify/backstage/a/file.txt', + 'https://github.com/backstage/backstage/a/file.txt', ); }); @@ -186,7 +187,8 @@ describe('PlaceholderProcessor', () => { }, { type: 'github', - target: 'https://github.com/spotify/backstage/a/b/catalog-info.yaml', + target: + 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', }, ), ).resolves.toEqual({ @@ -197,7 +199,7 @@ describe('PlaceholderProcessor', () => { }); expect(read).toBeCalledWith( - 'https://github.com/spotify/backstage/a/b/file.json', + 'https://github.com/backstage/backstage/a/b/file.json', ); }); @@ -218,7 +220,8 @@ describe('PlaceholderProcessor', () => { }, { type: 'github', - target: 'https://github.com/spotify/backstage/a/b/catalog-info.yaml', + target: + 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', }, ), ).resolves.toEqual({ @@ -229,7 +232,7 @@ describe('PlaceholderProcessor', () => { }); expect(read).toBeCalledWith( - 'https://github.com/spotify/backstage/a/file.yaml', + 'https://github.com/backstage/backstage/a/file.yaml', ); }); @@ -248,13 +251,14 @@ describe('PlaceholderProcessor', () => { metadata: { name: 'n' }, spec: { data: { - $text: 'https://github.com/spotify/backstage/catalog-info.yaml', + $text: 'https://github.com/backstage/backstage/catalog-info.yaml', }, }, }, { type: 'github', - target: 'https://github.com/spotify/backstage/a/b/catalog-info.yaml', + target: + 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', }, ), ).resolves.toEqual({ @@ -265,7 +269,7 @@ describe('PlaceholderProcessor', () => { }); expect(read).toBeCalledWith( - 'https://github.com/spotify/backstage/catalog-info.yaml', + 'https://github.com/backstage/backstage/catalog-info.yaml', ); }); @@ -284,7 +288,7 @@ describe('PlaceholderProcessor', () => { metadata: { name: 'n' }, spec: { data: { - $text: 'https://github.com/spotify/backstage/catalog-info.yaml', + $text: 'https://github.com/backstage/backstage/catalog-info.yaml', }, }, }, @@ -301,7 +305,7 @@ describe('PlaceholderProcessor', () => { }); expect(read).toBeCalledWith( - 'https://github.com/spotify/backstage/catalog-info.yaml', + 'https://github.com/backstage/backstage/catalog-info.yaml', ); }); @@ -345,7 +349,7 @@ describe('yamlPlaceholderResolver', () => { const params: ResolverParams = { key: 'a', value: './file.yaml', - baseUrl: 'https://github.com/spotify/backstage/a/b/catalog-info.yaml', + baseUrl: 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', read, }; @@ -389,7 +393,7 @@ describe('jsonPlaceholderResolver', () => { const params: ResolverParams = { key: 'a', value: './file.json', - baseUrl: 'https://github.com/spotify/backstage/a/b/catalog-info.yaml', + baseUrl: 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', read, }; diff --git a/plugins/catalog-backend/src/ingestion/processors/index.ts b/plugins/catalog-backend/src/ingestion/processors/index.ts index d654f37dc7..ef9c6332cd 100644 --- a/plugins/catalog-backend/src/ingestion/processors/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/index.ts @@ -19,6 +19,8 @@ import * as results from './results'; export { results }; export * from './types'; +export { parseEntityYaml } from './util/parse'; + export { AnnotateLocationEntityProcessor } from './AnnotateLocationEntityProcessor'; export { CodeOwnersProcessor } from './CodeOwnersProcessor'; export { FileReaderProcessor } from './FileReaderProcessor'; diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts index 74c02e3f84..2a63b20619 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts @@ -17,7 +17,7 @@ import { Config, JsonValue } from '@backstage/config'; import { SearchOptions } from 'ldapjs'; import mergeWith from 'lodash/mergeWith'; -import { RecursivePartial } from './util'; +import { RecursivePartial } from '../../../util'; /** * The configuration parameters for a single LDAP provider. diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/read.test.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/read.test.ts index e7a7d1c567..e644bab22a 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/read.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/read.test.ts @@ -17,6 +17,7 @@ import { GroupEntity, UserEntity } from '@backstage/catalog-model'; import { SearchEntry } from 'ldapjs'; import merge from 'lodash/merge'; +import { RecursivePartial } from '../../../util'; import { LdapClient } from './client'; import { GroupConfig, UserConfig } from './config'; import { @@ -25,7 +26,6 @@ import { LDAP_UUID_ANNOTATION, } from './constants'; import { readLdapGroups, readLdapUsers, resolveRelations } from './read'; -import { RecursivePartial } from './util'; function user(data: RecursivePartial): UserEntity { return merge( diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/util.test.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/util.test.ts index 2def6ad960..63c7253411 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/util.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/util.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { errorString, RecursivePartial } from './util'; +import { errorString } from './util'; describe('errorString', () => { it('formats', () => { @@ -22,17 +22,3 @@ describe('errorString', () => { expect(errorString(e)).toEqual('1 n: m'); }); }); - -describe('RecursivePartial', () => { - it('is recursive', () => { - type X = { - required: { - required: string; - }; - }; - const x: RecursivePartial = { - required: {}, - }; - expect(x).toEqual({ required: {} }); - }); -}); diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/util.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/util.ts index 29159dc219..f5751b1e9f 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/util.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/util.ts @@ -24,14 +24,3 @@ import { Error as LDAPError } from 'ldapjs'; export function errorString(error: LDAPError) { return `${error.code} ${error.name}: ${error.message}`; } - -/** - * Makes all keys of an entire hierarchy optional. - */ -export type RecursivePartial = { - [P in keyof T]?: T[P] extends (infer U)[] - ? RecursivePartial[] - : T[P] extends object - ? RecursivePartial - : T[P]; -}; diff --git a/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts b/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts index 1400a066cd..8cb91fb2ce 100644 --- a/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts @@ -34,7 +34,7 @@ describe('parseEntityYaml', () => { name: backstage description: backstage.io annotations: - github.com/project-slug: 'spotify/backstage' + github.com/project-slug: 'backstage/backstage' spec: type: website lifecycle: production @@ -54,7 +54,7 @@ describe('parseEntityYaml', () => { name: 'backstage', description: 'backstage.io', annotations: { - 'github.com/project-slug': 'spotify/backstage', + 'github.com/project-slug': 'backstage/backstage', }, }, spec: { diff --git a/plugins/catalog-backend/src/service/EntityFilters.test.ts b/plugins/catalog-backend/src/service/EntityFilters.test.ts new file mode 100644 index 0000000000..bfc20c625a --- /dev/null +++ b/plugins/catalog-backend/src/service/EntityFilters.test.ts @@ -0,0 +1,113 @@ +/* + * 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. + */ + +import { EntityFilters } from './EntityFilters'; + +describe('EntityFilters', () => { + describe('ofQuery', () => { + it('translates empty query to empty list', () => { + const result = EntityFilters.ofQuery({}); + expect(result).toEqual(undefined); + }); + + it('supports single-string format', () => { + const result = EntityFilters.ofQuery({ filter: 'a=1' })!; + expect(result).toEqual({ + anyOf: [{ allOf: [{ key: 'a', matchValueIn: ['1'] }] }], + }); + }); + + it('supports array-of-strings format', () => { + const result = EntityFilters.ofQuery({ filter: ['a=1', 'b=2'] }); + expect(result).toEqual({ + anyOf: [ + { allOf: [{ key: 'a', matchValueIn: ['1'] }] }, + { allOf: [{ key: 'b', matchValueIn: ['2'] }] }, + ], + }); + }); + + it('throws for non-strings', () => { + expect(() => EntityFilters.ofQuery({ filter: [3] })).toThrow(/string/); + }); + }); + + describe('ofFilterString', () => { + it('runs the happy path', () => { + const result = EntityFilters.ofFilterString('a=1,b=2'); + expect(result).toEqual({ + anyOf: [ + { + allOf: [ + { key: 'a', matchValueIn: ['1'] }, + { key: 'b', matchValueIn: ['2'] }, + ], + }, + ], + }); + }); + + it('ignores empty', () => { + const result = EntityFilters.ofFilterString('a=1,,b=2,'); + expect(result).toEqual({ + anyOf: [ + { + allOf: [ + { key: 'a', matchValueIn: ['1'] }, + { key: 'b', matchValueIn: ['2'] }, + ], + }, + ], + }); + }); + + it('trims', () => { + const result = EntityFilters.ofFilterString(' a = 1 ,, b=2 ,'); + expect(result).toEqual({ + anyOf: [ + { + allOf: [ + { key: 'a', matchValueIn: ['1'] }, + { key: 'b', matchValueIn: ['2'] }, + ], + }, + ], + }); + }); + + it('merges multiple of the same key', () => { + const result = EntityFilters.ofFilterString('a=1,a=2,b=3'); + expect(result).toEqual({ + anyOf: [ + { + allOf: [ + { key: 'a', matchValueIn: ['1', '2'] }, + { key: 'b', matchValueIn: ['3'] }, + ], + }, + ], + }); + }); + + it('throws on missing equal sign', () => { + expect(() => EntityFilters.ofFilterString('a,b=2')).toThrow(); + }); + + it('throws on misplaced equal sign', () => { + expect(() => EntityFilters.ofFilterString('a=,b=2')).toThrow(); + }); + }); +}); diff --git a/plugins/catalog-backend/src/service/EntityFilters.ts b/plugins/catalog-backend/src/service/EntityFilters.ts new file mode 100644 index 0000000000..5a93407424 --- /dev/null +++ b/plugins/catalog-backend/src/service/EntityFilters.ts @@ -0,0 +1,120 @@ +/* + * 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. + */ + +import { InputError } from '@backstage/backend-common'; +import { EntitiesSearchFilter, EntityFilter } from '../database'; + +/** + * A builder that assists in creating entity filter instances. + */ +export class EntityFilters { + // Builds a filter from the value of a filter=a=1,b=2 type filter string + static ofFilterString(filterString: string): EntityFilter | undefined { + const builder = new EntityFilters(); + builder.addFilterString(filterString); + return builder.build(); + } + + // Builds a filter from an entire query params structure + static ofQuery(query: Record): EntityFilter | undefined { + const filterStrings = [query.filter || []].flat(); + + if (filterStrings.some(f => typeof f !== 'string')) { + throw new InputError( + 'Only string type filter query parameters are supported', + ); + } + + const builder = new EntityFilters(); + for (const filterString of filterStrings) { + builder.addFilterString(filterString); + } + + return builder.build(); + } + + // Builds a filter from a { key: value } matcher object + static ofMatchers( + matchers: Record, + ): EntityFilter | undefined { + const builder = new EntityFilters(); + builder.addMatchers(matchers); + return builder.build(); + } + + private filters: EntitiesSearchFilter[][]; + + constructor() { + this.filters = []; + } + + addFilterString(filterString: string): EntityFilters { + const filtersByKey: Record = {}; + + const addFilter = (key: string, value: string) => { + const f = + key in filtersByKey + ? filtersByKey[key] + : (filtersByKey[key] = { key, matchValueIn: [] }); + f.matchValueIn!.push(value); + }; + + const statements = filterString + .split(',') + .map(s => s.trim()) + .filter(Boolean); + + for (const statement of statements) { + const equalsIndex = statement.indexOf('='); + if (equalsIndex < 1) { + throw new InputError('Malformed filter query'); + } else { + const key = statement.substr(0, equalsIndex).trim(); + const value = statement.substr(equalsIndex + 1).trim(); + if (!key || !value) { + throw new InputError('Malformed filter query'); + } + addFilter(key, value); + } + } + + this.filters.push(Object.values(filtersByKey)); + + return this; + } + + addMatchers(matchers: Record): EntityFilters { + const filters: EntitiesSearchFilter[] = []; + + for (const [key, value] of Object.entries(matchers)) { + filters.push({ key, matchValueIn: [value].flat() }); + } + + if (filters.length) { + this.filters.push(filters); + } + + return this; + } + + build(): EntityFilter | undefined { + if (!this.filters.length) { + return undefined; + } + + return { anyOf: this.filters.map(f => ({ allOf: f })) }; + } +} diff --git a/plugins/catalog-backend/src/service/filterQuery.test.ts b/plugins/catalog-backend/src/service/filterQuery.test.ts index bfb58568b5..a4b3d9c671 100644 --- a/plugins/catalog-backend/src/service/filterQuery.test.ts +++ b/plugins/catalog-backend/src/service/filterQuery.test.ts @@ -15,66 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; -import { - translateFilterQueryEntryToEntityFilters, - translateQueryToEntityFilters, - translateQueryToFieldMapper, -} from './filterQuery'; - -describe('translateQueryToEntityFilters', () => { - it('translates empty query to empty list', () => { - const result = translateQueryToEntityFilters({}); - expect(result).toEqual([]); - }); - - it('supports single-string format', () => { - const result = translateQueryToEntityFilters({ filter: 'a=1' }); - expect(result).toEqual([{ a: ['1'] }]); - }); - - it('supports array-of-strings format', () => { - const result = translateQueryToEntityFilters({ filter: ['a=1', 'b=2'] }); - expect(result).toEqual([{ a: ['1'] }, { b: ['2'] }]); - }); - - it('throws for non-strings', () => { - expect(() => translateQueryToEntityFilters({ filter: [3] })).toThrow( - /string/, - ); - }); -}); - -describe('translateFilterQueryEntryToEntityFilters', () => { - it('runs the happy path', () => { - const result = translateFilterQueryEntryToEntityFilters('a=1,b=2'); - expect(result).toEqual({ a: ['1'], b: ['2'] }); - }); - - it('ignores empty', () => { - const result = translateFilterQueryEntryToEntityFilters('a=1,,b=2,'); - expect(result).toEqual({ a: ['1'], b: ['2'] }); - }); - - it('trims', () => { - const result = translateFilterQueryEntryToEntityFilters(' a = 1 ,, b=2 ,'); - expect(result).toEqual({ a: ['1'], b: ['2'] }); - }); - - it('merges multiple of the same key', () => { - const result = translateFilterQueryEntryToEntityFilters('a=1,a=2,b=3'); - expect(result).toEqual({ a: ['1', '2'], b: ['3'] }); - }); - - it('treats missing equal signs as presence', () => { - const result = translateFilterQueryEntryToEntityFilters('a,b=2'); - expect(result).toEqual({ a: ['*'], b: ['2'] }); - }); - - it('treats empty value as null/absence', () => { - const result = translateFilterQueryEntryToEntityFilters('a=,b=2'); - expect(result).toEqual({ a: [null], b: ['2'] }); - }); -}); +import { translateQueryToFieldMapper } from './filterQuery'; describe('translateQueryToFieldMapper', () => { const entity: Entity = { diff --git a/plugins/catalog-backend/src/service/filterQuery.ts b/plugins/catalog-backend/src/service/filterQuery.ts index 4ab471ffcd..e9b6ef6062 100644 --- a/plugins/catalog-backend/src/service/filterQuery.ts +++ b/plugins/catalog-backend/src/service/filterQuery.ts @@ -17,62 +17,7 @@ import { InputError } from '@backstage/backend-common'; import { Entity } from '@backstage/catalog-model'; import lodash from 'lodash'; -import { EntityFilters } from '../database'; -import { RecursivePartial } from '../ingestion/processors/ldap/util'; - -export function translateQueryToEntityFilters( - query: Record, -): EntityFilters[] { - if (!query.filter) { - return []; - } - - const filterStrings = [query.filter].flat(); - - if (filterStrings.some(s => typeof s !== 'string')) { - throw new InputError( - 'Only string type filter query parameters are supported', - ); - } - - return filterStrings - .filter(Boolean) - .map(translateFilterQueryEntryToEntityFilters); -} - -// Parses the value of a filter=a=1,b=2 type query param -export function translateFilterQueryEntryToEntityFilters( - filterString: string, -): EntityFilters { - const filters: Record = {}; - - const addFilter = (key: string, value: string | null) => { - const matchers = key in filters ? filters[key] : (filters[key] = []); - matchers.push(value || null); - }; - - const statements = filterString - .split(',') - .map(s => s.trim()) - .filter(Boolean); - - for (const statement of statements) { - const equalsIndex = statement.indexOf('='); - if (equalsIndex < 0) { - // Check presence, any value - addFilter(statement, '*'); - } else { - const key = statement.substr(0, equalsIndex).trim(); - const value = statement.substr(equalsIndex + 1).trim(); - if (!key) { - throw new InputError('Malformed filter query'); - } - addFilter(key, value); - } - } - - return filters; -} +import { RecursivePartial } from '../util'; type FieldMapper = (entity: Entity) => Entity; diff --git a/plugins/catalog-backend/src/service/router.test.ts b/plugins/catalog-backend/src/service/router.test.ts index 1cf64945ee..cef40a9aac 100644 --- a/plugins/catalog-backend/src/service/router.test.ts +++ b/plugins/catalog-backend/src/service/router.test.ts @@ -21,6 +21,7 @@ import request from 'supertest'; import { EntitiesCatalog, LocationsCatalog } from '../catalog'; import { LocationResponse } from '../catalog/types'; import { HigherOrderOperation } from '../ingestion/types'; +import { EntityFilters } from './EntityFilters'; import { createRouter } from './router'; describe('createRouter', () => { @@ -78,18 +79,22 @@ describe('createRouter', () => { it('parses single and multiple request parameters and passes them down', async () => { entitiesCatalog.entities.mockResolvedValueOnce([]); const response = await request(app).get( - '/entities?filter=a=1,a=,a=3,b=4&filter=c=', + '/entities?filter=a=1,a=2,b=3&filter=c=4', ); expect(response.status).toEqual(200); expect(entitiesCatalog.entities).toHaveBeenCalledTimes(1); - expect(entitiesCatalog.entities).toHaveBeenCalledWith([ - { - a: ['1', null, '3'], - b: ['4'], - }, - { c: [null] }, - ]); + expect(entitiesCatalog.entities).toHaveBeenCalledWith({ + anyOf: [ + { + allOf: [ + { key: 'a', matchValueIn: ['1', '2'] }, + { key: 'b', matchValueIn: ['3'] }, + ], + }, + { allOf: [{ key: 'c', matchValueIn: ['4'] }] }, + ], + }); }); }); @@ -107,9 +112,9 @@ describe('createRouter', () => { const response = await request(app).get('/entities/by-uid/zzz'); expect(entitiesCatalog.entities).toHaveBeenCalledTimes(1); - expect(entitiesCatalog.entities).toHaveBeenCalledWith([ - { 'metadata.uid': 'zzz' }, - ]); + expect(entitiesCatalog.entities).toHaveBeenCalledWith( + EntityFilters.ofMatchers({ 'metadata.uid': 'zzz' }), + ); expect(response.status).toEqual(200); expect(response.body).toEqual(expect.objectContaining(entity)); }); @@ -120,9 +125,9 @@ describe('createRouter', () => { const response = await request(app).get('/entities/by-uid/zzz'); expect(entitiesCatalog.entities).toHaveBeenCalledTimes(1); - expect(entitiesCatalog.entities).toHaveBeenCalledWith([ - { 'metadata.uid': 'zzz' }, - ]); + expect(entitiesCatalog.entities).toHaveBeenCalledWith( + EntityFilters.ofMatchers({ 'metadata.uid': 'zzz' }), + ); expect(response.status).toEqual(404); expect(response.text).toMatch(/uid/); }); @@ -143,13 +148,13 @@ describe('createRouter', () => { const response = await request(app).get('/entities/by-name/k/ns/n'); expect(entitiesCatalog.entities).toHaveBeenCalledTimes(1); - expect(entitiesCatalog.entities).toHaveBeenCalledWith([ - { + expect(entitiesCatalog.entities).toHaveBeenCalledWith( + EntityFilters.ofMatchers({ kind: 'k', 'metadata.namespace': 'ns', 'metadata.name': 'n', - }, - ]); + }), + ); expect(response.status).toEqual(200); expect(response.body).toEqual(expect.objectContaining(entity)); }); @@ -160,13 +165,13 @@ describe('createRouter', () => { const response = await request(app).get('/entities/by-name/b/d/c'); expect(entitiesCatalog.entities).toHaveBeenCalledTimes(1); - expect(entitiesCatalog.entities).toHaveBeenCalledWith([ - { + expect(entitiesCatalog.entities).toHaveBeenCalledWith( + EntityFilters.ofMatchers({ kind: 'b', 'metadata.namespace': 'd', 'metadata.name': 'c', - }, - ]); + }), + ); expect(response.status).toEqual(404); expect(response.text).toMatch(/name/); }); @@ -209,9 +214,9 @@ describe('createRouter', () => { { entity, relations: [] }, ]); expect(entitiesCatalog.entities).toHaveBeenCalledTimes(1); - expect(entitiesCatalog.entities).toHaveBeenCalledWith([ - { 'metadata.uid': 'u' }, - ]); + expect(entitiesCatalog.entities).toHaveBeenCalledWith( + EntityFilters.ofMatchers({ 'metadata.uid': 'u' }), + ); expect(response.status).toEqual(200); expect(response.body).toEqual(entity); }); diff --git a/plugins/catalog-backend/src/service/router.ts b/plugins/catalog-backend/src/service/router.ts index 96b343a184..ebad544bef 100644 --- a/plugins/catalog-backend/src/service/router.ts +++ b/plugins/catalog-backend/src/service/router.ts @@ -23,10 +23,8 @@ import { Logger } from 'winston'; import yn from 'yn'; import { EntitiesCatalog, LocationsCatalog } from '../catalog'; import { HigherOrderOperation } from '../ingestion/types'; -import { - translateQueryToEntityFilters, - translateQueryToFieldMapper, -} from './filterQuery'; +import { EntityFilters } from './EntityFilters'; +import { translateQueryToFieldMapper } from './filterQuery'; import { requireRequestBody, validateRequestBody } from './util'; export interface RouterOptions { @@ -47,9 +45,9 @@ export async function createRouter( if (entitiesCatalog) { router .get('/entities', async (req, res) => { - const filters = translateQueryToEntityFilters(req.query); + const filter = EntityFilters.ofQuery(req.query); const fieldMapper = translateQueryToFieldMapper(req.query); - const entities = await entitiesCatalog.entities(filters); + const entities = await entitiesCatalog.entities(filter); res.status(200).send(entities.map(fieldMapper)); }) .post('/entities', async (req, res) => { @@ -57,18 +55,16 @@ export async function createRouter( const [result] = await entitiesCatalog.batchAddOrUpdateEntities([ { entity: body as Entity, relations: [] }, ]); - const [entity] = await entitiesCatalog.entities([ - { 'metadata.uid': result.entityId }, - ]); + const [entity] = await entitiesCatalog.entities( + EntityFilters.ofMatchers({ 'metadata.uid': result.entityId }), + ); res.status(200).send(entity); }) .get('/entities/by-uid/:uid', async (req, res) => { const { uid } = req.params; - const entities = await entitiesCatalog.entities([ - { - 'metadata.uid': uid, - }, - ]); + const entities = await entitiesCatalog.entities( + EntityFilters.ofMatchers({ 'metadata.uid': uid }), + ); if (!entities.length) { res.status(404).send(`No entity with uid ${uid}`); } @@ -81,13 +77,13 @@ export async function createRouter( }) .get('/entities/by-name/:kind/:namespace/:name', async (req, res) => { const { kind, namespace, name } = req.params; - const entities = await entitiesCatalog.entities([ - { + const entities = await entitiesCatalog.entities( + EntityFilters.ofMatchers({ kind: kind, 'metadata.namespace': namespace, 'metadata.name': name, - }, - ]); + }), + ); if (!entities.length) { res .status(404) diff --git a/packages/techdocs-cli/bin/techdocs-cli b/plugins/catalog-backend/src/util/RecursivePartial.test.ts old mode 100755 new mode 100644 similarity index 54% rename from packages/techdocs-cli/bin/techdocs-cli rename to plugins/catalog-backend/src/util/RecursivePartial.test.ts index 9818edf417..7f16226188 --- a/packages/techdocs-cli/bin/techdocs-cli +++ b/plugins/catalog-backend/src/util/RecursivePartial.test.ts @@ -1,4 +1,3 @@ -#!/usr/bin/env node /* * Copyright 2020 Spotify AB * @@ -15,22 +14,18 @@ * limitations under the License. */ -/* eslint-disable no-restricted-syntax */ -const path = require('path'); +import { RecursivePartial } from './RecursivePartial'; -// Figure out whether we're running inside the backstage repo or as an installed dependency -const isLocal = require('fs').existsSync(path.resolve(__dirname, '../src')); - -if (!isLocal) { - require('..'); -} else { - require('ts-node').register({ - transpileOnly: true, - project: path.resolve(__dirname, '../../../tsconfig.json'), - compilerOptions: { - module: 'CommonJS', - }, +describe('RecursivePartial', () => { + it('is recursive', () => { + type X = { + required: { + required: string; + }; + }; + const x: RecursivePartial = { + required: {}, + }; + expect(x).toEqual({ required: {} }); }); - - require('../src'); -} +}); diff --git a/plugins/catalog-backend/src/util/RecursivePartial.ts b/plugins/catalog-backend/src/util/RecursivePartial.ts new file mode 100644 index 0000000000..0fa468b4c4 --- /dev/null +++ b/plugins/catalog-backend/src/util/RecursivePartial.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +/** + * Makes all keys of an entire hierarchy optional. + */ +export type RecursivePartial = { + [P in keyof T]?: T[P] extends (infer U)[] + ? RecursivePartial[] + : T[P] extends object + ? RecursivePartial + : T[P]; +}; diff --git a/plugins/catalog-backend/src/util/index.ts b/plugins/catalog-backend/src/util/index.ts index 6f0505d8c5..8364819f99 100644 --- a/plugins/catalog-backend/src/util/index.ts +++ b/plugins/catalog-backend/src/util/index.ts @@ -15,3 +15,5 @@ */ export * from './runPeriodically'; +export * from './RecursivePartial'; +export * from './timing'; diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md new file mode 100644 index 0000000000..30414d6998 --- /dev/null +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -0,0 +1,29 @@ +# @backstage/plugin-catalog-graphql + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- Updated dependencies [3a4236570] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [a768a07fb] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [5adfc005e] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [fa56f4615] +- Updated dependencies [8afce088a] +- Updated dependencies [b3d57961c] +- Updated dependencies [7bbeb049f] + - @backstage/catalog-model@0.2.0 + - @backstage/backend-common@0.2.0 diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index f74aaf7b57..aaa5faac36 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graphql", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/catalog-model": "^0.2.0", + "@backstage/config": "^0.1.1", "@graphql-modules/core": "^0.7.17", "apollo-server": "^2.16.1", "cross-fetch": "^3.0.6", @@ -32,8 +32,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/test-utils": "^0.1.2", "@graphql-codegen/cli": "^1.17.7", "@graphql-codegen/typescript": "^1.17.7", "@graphql-codegen/typescript-resolvers": "^1.17.7", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md new file mode 100644 index 0000000000..7fe67ffba4 --- /dev/null +++ b/plugins/catalog/CHANGELOG.md @@ -0,0 +1,79 @@ +# @backstage/plugin-catalog + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 368fd8243: Created EntityNotFound component for catalog which displays the 404 page when entity is not found. + + Fixes #2266 + +- 6d97d2d6f: The InfoCard variant `'height100'` is deprecated. Use variant `'gridItem'` instead. + + When the InfoCard is displayed as a grid item within a grid, you may want items to have the same height for all items. + Set to the `'gridItem'` variant to display the InfoCard with full height suitable for Grid: + `...` + + Changed the InfoCards in '@backstage/plugin-github-actions', '@backstage/plugin-jenkins', '@backstage/plugin-lighthouse' + to pass an optional variant to the corresponding card of the plugin. + + As a result the overview content of the EntityPage shows cards with full height suitable for Grid. + +- f0aa01bcc: Add client side paging for catalog table +- 8b9c8196f: Locations registered through the catalog client now default to the 'url' type. The type selection dropdown in the register-component form has been removed. +- 2ebcfac8d: Add a validate button to the register-component page + + This allows the user to validate his location before adding it. + +- 0b956f21b: The URL path for a catalog entity has changed, + + - from: `/catalog/:kind/:optionalNamespaceAndName` + - to: `/catalog/:namespace/:kind/:name` + + Redirects are in place, so disruptions for users should not happen. + +### Patch Changes + +- 0aecfded0: handle the case where no entities are available to show +- 60d40892c: Remove "in default" in component name +- 97c2cb19b: update the EntityNotFound component +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [8351ad79b] +- Updated dependencies [fb74f1db6] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [c5ef12926] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [1c8c43756] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [57b54c8ed] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-scaffolder@0.2.0 + - @backstage/plugin-techdocs@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/catalog/README.md b/plugins/catalog/README.md index cff632cb24..e9405a41f5 100644 --- a/plugins/catalog/README.md +++ b/plugins/catalog/README.md @@ -9,5 +9,5 @@ supply the base views to show and manage them. ## Links -- [Backend part of the plugin](https://github.com/spotify/backstage/tree/master/plugins/catalog-backend) +- [Backend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/catalog-backend) - [The Backstage homepage](https://backstage.io) diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 663ac7554b..6d52c4722f 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-scaffolder": "^0.1.1-alpha.26", - "@backstage/plugin-techdocs": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-client": "^0.2.0", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-scaffolder": "^0.2.0", + "@backstage/plugin-techdocs": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -41,9 +42,9 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/react-hooks": "^3.3.0", diff --git a/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx b/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx index bf69818995..2854af2f26 100644 --- a/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx +++ b/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx @@ -27,7 +27,7 @@ describe('', () => { name: 'software', annotations: { 'backstage.io/managed-by-location': - 'github:https://github.com/spotify/backstage/blob/master/software.yaml', + 'github:https://github.com/backstage/backstage/blob/master/software.yaml', }, }, spec: { @@ -40,7 +40,7 @@ describe('', () => { expect(getByText('service')).toBeInTheDocument(); expect(getByText('View Source').closest('a')).toHaveAttribute( 'href', - 'https://github.com/spotify/backstage/blob/master/software.yaml', + 'https://github.com/backstage/backstage/blob/master/software.yaml', ); }); }); diff --git a/plugins/catalog/src/components/AboutCard/AboutCard.tsx b/plugins/catalog/src/components/AboutCard/AboutCard.tsx index fbbf5fa11c..74877b5a65 100644 --- a/plugins/catalog/src/components/AboutCard/AboutCard.tsx +++ b/plugins/catalog/src/components/AboutCard/AboutCard.tsx @@ -87,7 +87,7 @@ function getCodeLinkInfo(entity: Entity): CodeLinkInfo { if (location) { // split by first `:` - // e.g. "github:https://github.com/spotify/backstage/blob/master/software.yaml" + // e.g. "github:https://github.com/backstage/backstage/blob/master/software.yaml" const [type, target] = location.split(/:(.+)/); return { icon: iconMap[type], href: target }; diff --git a/plugins/catalog/src/components/CatalogFilter/AllServicesCount.tsx b/plugins/catalog/src/components/CatalogFilter/AllServicesCount.tsx index b4d90c249a..e78cedbe2d 100644 --- a/plugins/catalog/src/components/CatalogFilter/AllServicesCount.tsx +++ b/plugins/catalog/src/components/CatalogFilter/AllServicesCount.tsx @@ -14,13 +14,13 @@ * limitations under the License. */ -import React, { FC } from 'react'; import { useApi } from '@backstage/core'; -import { catalogApiRef } from '../../api/types'; -import { useAsync } from 'react-use'; import { CircularProgress, useTheme } from '@material-ui/core'; +import React from 'react'; +import { useAsync } from 'react-use'; +import { catalogApiRef } from '../../plugin'; -export const AllServicesCount: FC<{}> = () => { +export const AllServicesCount = () => { const theme = useTheme(); const catalogApi = useApi(catalogApiRef); const { value, loading } = useAsync(() => catalogApi.getEntities()); diff --git a/plugins/catalog/src/components/CatalogFilter/CatalogFilter.test.tsx b/plugins/catalog/src/components/CatalogFilter/CatalogFilter.test.tsx index bc23d61d9c..a4ede7c2f2 100644 --- a/plugins/catalog/src/components/CatalogFilter/CatalogFilter.test.tsx +++ b/plugins/catalog/src/components/CatalogFilter/CatalogFilter.test.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ +import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { ApiProvider, @@ -25,8 +26,8 @@ import { import { MockStorageApi, wrapInTestApp } from '@backstage/test-utils'; import { fireEvent, render, waitFor } from '@testing-library/react'; import React from 'react'; -import { CatalogApi, catalogApiRef } from '../../api/types'; import { EntityFilterGroupsProvider } from '../../filter'; +import { catalogApiRef } from '../../plugin'; import { ButtonGroup, CatalogFilter } from './CatalogFilter'; describe('Catalog Filter', () => { diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx index 5752e58215..0d645f0f35 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx @@ -14,21 +14,21 @@ * limitations under the License. */ +import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { ApiProvider, ApiRegistry, IdentityApi, identityApiRef, - storageApiRef, ProfileInfo, + storageApiRef, } from '@backstage/core'; import { MockStorageApi, wrapInTestApp } from '@backstage/test-utils'; import { fireEvent, render } from '@testing-library/react'; import React from 'react'; -import { catalogApiRef } from '../..'; -import { CatalogApi } from '../../api/types'; import { EntityFilterGroupsProvider } from '../../filter'; +import { catalogApiRef } from '../../plugin'; import { CatalogPage } from './CatalogPage'; describe('CatalogPage', () => { diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 1a9a723f16..e73a789380 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -29,9 +29,9 @@ import SettingsIcon from '@material-ui/icons/Settings'; import StarIcon from '@material-ui/icons/Star'; import React, { useCallback, useMemo, useState } from 'react'; import { Link as RouterLink } from 'react-router-dom'; -import { catalogApiRef } from '../../api/types'; import { EntityFilterGroupsProvider, useFilteredEntities } from '../../filter'; import { useStarredEntities } from '../../hooks/useStarredEntities'; +import { catalogApiRef } from '../../plugin'; import { ButtonGroup, CatalogFilter } from '../CatalogFilter/CatalogFilter'; import { CatalogTable } from '../CatalogTable/CatalogTable'; import { ResultsFilter } from '../ResultsFilter/ResultsFilter'; diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index 4d97ea4334..731a8dedc9 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -68,7 +68,13 @@ const columns: TableColumn[] = [ <> {entity.metadata.tags && entity.metadata.tags.map(t => ( - + ))} ), @@ -150,10 +156,12 @@ export const CatalogTable = ({ columns={columns} options={{ paging: true, - pageSize: 10, + pageSize: 20, actionsColumnIndex: -1, loadingType: 'linear', showEmptyDataSourceMessage: !loading, + padding: 'dense', + pageSizeOptions: [20, 50, 100], }} title={`${titlePreamble} (${(entities && entities.length) || 0})`} data={entities} diff --git a/plugins/catalog/src/components/ResultsFilter/ResultsFilter.test.tsx b/plugins/catalog/src/components/ResultsFilter/ResultsFilter.test.tsx index 6f294c54ff..39837d2ca1 100644 --- a/plugins/catalog/src/components/ResultsFilter/ResultsFilter.test.tsx +++ b/plugins/catalog/src/components/ResultsFilter/ResultsFilter.test.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ +import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { ApiProvider, @@ -25,8 +26,8 @@ import { import { MockStorageApi, wrapInTestApp } from '@backstage/test-utils'; import { render } from '@testing-library/react'; import React from 'react'; -import { CatalogApi, catalogApiRef } from '../../api/types'; import { EntityFilterGroupsProvider } from '../../filter'; +import { catalogApiRef } from '../../plugin'; import { ResultsFilter } from './ResultsFilter'; describe('Results Filter', () => { diff --git a/plugins/catalog/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx b/plugins/catalog/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx index d860ba1ea4..218cc45e78 100644 --- a/plugins/catalog/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx +++ b/plugins/catalog/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx @@ -15,7 +15,7 @@ */ import { Entity, LOCATION_ANNOTATION } from '@backstage/catalog-model'; -import { Progress, useApi, alertApiRef } from '@backstage/core'; +import { alertApiRef, Progress, useApi } from '@backstage/core'; import { Button, Dialog, @@ -31,7 +31,7 @@ import Alert from '@material-ui/lab/Alert'; import React, { FC } from 'react'; import { useAsync } from 'react-use'; import { AsyncState } from 'react-use/lib/useAsync'; -import { catalogApiRef } from '../../api/types'; +import { catalogApiRef } from '../../plugin'; type Props = { open: boolean; diff --git a/plugins/catalog/src/filter/EntityFilterGroupsProvider.tsx b/plugins/catalog/src/filter/EntityFilterGroupsProvider.tsx index ceecc17953..36cc0c56df 100644 --- a/plugins/catalog/src/filter/EntityFilterGroupsProvider.tsx +++ b/plugins/catalog/src/filter/EntityFilterGroupsProvider.tsx @@ -18,7 +18,7 @@ import { Entity } from '@backstage/catalog-model'; import { useApi } from '@backstage/core'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useAsyncFn } from 'react-use'; -import { catalogApiRef } from '../api/types'; +import { catalogApiRef } from '../plugin'; import { filterGroupsContext, FilterGroupsContext } from './context'; import { EntityFilterFn, diff --git a/plugins/catalog/src/filter/useEntityFilterGroup.test.tsx b/plugins/catalog/src/filter/useEntityFilterGroup.test.tsx index 3d11ffe7a9..6b573e3721 100644 --- a/plugins/catalog/src/filter/useEntityFilterGroup.test.tsx +++ b/plugins/catalog/src/filter/useEntityFilterGroup.test.tsx @@ -15,13 +15,13 @@ */ import { ApiProvider, ApiRegistry, storageApiRef } from '@backstage/core'; +import { MockStorageApi } from '@backstage/test-utils'; import { act, renderHook } from '@testing-library/react-hooks'; import React from 'react'; -import { catalogApiRef } from '../api/types'; +import { catalogApiRef } from '../plugin'; import { EntityFilterGroupsProvider } from './EntityFilterGroupsProvider'; -import { FilterGroupStatesReady, FilterGroup } from './types'; +import { FilterGroup, FilterGroupStatesReady } from './types'; import { useEntityFilterGroup } from './useEntityFilterGroup'; -import { MockStorageApi } from '@backstage/test-utils'; describe('useEntityFilterGroup', () => { let catalogApi: jest.Mocked; diff --git a/plugins/catalog/src/hooks/useEntity.ts b/plugins/catalog/src/hooks/useEntity.ts index 1c5b94b8c1..29ca63904d 100644 --- a/plugins/catalog/src/hooks/useEntity.ts +++ b/plugins/catalog/src/hooks/useEntity.ts @@ -18,8 +18,8 @@ import { errorApiRef, useApi } from '@backstage/core'; import { createContext, useContext, useEffect } from 'react'; import { useNavigate } from 'react-router'; import { useAsync } from 'react-use'; -import { catalogApiRef } from '../api/types'; import { useEntityCompoundName } from '../components/useEntityCompoundName'; +import { catalogApiRef } from '../plugin'; type EntityLoadingStatus = { entity?: Entity; diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 762f4924c0..606ad9028d 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -14,12 +14,11 @@ * limitations under the License. */ -export { plugin } from './plugin'; -export * from './api/CatalogClient'; -export * from './api/types'; -export * from './routes'; -export { useEntityCompoundName } from './components/useEntityCompoundName'; -export { Router } from './components/Router'; -export { useEntity, EntityContext } from './hooks/useEntity'; +export * from '@backstage/catalog-client'; export { AboutCard } from './components/AboutCard'; export { EntityPageLayout } from './components/EntityPageLayout'; +export { Router } from './components/Router'; +export { useEntityCompoundName } from './components/useEntityCompoundName'; +export { EntityContext, useEntity } from './hooks/useEntity'; +export { catalogApiRef, plugin } from './plugin'; +export * from './routes'; diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index dfe12fd500..5f737ec12d 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -14,13 +14,19 @@ * limitations under the License. */ +import { CatalogApi, CatalogClient } from '@backstage/catalog-client'; import { - createPlugin, createApiFactory, + createApiRef, + createPlugin, discoveryApiRef, } from '@backstage/core'; -import { catalogApiRef } from './api/types'; -import { CatalogClient } from './api/CatalogClient'; + +export const catalogApiRef = createApiRef({ + id: 'plugin.catalog.service', + description: + 'Used by the Catalog plugin to make requests to accompanying backend', +}); export const plugin = createPlugin({ id: 'catalog', diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md new file mode 100644 index 0000000000..065d2e6526 --- /dev/null +++ b/plugins/circleci/CHANGELOG.md @@ -0,0 +1,52 @@ +# @backstage/plugin-circleci + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 30dd11122: Refactor to use DiscoveryApi + +### Patch Changes + +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 7733d713ab..cd849cbd31 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-circleci", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "postpack": "backstage-cli postpack" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -38,9 +38,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md new file mode 100644 index 0000000000..a9df03e8e2 --- /dev/null +++ b/plugins/cloudbuild/CHANGELOG.md @@ -0,0 +1,51 @@ +# @backstage/plugin-cloudbuild + +## 0.2.0 + +### Minor Changes + +- 2846ef95c: Releasing Google Cloud Build Plugin + +### Patch Changes + +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 29bfd1b261..14a7c5091c 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cloudbuild", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,10 +20,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -39,9 +39,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md new file mode 100644 index 0000000000..2d478c5717 --- /dev/null +++ b/plugins/cost-insights/CHANGELOG.md @@ -0,0 +1,65 @@ +# @backstage/plugin-cost-insights + +## 0.2.0 + +### Minor Changes + +- cab473771: This PR adds Spotify's Cost Insights Tool. Cost Insights explains costs from cloud services in an understandable way, using software terms familiar to your engineers. This tool helps you and your team make trade-offs between cost optimization efforts and your other priorities. + + Cost Insights features: + + Daily cost graph by team or billing account + Cost comparison against configurable business metrics + Insights panels for configurable cloud products your company uses + Cost alerts and recommendations + Selectable time periods for month over month, or quarter over quarter cost comparison + Conversion of cost growth into average engineer cost (configurable) to help optimization trade-off decisions + + ![plugin-cost-insights](https://user-images.githubusercontent.com/3030003/94430416-e166d380-0161-11eb-891c-9ce10187683e.gif) + + This PR adds the Cost Insights frontend React plugin with a defined CostInsightsApi. We include an example client with static data in the expected format. This API should talk with a cloud billing backend that aggregates billing data from your cloud provider. + + Fixes #688 💵 + +- bb48b9833: Added getLastCompleteBillingDate to the CostInsightsApi to reason about completeness of billing data +- 6a84cb072: Enable custom alert types in Cost Insights +- e7d4ac7ce: - getProjectDailyCost and getGroupDailyCost no longer accept a metric as a parameter + - getDailyMetricData added to API for fetching daily metric data for given interval + - dailyCost removed as configurable metric + - default field added to metric configuration for displaying comparison metric data in top panel + - Metric.kind can no longer be null + - MetricData type added +- 0e67c6b40: Remove product filters from query parameters + +### Patch Changes + +- 8d1360aa9: export test utilities for mocking context +- 0ee9e9f66: migrate type utilities out of type definition files +- 5c70f3d35: expose alerts utilities for export +- fd8384d7e: prefer named exports +- 26e69ab1a: Remove cost insights example client from demo app and export from plugin + Create cost insights dev plugin using example client + Make PluginConfig and dependent types public +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 + - @backstage/test-utils@0.1.2 diff --git a/plugins/cost-insights/README.md b/plugins/cost-insights/README.md index 3b6e1e4fd5..886efa8eb6 100644 --- a/plugins/cost-insights/README.md +++ b/plugins/cost-insights/README.md @@ -21,7 +21,7 @@ yarn add @backstage/plugin-cost-insights 1. Configure `app-config.yaml`. See [Configuration](#configuration). -2. Create a CostInsights client. Clients must implement the CostInsightsApi interface. See the [API file](https://github.com/spotify/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts) for required methods and documentation. +2. Create a CostInsights client. Clients must implement the CostInsightsApi interface. See the [API file](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts) for required methods and documentation. ```ts // path/to/CostInsightsClient.ts @@ -58,7 +58,7 @@ export { plugin as CostInsights } from '@backstage/plugin-cost-insights'; Cost Insights has only two required configuration fields: a map of cloud `products` for showing cost breakdowns and `engineerCost` - the average yearly cost of an engineer including benefits. Products must be defined as keys on the `products` field. -You can optionally supply a product `icon` to display in Cost Insights navigation. See the [type file](https://github.com/spotify/backstage/blob/master/plugins/cost-insights/src/types/Icon.ts) for supported types and Material UI icon [mappings](https://github.com/spotify/backstage/blob/master/plugins/cost-insights/src/utils/navigation.tsx). +You can optionally supply a product `icon` to display in Cost Insights navigation. See the [type file](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/types/Icon.ts) for supported types and Material UI icon [mappings](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/utils/navigation.tsx). **Note:** Product keys should be unique and camelCased. Backstage does not support underscores in configuration keys. @@ -106,7 +106,7 @@ costInsights: ## Alerts -The CostInsightsApi `getAlerts` method may return any type of alert or recommendation (called collectively "Action Items" in Cost Insights) that implements the [Alert type](https://github.com/spotify/backstage/blob/master/plugins/cost-insights/src/types/Alert.ts). This allows you to deliver any alerts or recommendations specific to your infrastructure or company migrations. +The CostInsightsApi `getAlerts` method may return any type of alert or recommendation (called collectively "Action Items" in Cost Insights) that implements the [Alert type](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/types/Alert.ts). This allows you to deliver any alerts or recommendations specific to your infrastructure or company migrations. The Alert type includes an `element` field to supply the JSX Element that will be rendered in the Cost Insights "Action Items" section; we recommend using Backstage's [InfoCard](https://backstage.io/storybook/?path=/story/layout-information-card--default) and [Recharts](http://recharts.org/en-US/) to show actionable visualizations. diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index abefb601d2..944dbf587f 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cost-insights", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1", + "@backstage/core": "^0.2.0", + "@backstage/test-utils": "^0.1.2", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -46,9 +46,9 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/cost-insights/src/api/CostInsightsApi.ts b/plugins/cost-insights/src/api/CostInsightsApi.ts index 5493130f78..9baad5ffab 100644 --- a/plugins/cost-insights/src/api/CostInsightsApi.ts +++ b/plugins/cost-insights/src/api/CostInsightsApi.ts @@ -26,6 +26,34 @@ import { MetricData, } from '../types'; +export type ProductInsightsOptions = { + /** + * The product from the cost-insights configuration in app-config.yaml + */ + product: string; + + /** + * The group id from getUserGroups or query parameters + */ + group: string; + + /** + * A time duration, such as P1M. See the Duration type for a detailed explanation + * of how the durations are interpreted in Cost Insights. + */ + duration: Duration; + + /** + * The most current date for which billing data is complete, in YYYY-MM-DD format. + */ + lastCompleteBillingDate: string; + + /** + * (optional) The project id from getGroupProjects or query parameters + */ + project: Maybe; +}; + export type CostInsightsApi = { /** * Get the most current date for which billing data is complete, in YYYY-MM-DD format. This helps @@ -108,19 +136,9 @@ export type CostInsightsApi = { * The time period is supplied as a Duration rather than intervals, since this is always expected * to return data for two bucketed time period (e.g. month vs month, or quarter vs quarter). * - * @param product The product from the cost-insights configuration in app-config.yaml - * @param group - * @param duration A time duration, such as P1M. See the Duration type for a detailed explanation - * of how the durations are interpreted in Cost Insights. - * @param project (optional) The project id from getGroupProjects or query parameters + * @param options Options to use when fetching insights for a particular cloud product and interval timeframe. */ - getProductInsights( - product: string, - group: string, - duration: Duration, - project: Maybe, - ): Promise; - + getProductInsights(options: ProductInsightsOptions): Promise; /** * Get current cost alerts for a given group. These show up as Action Items for the group on the * Cost Insights page. Alerts may include cost-saving recommendations, such as infrastructure diff --git a/plugins/cost-insights/src/client.ts b/plugins/cost-insights/src/client.ts index afdd9aff74..50e925bc28 100644 --- a/plugins/cost-insights/src/client.ts +++ b/plugins/cost-insights/src/client.ts @@ -17,7 +17,7 @@ import dayjs from 'dayjs'; import regression, { DataPoint } from 'regression'; -import { CostInsightsApi } from '../src/api'; +import { CostInsightsApi, ProductInsightsOptions } from '../src/api'; import { Alert, ChangeStatistic, @@ -27,7 +27,6 @@ import { Duration, Entity, Group, - Maybe, MetricData, Project, ProjectGrowthData, @@ -194,176 +193,169 @@ export class ExampleCostInsightsClient implements CostInsightsApi { } async getProductInsights( - product: string, - group: string, - duration: Duration, - project: Maybe, + productInsightsOptions: ProductInsightsOptions, ): Promise { - const projectProductInsights = await this.request( - { product, group, duration, project }, - { - id: 'project-product', - aggregation: [80_000, 110_000], - change: { - ratio: 0.375, - amount: 30_000, - }, - entities: [ - { - id: null, // entities with null ids will be appear as "Unlabeled" in product panels - aggregation: [45_000, 50_000], - change: { - ratio: 0.111, - amount: 5_000, - }, - entities: [], - }, - { - id: 'entity-a', - aggregation: [15_000, 20_000], - change: { - ratio: 0.333, - amount: 5_000, - }, - entities: [], - }, - { - id: 'entity-b', - aggregation: [20_000, 30_000], - change: { - ratio: 0.5, - amount: 10_000, - }, - entities: [], - }, - { - id: 'entity-c', - aggregation: [0, 10_000], - change: { - ratio: 10_000, - amount: 10_000, - }, - entities: [], - }, - ], + const projectProductInsights = await this.request(productInsightsOptions, { + id: 'project-product', + aggregation: [80_000, 110_000], + change: { + ratio: 0.375, + amount: 30_000, }, - ); - - const productInsights: Entity = await this.request( - { product, group, duration, project }, - { - id: 'product', - aggregation: [200_000, 250_000], - change: { - ratio: 0.2, - amount: 50_000, + entities: [ + { + id: null, // entities with null ids will be appear as "Unlabeled" in product panels + aggregation: [45_000, 50_000], + change: { + ratio: 0.111, + amount: 5_000, + }, + entities: [], }, - entities: [ - { - id: null, // entities with null ids will be appear as "Unlabeled" in product panels - aggregation: [36_000, 42_000], - change: { - ratio: 0.1666, - amount: 6_000, - }, - entities: [], + { + id: 'entity-a', + aggregation: [15_000, 20_000], + change: { + ratio: 0.333, + amount: 5_000, }, - { - id: 'entity-a', - aggregation: [15_000, 20_000], - change: { - ratio: -0.33333333, - amount: 5_000, - }, - entities: [], + entities: [], + }, + { + id: 'entity-b', + aggregation: [20_000, 30_000], + change: { + ratio: 0.5, + amount: 10_000, }, - { - id: 'entity-b', - aggregation: [20_000, 30_000], - change: { - ratio: 0.5, - amount: 10_000, - }, - entities: [], + entities: [], + }, + { + id: 'entity-c', + aggregation: [0, 10_000], + change: { + ratio: 10_000, + amount: 10_000, }, - { - id: 'entity-c', - aggregation: [18_000, 25_000], - change: { - ratio: 0.38, - amount: 7_000, - }, - entities: [], - }, - { - id: 'entity-d', - aggregation: [15_000, 30_000], - change: { - ratio: 1, - amount: 15_000, - }, - entities: [], - }, - { - id: 'entity-e', - aggregation: [0, 10_000], - entities: [], - change: { - ratio: 10_000, - amount: 10_000, - }, - }, - { - id: 'entity-f', - aggregation: [17_000, 19_000], - change: { - ratio: 0.118, - amount: 2_000, - }, - entities: [], - }, - { - id: 'entity-g', - aggregation: [80_000, 60_000], - change: { - ratio: -0.25, - amount: -20_000, - }, - entities: [ - { - id: 'vCPU Time Batch Belgium', - aggregation: [15_000, 15_000], - change: { - ratio: 0, - amount: 0, - }, - entities: [], - }, - { - id: 'RAM Time Belgium', - aggregation: [15_000, 30_000], - change: { - ratio: 1, - amount: 15_000, - }, - entities: [], - }, - { - id: 'Local Disk Time PD Standard Belgium', - aggregation: [50_000, 15_000], - change: { - ratio: -0.7, - amount: -35_000, - }, - entities: [], - }, - ], - }, - ], - }, - ); + entities: [], + }, + ], + }); - return project ? projectProductInsights : productInsights; + const productInsights: Entity = await this.request(productInsightsOptions, { + id: 'product', + aggregation: [200_000, 250_000], + change: { + ratio: 0.2, + amount: 50_000, + }, + entities: [ + { + id: null, // entities with null ids will be appear as "Unlabeled" in product panels + aggregation: [36_000, 42_000], + change: { + ratio: 0.1666, + amount: 6_000, + }, + entities: [], + }, + { + id: 'entity-a', + aggregation: [15_000, 20_000], + change: { + ratio: -0.33333333, + amount: 5_000, + }, + entities: [], + }, + { + id: 'entity-b', + aggregation: [20_000, 30_000], + change: { + ratio: 0.5, + amount: 10_000, + }, + entities: [], + }, + { + id: 'entity-c', + aggregation: [18_000, 25_000], + change: { + ratio: 0.38, + amount: 7_000, + }, + entities: [], + }, + { + id: 'entity-d', + aggregation: [15_000, 30_000], + change: { + ratio: 1, + amount: 15_000, + }, + entities: [], + }, + { + id: 'entity-e', + aggregation: [0, 10_000], + entities: [], + change: { + ratio: 10_000, + amount: 10_000, + }, + }, + { + id: 'entity-f', + aggregation: [17_000, 19_000], + change: { + ratio: 0.118, + amount: 2_000, + }, + entities: [], + }, + { + id: 'entity-g', + aggregation: [80_000, 60_000], + change: { + ratio: -0.25, + amount: -20_000, + }, + entities: [ + { + id: 'vCPU Time Batch Belgium', + aggregation: [15_000, 15_000], + change: { + ratio: 0, + amount: 0, + }, + entities: [], + }, + { + id: 'RAM Time Belgium', + aggregation: [15_000, 30_000], + change: { + ratio: 1, + amount: 15_000, + }, + entities: [], + }, + { + id: 'Local Disk Time PD Standard Belgium', + aggregation: [50_000, 15_000], + change: { + ratio: -0.7, + amount: -35_000, + }, + entities: [], + }, + ], + }, + ], + }); + + return productInsightsOptions.project + ? projectProductInsights + : productInsights; } async getAlerts(group: string): Promise { diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx index 1bd945241a..6ed72923ff 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx @@ -37,7 +37,10 @@ import { MetricData, CostInsightsTheme, } from '../../types'; -import { BarChartTooltip, BarChartTooltipItem } from '../BarChart'; +import { + BarChartTooltip as Tooltip, + BarChartTooltipItem as TooltipItem, +} from '../BarChart'; import { overviewGraphTickFormatter, formatGraphValue, @@ -120,11 +123,11 @@ export const CostOverviewChart = ({ })); return ( - + {items.map((item, index) => ( - + ))} - + ); }; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx index da304d42a2..2a1f962000 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx @@ -17,10 +17,16 @@ import React, { useCallback, useEffect, useState } from 'react'; import { InfoCard, useApi } from '@backstage/core'; import Alert from '@material-ui/lab/Alert'; +import { Typography } from '@material-ui/core'; import { costInsightsApiRef } from '../../api'; import { ProductInsightsChart } from './ProductInsightsChart'; import { PeriodSelect } from '../PeriodSelect'; -import { useFilters, useLoading, useScroll } from '../../hooks'; +import { + useFilters, + useLastCompleteBillingDate, + useLoading, + useScroll, +} from '../../hooks'; import { useProductInsightsCardStyles as useStyles } from '../../utils/styles'; import { mapFiltersToProps, mapLoadingToProps } from './selector'; import { Duration, Maybe, Product, Entity } from '../../types'; @@ -34,6 +40,7 @@ export const ProductInsightsCard = ({ product }: ProductInsightsCardProps) => { const client = useApi(costInsightsApiRef); const classes = useStyles(); const { ScrollAnchor } = useScroll(product.kind); + const lastCompleteBillingDate = useLastCompleteBillingDate(); const [entity, setEntity] = useState>(null); const [error, setError] = useState>(null); @@ -49,22 +56,23 @@ export const ProductInsightsCard = ({ product }: ProductInsightsCardProps) => { const dispatchLoadingProduct = useCallback(dispatchLoading, [product.kind]); const amount = entity?.entities?.length || 0; - const hasCostsWithinTimeframe = entity?.change && !!amount; + const hasCostsWithinTimeframe = !!(entity?.change && amount); - const subheader = amount + const subheader = hasCostsWithinTimeframe ? `${amount} ${pluralOf(amount, 'entity', 'entities')}, sorted by cost` - : `There are no ${product.name} costs within this timeframe for your team's projects.`; + : null; useEffect(() => { async function load() { if (loadingProduct) { try { - const e: Entity = await client.getProductInsights( - product.kind, - group!, - productFilter!.duration, + const e: Entity = await client.getProductInsights({ + product: product.kind, + group: group!, + duration: productFilter!.duration, + lastCompleteBillingDate, project, - ); + }); setEntity(e); } catch (e) { setError(e); @@ -84,6 +92,7 @@ export const ProductInsightsCard = ({ product }: ProductInsightsCardProps) => { group, product.kind, project, + lastCompleteBillingDate, ]); const onPeriodSelect = (duration: Duration) => { @@ -119,11 +128,17 @@ export const ProductInsightsCard = ({ product }: ProductInsightsCardProps) => { return ( - {hasCostsWithinTimeframe && ( + {hasCostsWithinTimeframe ? ( + ) : ( + + There are no {product.name} costs within this timeframe for your + team's projects. + )} ); diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx index 507be28500..489c852f26 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx @@ -49,17 +49,18 @@ import { import { BarChartOptions, Duration, Entity, Maybe } from '../../types'; export type ProductInsightsChartProps = { + billingDate: string; entity: Entity; duration: Duration; }; export const ProductInsightsChart = ({ + billingDate, entity, duration, }: ProductInsightsChartProps) => { const classes = useStyles(); const layoutClasses = useLayoutStyles(); - const lastCompleteBillingDate = useLastCompleteBillingDate(); const [isOpen, setOpen] = useState(false); const [isClickable, setClickable] = useState(true); const [selectLabel, setSelected] = useState>(null); @@ -71,8 +72,8 @@ export const ProductInsightsChart = ({ const resources = entity.entities.map(resourceOf); const options: Partial = { - previousName: formatPeriod(duration, lastCompleteBillingDate, false), - currentName: formatPeriod(duration, lastCompleteBillingDate, true), + previousName: formatPeriod(duration, billingDate, false), + currentName: formatPeriod(duration, billingDate, true), }; useEffect(() => { diff --git a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx index ab5d7f3163..41b4ca90f6 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx @@ -20,7 +20,6 @@ import { Box, Typography } from '@material-ui/core'; import { InfoCard } from '@backstage/core'; import { AlertInstructionsLayout } from '../AlertInstructionsLayout'; import { ProductInsightsChart } from '../ProductInsightsCard'; -import { MockBillingDateProvider } from '../../utils/tests'; import { Alert, DEFAULT_DATE_FORMAT, @@ -172,14 +171,13 @@ export const ProjectGrowthInstructionsPage = () => { ) that has grown in cost: - - - - - + + + From here, you can dig into commit history or deployment logs to find diff --git a/plugins/cost-insights/src/index.ts b/plugins/cost-insights/src/index.ts index 1e6172d568..28bdb1a8b3 100644 --- a/plugins/cost-insights/src/index.ts +++ b/plugins/cost-insights/src/index.ts @@ -22,3 +22,4 @@ export { useCurrency } from './hooks'; export * from './types'; export * from './utils/tests'; export * from './utils/duration'; +export * from './utils/alerts'; diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md new file mode 100644 index 0000000000..dfa428b62a --- /dev/null +++ b/plugins/explore/CHANGELOG.md @@ -0,0 +1,48 @@ +# @backstage/plugin-explore + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- cab473771: This PR adds Spotify's Cost Insights Tool. Cost Insights explains costs from cloud services in an understandable way, using software terms familiar to your engineers. This tool helps you and your team make trade-offs between cost optimization efforts and your other priorities. + + Cost Insights features: + + Daily cost graph by team or billing account + Cost comparison against configurable business metrics + Insights panels for configurable cloud products your company uses + Cost alerts and recommendations + Selectable time periods for month over month, or quarter over quarter cost comparison + Conversion of cost growth into average engineer cost (configurable) to help optimization trade-off decisions + + ![plugin-cost-insights](https://user-images.githubusercontent.com/3030003/94430416-e166d380-0161-11eb-891c-9ce10187683e.gif) + + This PR adds the Cost Insights frontend React plugin with a defined CostInsightsApi. We include an example client with static data in the expected format. This API should talk with a cloud billing backend that aggregates billing data from your cloud provider. + + Fixes #688 💵 + +### Patch Changes + +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 4db68909b9..a1f71de6a2 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/core": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -33,9 +33,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md new file mode 100644 index 0000000000..08e1962f3c --- /dev/null +++ b/plugins/gcp-projects/CHANGELOG.md @@ -0,0 +1,32 @@ +# @backstage/plugin-gcp-projects + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 4c6375ebf6..812c3b1051 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcp-projects", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/core": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -31,9 +31,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md new file mode 100644 index 0000000000..a4b69a07d4 --- /dev/null +++ b/plugins/github-actions/CHANGELOG.md @@ -0,0 +1,66 @@ +# @backstage/plugin-github-actions + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- d67c529ab: Adds a widget to show recent git workflow runs to the github actions plugin. The default setting is the last 5 runs across all branches but both branch and the number of runs are configurable. +- 6d97d2d6f: The InfoCard variant `'height100'` is deprecated. Use variant `'gridItem'` instead. + + When the InfoCard is displayed as a grid item within a grid, you may want items to have the same height for all items. + Set to the `'gridItem'` variant to display the InfoCard with full height suitable for Grid: + `...` + + Changed the InfoCards in '@backstage/plugin-github-actions', '@backstage/plugin-jenkins', '@backstage/plugin-lighthouse' + to pass an optional variant to the corresponding card of the plugin. + + As a result the overview content of the EntityPage shows cards with full height suitable for Grid. + +### Patch Changes + +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [cbbd271c4] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [26e69ab1a] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [cbab5bbf8] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core-api@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/github-actions/README.md b/plugins/github-actions/README.md index 07a69cdfad..1a46022c58 100644 --- a/plugins/github-actions/README.md +++ b/plugins/github-actions/README.md @@ -26,8 +26,7 @@ TBD name: backstage description: backstage.io annotations: - github.com/project-slug: 'spotify/backstage' - + github.com/project-slug: 'backstage/backstage' spec: type: website lifecycle: production diff --git a/plugins/github-actions/examples/sample.yaml b/plugins/github-actions/examples/sample.yaml index 7d9de50463..beda3c58ed 100644 --- a/plugins/github-actions/examples/sample.yaml +++ b/plugins/github-actions/examples/sample.yaml @@ -4,8 +4,8 @@ metadata: name: backstage description: backstage.io annotations: - github.com/project-slug: 'spotify/backstage' - backstage.io/techdocs-ref: github:https://github.com/spotify/backstage.git + github.com/project-slug: 'backstage/backstage' + backstage.io/techdocs-ref: github:https://github.com/backstage/backstage.git spec: type: website lifecycle: production diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 75fed63465..8d10760843 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-actions", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/core-api": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/core-api": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -40,9 +40,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md new file mode 100644 index 0000000000..a5d5249737 --- /dev/null +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -0,0 +1,32 @@ +# @backstage/plugin-gitops-profiles + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 18486bc2b7..b61c2f6620 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gitops-profiles", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/core": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -32,9 +32,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md new file mode 100644 index 0000000000..db59e7d369 --- /dev/null +++ b/plugins/graphiql/CHANGELOG.md @@ -0,0 +1,33 @@ +# @backstage/plugin-graphiql + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- 782f3b354: add test case for Progress component +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 9e1ffd5ef1..e346133e3d 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,17 +1,17 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, - "homepage": "https://github.com/spotify/backstage/tree/master/plugins/graphiql#readme", + "homepage": "https://github.com/backstage/backstage/tree/master/plugins/graphiql#readme", "repository": { "type": "git", - "url": "https://github.com/spotify/backstage", + "url": "https://github.com/backstage/backstage", "directory": "plugins/graphiql" }, "keywords": [ @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/core": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -43,9 +43,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/graphql/CHANGELOG.md b/plugins/graphql/CHANGELOG.md new file mode 100644 index 0000000000..f9a626d543 --- /dev/null +++ b/plugins/graphql/CHANGELOG.md @@ -0,0 +1,18 @@ +# @backstage/plugin-graphql-backend + +## 0.1.2 + +### Patch Changes + +- Updated dependencies [28edd7d29] +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [8afce088a] +- Updated dependencies [7bbeb049f] + - @backstage/plugin-catalog-graphql@0.2.0 + - @backstage/backend-common@0.2.0 diff --git a/plugins/graphql/package.json b/plugins/graphql/package.json index 58b6c763c6..f62fecc648 100644 --- a/plugins/graphql/package.json +++ b/plugins/graphql/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-graphql-backend", - "version": "0.1.1-alpha.26", + "version": "0.1.2", "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.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/plugin-catalog-graphql": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/config": "^0.1.1", + "@backstage/plugin-catalog-graphql": "^0.2.0", "@graphql-modules/core": "^0.7.17", "@types/express": "^4.17.6", "apollo-server": "^2.16.1", @@ -35,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "@types/supertest": "^2.0.8", "eslint-plugin-graphql": "^4.0.0", "msw": "^0.20.5", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md new file mode 100644 index 0000000000..010471d9b2 --- /dev/null +++ b/plugins/jenkins/CHANGELOG.md @@ -0,0 +1,62 @@ +# @backstage/plugin-jenkins + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 6d97d2d6f: The InfoCard variant `'height100'` is deprecated. Use variant `'gridItem'` instead. + + When the InfoCard is displayed as a grid item within a grid, you may want items to have the same height for all items. + Set to the `'gridItem'` variant to display the InfoCard with full height suitable for Grid: + `...` + + Changed the InfoCards in '@backstage/plugin-github-actions', '@backstage/plugin-jenkins', '@backstage/plugin-lighthouse' + to pass an optional variant to the corresponding card of the plugin. + + As a result the overview content of the EntityPage shows cards with full height suitable for Grid. + +### Patch Changes + +- 1297dcb3a: Refactor to use DiscoveryApi +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 194ae71429..d0304376fd 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -36,9 +36,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx index 23f9af445c..5d5d7d9fcd 100644 --- a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React, { FC } from 'react'; -import { Box, IconButton, Link, Typography } from '@material-ui/core'; +import { Box, IconButton, Link, Typography, Tooltip } from '@material-ui/core'; import RetryIcon from '@material-ui/icons/Replay'; import GitHubIcon from '@material-ui/icons/GitHub'; import { generatePath, Link as RouterLink } from 'react-router-dom'; @@ -179,9 +179,11 @@ const generatedColumns: TableColumn[] = [ title: 'Actions', sorting: false, render: (row: Partial) => ( - - - + + + + + ), width: '10%', }, diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md new file mode 100644 index 0000000000..2834082657 --- /dev/null +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -0,0 +1,16 @@ +# @backstage/plugin-kubernetes-backend + +## 0.1.2 + +### Patch Changes + +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [8afce088a] +- Updated dependencies [7bbeb049f] + - @backstage/backend-common@0.2.0 diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 26cc842db9..7ac5f99f4c 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-backend", - "version": "0.1.1-alpha.26", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/config": "^0.1.1", "@kubernetes/client-node": "^0.12.1", "@types/express": "^4.17.6", "compression": "^1.7.4", @@ -37,7 +37,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "supertest": "^4.0.2" }, "files": [ diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md new file mode 100644 index 0000000000..0ec2c5dbaf --- /dev/null +++ b/plugins/kubernetes/CHANGELOG.md @@ -0,0 +1,42 @@ +# @backstage/plugin-kubernetes + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 + - @backstage/plugin-kubernetes-backend@0.1.2 diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 6544d751e1..29193e27ed 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,11 +20,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-kubernetes-backend": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/config": "^0.1.1", + "@backstage/core": "^0.2.0", + "@backstage/plugin-kubernetes-backend": "^0.1.2", + "@backstage/theme": "^0.2.0", "@kubernetes/client-node": "^0.12.1", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -35,9 +35,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md new file mode 100644 index 0000000000..9a68b78a92 --- /dev/null +++ b/plugins/lighthouse/CHANGELOG.md @@ -0,0 +1,65 @@ +# @backstage/plugin-lighthouse + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 6d97d2d6f: The InfoCard variant `'height100'` is deprecated. Use variant `'gridItem'` instead. + + When the InfoCard is displayed as a grid item within a grid, you may want items to have the same height for all items. + Set to the `'gridItem'` variant to display the InfoCard with full height suitable for Grid: + `...` + + Changed the InfoCards in '@backstage/plugin-github-actions', '@backstage/plugin-jenkins', '@backstage/plugin-lighthouse' + to pass an optional variant to the corresponding card of the plugin. + + As a result the overview content of the EntityPage shows cards with full height suitable for Grid. + +### Patch Changes + +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [cbbd271c4] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [26e69ab1a] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [cbab5bbf8] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core-api@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/lighthouse/README.md b/plugins/lighthouse/README.md index 19244f3cf0..cdcc2fe2c4 100644 --- a/plugins/lighthouse/README.md +++ b/plugins/lighthouse/README.md @@ -23,7 +23,7 @@ _It's likely you will need to enable CORS when running lighthouse-audit-service. with the environment variable `LAS_CORS` set to `true`._ When you have an instance running that Backstage can hook into, make sure to export the plugin in -your app's [`plugins.ts`](https://github.com/spotify/backstage/blob/master/packages/app/src/plugins.ts) +your app's [`plugins.ts`](https://github.com/backstage/backstage/blob/master/packages/app/src/plugins.ts) to enable the plugin: ```js @@ -32,7 +32,7 @@ export LighthousePlugin; ``` Then, you need to use the `lighthouseApiRef` exported from the plugin to initialize the Rest API in -your [`apis.ts`](https://github.com/spotify/backstage/blob/master/packages/app/src/apis.ts). +your [`apis.ts`](https://github.com/backstage/backstage/blob/master/packages/app/src/apis.ts). ```js import { ApiHolder, ApiRegistry } from '@backstage/core'; @@ -51,7 +51,7 @@ export const apis = (config: ConfigApi) => { } ``` -Then configure the lighthouse service url in your [`app-config.yaml`](https://github.com/spotify/backstage/blob/master/app-config.yaml). +Then configure the lighthouse service url in your [`app-config.yaml`](https://github.com/backstage/backstage/blob/master/app-config.yaml). ```yaml lighthouse: diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 8285d29635..27b6a21066 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-lighthouse", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,12 +21,12 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/core-api": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/config": "^0.1.1", + "@backstage/core": "^0.2.0", + "@backstage/core-api": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -39,9 +39,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/lighthouse/src/components/Intro/index.tsx b/plugins/lighthouse/src/components/Intro/index.tsx index ee5d5d66af..dc2a8ea283 100644 --- a/plugins/lighthouse/src/components/Intro/index.tsx +++ b/plugins/lighthouse/src/components/Intro/index.tsx @@ -43,7 +43,7 @@ _It's likely you will need to enable CORS when running lighthouse-audit-service. with the environment variable \`LAS_CORS\` set to \`true\`._ When you have an instance running that Backstage can hook into, make sure to export the plugin in -your app's [\`plugins.ts\`](https://github.com/spotify/backstage/blob/master/packages/app/src/plugins.ts) +your app's [\`plugins.ts\`](https://github.com/backstage/backstage/blob/master/packages/app/src/plugins.ts) to enable the plugin: \`\`\`js @@ -52,7 +52,7 @@ export LighthousePlugin; \`\`\` Then, you need to use the \`lighthouseApiRef\` exported from the plugin to initialize the Rest API in -your [\`apis.ts\`](https://github.com/spotify/backstage/blob/master/packages/app/src/apis.ts). +your [\`apis.ts\`](https://github.com/backstage/backstage/blob/master/packages/app/src/apis.ts). \`\`\`js import { ApiHolder, ApiRegistry } from '@backstage/core'; diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md new file mode 100644 index 0000000000..d007328180 --- /dev/null +++ b/plugins/newrelic/CHANGELOG.md @@ -0,0 +1,53 @@ +# @backstage/plugin-newrelic + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 4512b9967: The New Relic plugin now uses the Backstage proxy to communicate with New Relic's API. + + Please update your `app-config.yaml` as follows: + + ```yaml + # Old Config + newrelic: + api: + baseUrl: 'https://api.newrelic.com/v2' + key: NEW_RELIC_REST_API_KEY + ``` + + ```yaml + # New Config + proxy: + '/newrelic/apm/api': + target: https://api.newrelic.com/v2 + headers: + X-Api-Key: + $env: NEW_RELIC_REST_API_KEY + ``` + +### Patch Changes + +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index b9a12cc648..e7d000abc5 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/core": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -31,9 +31,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md new file mode 100644 index 0000000000..dcbe7eb7e8 --- /dev/null +++ b/plugins/proxy-backend/CHANGELOG.md @@ -0,0 +1,42 @@ +# @backstage/plugin-proxy-backend + +## 0.2.0 + +### Minor Changes + +- 5249594c5: Add service discovery interface and implement for single host deployments + + Fixes #1847, #2596 + + Went with an interface similar to the frontend DiscoveryApi, since it's dead simple but still provides a lot of flexibility in the implementation. + + Also ended up with two different methods, one for internal endpoint discovery and one for external. The two use-cases are explained a bit more in the docs, but basically it's service-to-service vs callback URLs. + + This did get me thinking about uniqueness and that we're heading towards a global namespace for backend plugin IDs. That's probably fine, but if we're happy with that we should leverage it a bit more to simplify the backend setup. For example we'd have each plugin provide its own ID and not manually mount on paths in the backend. + + Draft until we're happy with the implementation, then I can add more docs and changelog entry. Also didn't go on a thorough hunt for places where discovery can be used, but I don't think there are many since it's been pretty awkward to do service-to-service communication. + +- 9226c2aaa: Limit the http headers that are forwarded from the request to a safe set of defaults. + A user can configure additional headers that should be forwarded if the specific applications needs that. + + ```yaml + proxy: + '/my-api': + target: 'https://my-api.com/get' + allowedHeaders: + # We need to forward the Authorization header that was provided by the caller + - Authorization + ``` + +### Patch Changes + +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [8afce088a] +- Updated dependencies [7bbeb049f] + - @backstage/backend-common@0.2.0 diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index fcb68dcd78..f147e400e4 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-proxy-backend", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -19,8 +19,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/config": "^0.1.1", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^3.0.3", @@ -33,7 +33,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/register-component/CHANGELOG.md b/plugins/register-component/CHANGELOG.md new file mode 100644 index 0000000000..cb1a24d131 --- /dev/null +++ b/plugins/register-component/CHANGELOG.md @@ -0,0 +1,55 @@ +# @backstage/plugin-register-component + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 2ebcfac8d: Add a validate button to the register-component page + + This allows the user to validate his location before adding it. + +### Patch Changes + +- 8b9c8196f: Locations registered through the catalog client now default to the 'url' type. The type selection dropdown in the register-component form has been removed. +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json index 5c3f985b4d..095469f6b4 100644 --- a/plugins/register-component/package.json +++ b/plugins/register-component/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-register-component", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -36,9 +36,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md new file mode 100644 index 0000000000..21f9ce8090 --- /dev/null +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -0,0 +1,16 @@ +# @backstage/plugin-rollbar-backend + +## 0.1.2 + +### Patch Changes + +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [8afce088a] +- Updated dependencies [7bbeb049f] + - @backstage/backend-common@0.2.0 diff --git a/plugins/rollbar-backend/README.md b/plugins/rollbar-backend/README.md index f441efa416..8f13eb5f26 100644 --- a/plugins/rollbar-backend/README.md +++ b/plugins/rollbar-backend/README.md @@ -8,7 +8,7 @@ The following values are read from the configuration file. ```yaml rollbar: - organization: spotify + organization: organization-name accountToken: $env: ROLLBAR_ACCOUNT_TOKEN ``` @@ -18,5 +18,5 @@ access account token._ ## Links -- [Frontend part of the plugin](https://github.com/spotify/backstage/tree/master/plugins/rollbar) +- [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/rollbar) - [The Backstage homepage](https://backstage.io) diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index cb553d859b..b1764f238f 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar-backend", - "version": "0.1.1-alpha.26", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/config": "^0.1.1", "@types/express": "^4.17.6", "axios": "^0.20.0", "camelcase-keys": "^6.2.2", @@ -37,7 +37,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "@types/supertest": "^2.0.8", "supertest": "^4.0.2" }, diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md new file mode 100644 index 0000000000..ee25fb10d9 --- /dev/null +++ b/plugins/rollbar/CHANGELOG.md @@ -0,0 +1,51 @@ +# @backstage/plugin-rollbar + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/rollbar/README.md b/plugins/rollbar/README.md index 98f2272508..a232462dde 100644 --- a/plugins/rollbar/README.md +++ b/plugins/rollbar/README.md @@ -4,7 +4,7 @@ Website: [https://rollbar.com/](https://rollbar.com/) ## Setup -1. Configure the [rollbar backend plugin](https://github.com/spotify/backstage/tree/master/plugins/rollbar-backend/README.md) +1. Configure the [rollbar backend plugin](https://github.com/backstage/backstage/tree/master/plugins/rollbar-backend/README.md) 2. If you have standalone app (you didn't clone this repo), then do @@ -53,7 +53,7 @@ const ServiceEntityPage = ({ entity }: { entity: Entity }) => ( ```yaml # app.config.yaml rollbar: - organization: spotify + organization: organization-name accountToken: $env: ROLLBAR_ACCOUNT_TOKEN ``` @@ -83,5 +83,5 @@ metadata: ## Links -- [Backend part of the plugin](https://github.com/spotify/backstage/tree/master/plugins/rollbar-backend) +- [Backend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/rollbar-backend) - [The Backstage homepage](https://backstage.io) diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 27421cfd4d..03e393aa1b 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -37,9 +37,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/react-hooks": "^3.3.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md new file mode 100644 index 0000000000..78a6d9527b --- /dev/null +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -0,0 +1,46 @@ +# @backstage/plugin-scaffolder-backend + +## 0.2.0 + +### Minor Changes + +- 3e254503d: Add Azure DevOps support to the scaffolder backend + + This adds support for Azure DevOps to the scaffolder (preparer & publisher). I thought I should get this in there now since #2426 has been merged. I had a previous PR with only the preparer but I closed that in favor of this one. + + I stayed with the 'azure/api' structure but I guess we should try and go the same way as with GitHub here #2501 + +### Patch Changes + +- 0c370c979: Update SSR template to pass CI +- 991a950e0: Added .fromConfig static factories for Preparers and Publishers + read integrations config to support url location types +- c926765a2: Allow templates to be located on non-default branch +- 6840a68df: Add authentication token to Scaffolder GitHub Preparer +- 1c8c43756: The new `scaffolder.github.baseUrl` config property allows to specify a custom base url for GitHub enterprise instances +- 5e4551e3a: Added support for configuring the working directory of the Scaffolder: + + ```yaml + backend: + workingDirectory: /some-dir # Use this to configure a working directory for the scaffolder, defaults to the OS temp-dir + ``` + +- e3d063ffa: Introduce PreparerOptions for PreparerBase +- Updated dependencies [3a4236570] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [a768a07fb] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [5adfc005e] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [fa56f4615] +- Updated dependencies [8afce088a] +- Updated dependencies [b3d57961c] +- Updated dependencies [7bbeb049f] + - @backstage/catalog-model@0.2.0 + - @backstage/backend-common@0.2.0 diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 1c85adc23a..ac30e23828 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,11 +20,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", - "@gitbeaker/core": "^23.5.0", - "@gitbeaker/node": "^23.5.0", + "@backstage/backend-common": "^0.2.0", + "@backstage/catalog-model": "^0.2.0", + "@backstage/config": "^0.1.1", + "@gitbeaker/core": "^25.2.0", + "@gitbeaker/node": "^25.2.0", "@octokit/rest": "^18.0.0", "@types/dockerode": "^2.5.32", "@types/express": "^4.17.6", @@ -44,10 +44,11 @@ "nodegit": "0.27.0", "uuid": "^8.2.0", "winston": "^3.2.1", - "yaml": "^1.10.0" + "yaml": "^1.10.0", + "cross-fetch": "^3.0.6" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "@octokit/types": "^5.4.1", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder-backend/sample-templates/all-templates.yaml b/plugins/scaffolder-backend/sample-templates/all-templates.yaml index 1eb619a072..6866543ab0 100644 --- a/plugins/scaffolder-backend/sample-templates/all-templates.yaml +++ b/plugins/scaffolder-backend/sample-templates/all-templates.yaml @@ -6,8 +6,8 @@ metadata: spec: type: github targets: - - https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml - - https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml - - https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml + - https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml + - https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml + - https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml - https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml - - https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml + - https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml diff --git a/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml b/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml index 31b57135ad..36404f088c 100644 --- a/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml +++ b/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml @@ -9,13 +9,13 @@ metadata: - techdocs - mkdocs spec: - owner: spotify/techdocs-core + owner: backstage/techdocs-core templater: cookiecutter type: documentation path: '.' - + schema: - required: + required: - component_id - description properties: @@ -27,4 +27,3 @@ spec: title: Description type: string description: Help others understand what these docs are about. - diff --git a/plugins/scaffolder-backend/src/index.ts b/plugins/scaffolder-backend/src/index.ts index c461bfede6..28e6a2b24c 100644 --- a/plugins/scaffolder-backend/src/index.ts +++ b/plugins/scaffolder-backend/src/index.ts @@ -16,3 +16,4 @@ export * from './scaffolder'; export * from './service/router'; +export * from './lib/catalog'; diff --git a/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts b/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts new file mode 100644 index 0000000000..4541f03a4a --- /dev/null +++ b/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts @@ -0,0 +1,72 @@ +/* + * 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. + */ + +import fetch from 'cross-fetch'; +import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; +import { + ConflictError, + NotFoundError, + PluginEndpointDiscovery, +} from '@backstage/backend-common'; + +/** + * A catalog client tailored for reading out entity data from the catalog. + */ +export class CatalogEntityClient { + private readonly discovery: PluginEndpointDiscovery; + + constructor(options: { discovery: PluginEndpointDiscovery }) { + this.discovery = options.discovery; + } + + /** + * Looks up a single template using a template name. + * + * Throws a NotFoundError or ConflictError if 0 or multiple templates are found. + */ + async findTemplate(templateName: string): Promise { + const conditions = [ + 'kind=template', + `metadata.name=${encodeURIComponent(templateName)}`, + ]; + + const baseUrl = await this.discovery.getBaseUrl('catalog'); + const response = await fetch( + `${baseUrl}/entities?filter=${conditions.join(',')}`, + ); + + if (!response.ok) { + const text = await response.text(); + throw new Error( + `Request failed with ${response.status} ${response.statusText}, ${text}`, + ); + } + + const templates: TemplateEntityV1alpha1[] = await response.json(); + + if (templates.length !== 1) { + if (templates.length > 1) { + throw new ConflictError( + 'Templates lookup resulted in multiple matches', + ); + } else { + throw new NotFoundError('Template not found'); + } + } + + return templates[0]; + } +} diff --git a/plugins/scaffolder-backend/src/lib/catalog/index.ts b/plugins/scaffolder-backend/src/lib/catalog/index.ts new file mode 100644 index 0000000000..a8de546e00 --- /dev/null +++ b/plugins/scaffolder-backend/src/lib/catalog/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ +export { CatalogEntityClient } from './CatalogEntityClient'; diff --git a/plugins/scaffolder-backend/src/scaffolder/jobs/processor.test.ts b/plugins/scaffolder-backend/src/scaffolder/jobs/processor.test.ts index 8a875e4e2b..d23db937bb 100644 --- a/plugins/scaffolder-backend/src/scaffolder/jobs/processor.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/jobs/processor.test.ts @@ -61,7 +61,7 @@ describe('JobProcessor', () => { const mockValues: RequiredTemplateValues = { owner: 'blobby', - storePath: 'spotify/mock-repo', + storePath: 'backstage/mock-repo', }; describe('create', () => { diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.test.ts index 0aaef2633d..7c2d7e0a47 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.test.ts @@ -24,7 +24,7 @@ describe('Preparers', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'file:/Users/bingo/spotify/backstage/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml', + 'file:/Users/bingo/backstage/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml', }, name: 'react-ssr-template', title: 'React SSR Template', 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 106a448d7c..568c95a073 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts @@ -51,12 +51,12 @@ describe('CookieCutter Templater', () => { return await fs.promises.mkdtemp(path.join(tempDir, 'temp')); }; - it('should write a cookiecutter.json file with the values from the entitiy', async () => { + it('should write a cookiecutter.json file with the values from the entity', async () => { const tempdir = await mkTemp(); const values = { owner: 'blobby', - storePath: 'spotify/end-repo', + storePath: 'backstage/end-repo', description: 'description', component_id: 'newthing', }; @@ -78,7 +78,7 @@ describe('CookieCutter Templater', () => { const values = { owner: 'blobby', - storePath: 'spotify/end-repo', + storePath: 'backstage/end-repo', component_id: 'something', }; @@ -96,7 +96,7 @@ describe('CookieCutter Templater', () => { const values = { owner: 'blobby', - storePath: 'spotify/end-repo', + storePath: 'backstage/end-repo', }; await expect( @@ -109,7 +109,7 @@ describe('CookieCutter Templater', () => { const values = { owner: 'blobby', - storePath: 'spotify/end-repo', + storePath: 'backstage/end-repo', component_id: 'newthing', }; @@ -137,7 +137,7 @@ describe('CookieCutter Templater', () => { const values = { owner: 'blobby', - storePath: 'spotify/end-repo', + storePath: 'backstage/end-repo', component_id: 'newthing', }; @@ -157,7 +157,7 @@ describe('CookieCutter Templater', () => { const values = { owner: 'blobby', - storePath: 'spotify/end-repo', + storePath: 'backstage/end-repo', component_id: 'newthing', }; @@ -203,7 +203,7 @@ describe('CookieCutter Templater', () => { const values = { owner: 'blobby', - storePath: 'spotify/end-repo', + storePath: 'backstage/end-repo', component_id: 'newthing', }; @@ -243,7 +243,7 @@ describe('CookieCutter Templater', () => { directory: tempdir, values: { owner: 'blobby', - storePath: 'spotify/end-repo', + storePath: 'backstage/end-repo', }, logStream: stream, dockerClient: mockDocker, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.test.ts index 1c4fe90207..9ef20b7740 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.test.ts @@ -24,7 +24,7 @@ describe('Templaters', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'file:/Users/bingo/spotify/backstage/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml', + 'file:/Users/bingo/backstage/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml', }, name: 'react-ssr-template', title: 'React SSR Template', diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index fae7ee8beb..c2b60a2040 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -35,6 +35,10 @@ import Docker from 'dockerode'; jest.mock('dockerode'); +const generateEntityClient: any = (template: any) => ({ + findTemplate: () => Promise.resolve(template), +}); + describe('createRouter - working directory', () => { const mockPrepare = jest.fn(); const mockPreparers = new Preparers(); @@ -74,6 +78,8 @@ describe('createRouter - working directory', () => { }, }; + const mockedEntityClient = generateEntityClient(template); + it('should throw an error when working directory does not exist or is not writable', async () => { mockAccess.mockImplementation(() => { throw new Error('access error'); @@ -87,6 +93,7 @@ describe('createRouter - working directory', () => { publishers: new Publishers(), config: ConfigReader.fromConfigs([workDirConfig('/path')]), dockerClient: new Docker(), + entityClient: mockedEntityClient, }), ).rejects.toThrow('access error'); }); @@ -99,11 +106,12 @@ describe('createRouter - working directory', () => { publishers: new Publishers(), config: ConfigReader.fromConfigs([workDirConfig('/path')]), dockerClient: new Docker(), + entityClient: mockedEntityClient, }); const app = express().use(router); await request(app).post('/v1/jobs').send({ - template, + templateName: '', values: {}, }); @@ -121,11 +129,12 @@ describe('createRouter - working directory', () => { publishers: new Publishers(), config: ConfigReader.fromConfigs([]), dockerClient: new Docker(), + entityClient: mockedEntityClient, }); const app = express().use(router); await request(app).post('/v1/jobs').send({ - template, + templateName: '', values: {}, }); @@ -137,6 +146,43 @@ describe('createRouter - working directory', () => { describe('createRouter', () => { let app: express.Express; + const template = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Template', + metadata: { + description: 'Create a new CRA website project', + name: 'create-react-app-template', + tags: ['experimental', 'react', 'cra'], + title: 'Create React App Template', + }, + spec: { + owner: 'web@example.com', + path: '.', + schema: { + properties: { + component_id: { + description: 'Unique name of the component', + title: 'Name', + type: 'string', + }, + description: { + description: 'Description of the component', + title: 'Description', + type: 'string', + }, + use_typescript: { + default: true, + description: 'Include typescript', + title: 'Use Typescript', + type: 'boolean', + }, + }, + required: ['component_id', 'use_typescript'], + }, + templater: 'cra', + type: 'website', + }, + }; beforeAll(async () => { const router = await createRouter({ @@ -146,6 +192,7 @@ describe('createRouter', () => { publishers: new Publishers(), config: ConfigReader.fromConfigs([]), dockerClient: new Docker(), + entityClient: generateEntityClient(template), }); app = express().use(router); }); @@ -155,47 +202,9 @@ describe('createRouter', () => { }); describe('POST /v1/jobs', () => { - const template = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Template', - metadata: { - description: 'Create a new CRA website project', - name: 'create-react-app-template', - tags: ['experimental', 'react', 'cra'], - title: 'Create React App Template', - }, - spec: { - owner: 'web@example.com', - path: '.', - schema: { - properties: { - component_id: { - description: 'Unique name of the component', - title: 'Name', - type: 'string', - }, - description: { - description: 'Description of the component', - title: 'Description', - type: 'string', - }, - use_typescript: { - default: true, - description: 'Include typescript', - title: 'Use Typescript', - type: 'boolean', - }, - }, - required: ['component_id', 'use_typescript'], - }, - templater: 'cra', - type: 'website', - }, - }; - it('rejects template values which do not match the template schema definition', async () => { const response = await request(app).post('/v1/jobs').send({ - template, + templateName: '', values: {}, }); diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index fb40489622..2dc6a794fb 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { Config, JsonValue } from '@backstage/config'; import fs from 'fs-extra'; import Docker from 'dockerode'; @@ -29,6 +28,7 @@ import { TemplaterBuilder, PublisherBuilder, } from '../scaffolder'; +import { CatalogEntityClient } from '../lib/catalog'; import { validate, ValidatorResult } from 'jsonschema'; export interface RouterOptions { @@ -39,6 +39,7 @@ export interface RouterOptions { logger: Logger; config: Config; dockerClient: Docker; + entityClient: CatalogEntityClient; } export async function createRouter( @@ -54,6 +55,7 @@ export async function createRouter( logger: parentLogger, config, dockerClient, + entityClient, } = options; const logger = parentLogger.child({ plugin: 'scaffolder' }); @@ -104,14 +106,17 @@ export async function createRouter( }); }) .post('/v1/jobs', async (req, res) => { - const template: TemplateEntityV1alpha1 = req.body.template; + const templateName: string = req.body.templateName; const values: RequiredTemplateValues & Record = req.body.values; + const template = await entityClient.findTemplate(templateName); + const validationResult: ValidatorResult = validate( values, template.spec.schema, ); + if (!validationResult.valid) { res.status(400).json({ errors: validationResult.errors }); return; diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md new file mode 100644 index 0000000000..9c09366174 --- /dev/null +++ b/plugins/scaffolder/CHANGELOG.md @@ -0,0 +1,67 @@ +# @backstage/plugin-scaffolder + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- fb74f1db6: Make title meaningful after component creation + + Fixes #2458. + + After the change, the UX should look like this: + + ### If the component creation was successful: + + ![successfully-created-component](https://user-images.githubusercontent.com/33940798/94339294-8bd1e000-0016-11eb-885b-7936fcc23b63.gif) + + ### If the component creation failed: + + ![failed-to-create-component](https://user-images.githubusercontent.com/33940798/94339296-90969400-0016-11eb-9a74-ce16b3dd8d88.gif) + +- c5ef12926: fix the accordion details design when job stage fail +- 1c8c43756: The new `scaffolder.github.baseUrl` config property allows to specify a custom base url for GitHub enterprise instances +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/scaffolder/README.md b/plugins/scaffolder/README.md index a356cb8ec9..05a68dafdd 100644 --- a/plugins/scaffolder/README.md +++ b/plugins/scaffolder/README.md @@ -6,5 +6,5 @@ This is the frontend part of the default scaffolder plugin. ## Links -- [Backend part of the plugin](https://github.com/spotify/backstage/tree/master/plugins/scaffolder-backend) +- [Backend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/scaffolder-backend) - [The Backstage homepage](https://backstage.io) diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 751f4075b2..738734ceb7 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -41,9 +41,9 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index f58c8e68d1..ca52418e92 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -15,7 +15,6 @@ */ import { createApiRef, DiscoveryApi } from '@backstage/core'; -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; export const scaffolderApiRef = createApiRef({ id: 'plugin.scaffolder.service', @@ -33,20 +32,17 @@ export class ScaffolderApi { * Executes the scaffolding of a component, given a template and its * parameter values. * - * @param template Template entity for the scaffolder to use. New project is going to be created out of this template. + * @param templateName Template name for the scaffolder to use. New project is going to be created out of this template. * @param values Parameters for the template, e.g. name, description */ - async scaffold( - template: TemplateEntityV1alpha1, - values: Record, - ) { + async scaffold(templateName: string, values: Record) { const url = `${await this.discoveryApi.getBaseUrl('scaffolder')}/v1/jobs`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ template, values: { ...values } }), + body: JSON.stringify({ templateName, values: { ...values } }), }); if (response.status !== 201) { diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index f99df26264..cb6b38903e 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -96,7 +96,7 @@ export const TemplatePage = () => { const handleCreate = async () => { try { - const job = await scaffolderApi.scaffold(template!, formState); + const job = await scaffolderApi.scaffold(templateName, formState); setJobId(job); } catch (e) { errorApi.post(e); diff --git a/plugins/sentry-backend/CHANGELOG.md b/plugins/sentry-backend/CHANGELOG.md new file mode 100644 index 0000000000..93361e05ff --- /dev/null +++ b/plugins/sentry-backend/CHANGELOG.md @@ -0,0 +1,16 @@ +# @backstage/plugin-sentry-backend + +## 0.1.2 + +### Patch Changes + +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [8afce088a] +- Updated dependencies [7bbeb049f] + - @backstage/backend-common@0.2.0 diff --git a/plugins/sentry-backend/package.json b/plugins/sentry-backend/package.json index b51eb1509a..a1e1531b8b 100644 --- a/plugins/sentry-backend/package.json +++ b/plugins/sentry-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sentry-backend", - "version": "0.1.1-alpha.26", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,7 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", "@types/express": "^4.17.6", "axios": "^0.20.0", "compression": "^1.7.4", @@ -34,7 +34,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26" + "@backstage/cli": "^0.2.0" }, "files": [ "dist" diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md new file mode 100644 index 0000000000..06380c39d9 --- /dev/null +++ b/plugins/sentry/CHANGELOG.md @@ -0,0 +1,41 @@ +# @backstage/plugin-sentry + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 4d9cd59bc3..2ede8fd709 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sentry", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,9 +21,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -36,9 +36,9 @@ "timeago.js": "^4.0.2" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md new file mode 100644 index 0000000000..62f88596e7 --- /dev/null +++ b/plugins/sonarqube/CHANGELOG.md @@ -0,0 +1,37 @@ +# @backstage/plugin-sonarqube + +## 0.1.2 + +### Patch Changes + +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/sonarqube/README.md b/plugins/sonarqube/README.md index 3d3c1f725b..af18017359 100644 --- a/plugins/sonarqube/README.md +++ b/plugins/sonarqube/README.md @@ -90,6 +90,6 @@ metadata: sonarqube.org/project-key: YOUR_PROJECT_KEY spec: type: library - owner: Spotify + owner: CNCF lifecycle: experimental ``` diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index fc14805c06..bc41213ad8 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube", - "version": "0.1.1-alpha.26", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,9 +21,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -35,9 +35,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/sonarqube/src/api/index.test.ts b/plugins/sonarqube/src/api/index.test.ts index 272d021493..2d96fc2135 100644 --- a/plugins/sonarqube/src/api/index.test.ts +++ b/plugins/sonarqube/src/api/index.test.ts @@ -114,22 +114,29 @@ describe('SonarQubeApi', () => { const client = new SonarQubeApi({ discoveryApi }); const summary = await client.getFindingSummary('our-service'); - - expect(summary).toEqual({ - lastAnalysis: '2020-01-01T00:00:00Z', - metrics: { - alert_status: 'OK', - bugs: '2', - reliability_rating: '3.0', - vulnerabilities: '4', - security_rating: '1.0', - code_smells: '100', - sqale_rating: '2.0', - coverage: '55.5', - duplicated_lines_density: '1.0', - }, - projectUrl: 'https://sonarcloud.io/dashboard?id=our-service', - } as FindingSummary); + expect(summary).toEqual( + expect.objectContaining({ + lastAnalysis: '2020-01-01T00:00:00Z', + metrics: { + alert_status: 'OK', + bugs: '2', + reliability_rating: '3.0', + vulnerabilities: '4', + security_rating: '1.0', + code_smells: '100', + sqale_rating: '2.0', + coverage: '55.5', + duplicated_lines_density: '1.0', + }, + projectUrl: 'https://sonarcloud.io/dashboard?id=our-service', + }), + ); + expect(summary?.getIssuesUrl('CODE_SMELL')).toEqual( + 'https://sonarcloud.io/project/issues?id=our-service&types=CODE_SMELL&resolved=false', + ); + expect(summary?.getComponentMeasuresUrl('COVERAGE')).toEqual( + 'https://sonarcloud.io/component_measures?id=our-service&metric=coverage&resolved=false&view=list', + ); }); it('should report finding summary (custom baseUrl)', async () => { @@ -142,20 +149,28 @@ describe('SonarQubeApi', () => { const summary = await client.getFindingSummary('our-service'); - expect(summary).toEqual({ - lastAnalysis: '2020-01-01T00:00:00Z', - metrics: { - alert_status: 'OK', - bugs: '2', - reliability_rating: '3.0', - vulnerabilities: '4', - security_rating: '1.0', - code_smells: '100', - sqale_rating: '2.0', - coverage: '55.5', - duplicated_lines_density: '1.0', - }, - projectUrl: 'http://a.instance.local/dashboard?id=our-service', - } as FindingSummary); + expect(summary).toEqual( + expect.objectContaining({ + lastAnalysis: '2020-01-01T00:00:00Z', + metrics: { + alert_status: 'OK', + bugs: '2', + reliability_rating: '3.0', + vulnerabilities: '4', + security_rating: '1.0', + code_smells: '100', + sqale_rating: '2.0', + coverage: '55.5', + duplicated_lines_density: '1.0', + }, + projectUrl: 'http://a.instance.local/dashboard?id=our-service', + }) as FindingSummary, + ); + expect(summary?.getIssuesUrl('CODE_SMELL')).toEqual( + 'http://a.instance.local/project/issues?id=our-service&types=CODE_SMELL&resolved=false', + ); + expect(summary?.getComponentMeasuresUrl('COVERAGE')).toEqual( + 'http://a.instance.local/component_measures?id=our-service&metric=coverage&resolved=false&view=list', + ); }); }); diff --git a/plugins/sonarqube/src/api/index.ts b/plugins/sonarqube/src/api/index.ts index 01f6f74fe3..f2c616f53c 100644 --- a/plugins/sonarqube/src/api/index.ts +++ b/plugins/sonarqube/src/api/index.ts @@ -16,7 +16,12 @@ import { createApiRef, DiscoveryApi } from '@backstage/core'; import fetch from 'cross-fetch'; -import { ComponentWrapper, MeasuresWrapper, MetricKey } from './types'; +import { + ComponentWrapper, + MeasuresWrapper, + MetricKey, + SonarUrlProcessorFunc, +} from './types'; /** * Define a type to make sure that all metrics are used @@ -29,6 +34,8 @@ export interface FindingSummary { lastAnalysis: string; metrics: Metrics; projectUrl: string; + getIssuesUrl: SonarUrlProcessorFunc; + getComponentMeasuresUrl: SonarUrlProcessorFunc; } export const sonarQubeApiRef = createApiRef({ @@ -105,6 +112,14 @@ export class SonarQubeApi { lastAnalysis: component.component.analysisDate, metrics, projectUrl: `${this.baseUrl}dashboard?id=${componentKey}`, + getIssuesUrl: identifier => + `${ + this.baseUrl + }project/issues?id=${componentKey}&types=${identifier.toUpperCase()}&resolved=false`, + getComponentMeasuresUrl: (identifier: string) => + `${ + this.baseUrl + }component_measures?id=${componentKey}&metric=${identifier.toLowerCase()}&resolved=false&view=list`, }; } } diff --git a/plugins/sonarqube/src/api/types.ts b/plugins/sonarqube/src/api/types.ts index 17539070cb..fc99b2d87d 100644 --- a/plugins/sonarqube/src/api/types.ts +++ b/plugins/sonarqube/src/api/types.ts @@ -53,3 +53,5 @@ export interface Measure { value: string; component: string; } + +export type SonarUrlProcessorFunc = (identifier: string) => string; diff --git a/plugins/sonarqube/src/components/SonarQubeCard/RatingCard.tsx b/plugins/sonarqube/src/components/SonarQubeCard/RatingCard.tsx index cd678b7366..6a94f7e8f4 100644 --- a/plugins/sonarqube/src/components/SonarQubeCard/RatingCard.tsx +++ b/plugins/sonarqube/src/components/SonarQubeCard/RatingCard.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Grid, Typography } from '@material-ui/core'; +import { Grid, Typography, Link } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import React, { ReactNode } from 'react'; @@ -50,29 +50,33 @@ export const RatingCard = ({ rightSlot, title, titleIcon, + link, }: { leftSlot: ReactNode; rightSlot: ReactNode; title: string; titleIcon?: ReactNode; + link: string; }) => { const classes = useStyles(); return ( - - - - {leftSlot} + + + + + {leftSlot} + + + {rightSlot} + - - {rightSlot} + + + {titleIcon} {title} + - - - {titleIcon} {title} - - - + ); }; diff --git a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx index 8e6cc817a1..a68a022717 100644 --- a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx +++ b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx @@ -51,6 +51,9 @@ const useStyles = makeStyles(theme => ({ margin: 0, backgroundColor: theme.palette.success.main, }, + badgeUnknown: { + backgroundColor: theme.palette.grey[500], + }, header: { padding: theme.spacing(2, 2, 2, 2.5), }, @@ -104,17 +107,20 @@ export const SonarQubeCard = ({ } : undefined; - const gatePassed = value && value.metrics.alert_status === 'OK'; - const classes = useStyles(); + let gateLabel = 'Not computed'; + let gateColor = classes.badgeUnknown; + + if (value?.metrics.alert_status) { + const gatePassed = value.metrics.alert_status === 'OK'; + gateLabel = gatePassed ? 'Gate passed' : 'Gate failed'; + gateColor = gatePassed ? classes.badgeSuccess : classes.badgeError; + } const qualityBadge = !loading && value && ( ); @@ -181,29 +187,34 @@ export const SonarQubeCard = ({ } title="Bugs" + link={value.getIssuesUrl('BUG')} leftSlot={} rightSlot={} /> } title="Vulnerabilities" + link={value.getIssuesUrl('VULNERABILITY')} leftSlot={} rightSlot={} /> } title="Code Smells" + link={value.getIssuesUrl('CODE_SMELL')} leftSlot={} rightSlot={} />
} rightSlot={} /> } rightSlot={ diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md new file mode 100644 index 0000000000..7f9f11a702 --- /dev/null +++ b/plugins/tech-radar/CHANGELOG.md @@ -0,0 +1,35 @@ +# @backstage/plugin-tech-radar + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- 782f3b354: add test case for Progress component +- 02c60b5f8: fix the horizontal scrolling issue in the RadarPage component +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 + - @backstage/test-utils@0.1.2 diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index f27f4c1784..875d6d161b 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-radar", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,9 +21,9 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/core": "^0.2.0", + "@backstage/test-utils": "^0.1.2", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -35,9 +35,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/tech-radar/src/components/RadarFooter/RadarFooter.tsx b/plugins/tech-radar/src/components/RadarFooter/RadarFooter.tsx index ced1ab8054..219db714af 100644 --- a/plugins/tech-radar/src/components/RadarFooter/RadarFooter.tsx +++ b/plugins/tech-radar/src/components/RadarFooter/RadarFooter.tsx @@ -15,19 +15,19 @@ */ import React from 'react'; -import { makeStyles, Theme } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core'; export type Props = { x: number; y: number; }; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles(theme => ({ text: { pointerEvents: 'none', userSelect: 'none', fontSize: '10px', - fill: '#000', + fill: theme.palette.text.secondary, }, })); diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md new file mode 100644 index 0000000000..4191361a33 --- /dev/null +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -0,0 +1,94 @@ +# @backstage/plugin-techdocs-backend + +## 0.2.0 + +### Minor Changes + +- 6d29605db: Change the default backend plugin mount point to /api +- 5249594c5: Add service discovery interface and implement for single host deployments + + Fixes #1847, #2596 + + Went with an interface similar to the frontend DiscoveryApi, since it's dead simple but still provides a lot of flexibility in the implementation. + + Also ended up with two different methods, one for internal endpoint discovery and one for external. The two use-cases are explained a bit more in the docs, but basically it's service-to-service vs callback URLs. + + This did get me thinking about uniqueness and that we're heading towards a global namespace for backend plugin IDs. That's probably fine, but if we're happy with that we should leverage it a bit more to simplify the backend setup. For example we'd have each plugin provide its own ID and not manually mount on paths in the backend. + + Draft until we're happy with the implementation, then I can add more docs and changelog entry. Also didn't go on a thorough hunt for places where discovery can be used, but I don't think there are many since it's been pretty awkward to do service-to-service communication. + +- 5a920c6e4: Updated naming of environment variables. New pattern [NAME]\_TOKEN for Github, Gitlab, Azure & Github enterprise access tokens. + + ### Detail: + + - Previously we have to export same token for both, catalog & scaffolder + + ```bash + export GITHUB_ACCESS_TOKEN=foo + export GITHUB_PRIVATE_TOKEN=foo + ``` + + with latest changes, only single export is sufficient. + + ```bash + export GITHUB_TOKEN=foo + export GITLAB_TOKEN=foo + export GHE_TOKEN=foo + export AZURE_TOKEN=foo + ``` + + ### list: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Old nameNew name
GITHUB_ACCESS_TOKENGITHUB_TOKEN
GITHUB_PRIVATE_TOKENGITHUB_TOKEN
GITLAB_ACCESS_TOKENGITLAB_TOKEN
GITLAB_PRIVATE_TOKENGITLAB_TOKEN
AZURE_PRIVATE_TOKENAZURE_TOKEN
GHE_PRIVATE_TOKENGHE_TOKEN
+ +### Patch Changes + +- 22ff8fba5: Replacing the hard coded `baseApiUrl` by reading the value from configuration to enable private GitHub setup for TechDocs. +- Updated dependencies [3a4236570] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [5249594c5] +- Updated dependencies [56e4eb589] +- Updated dependencies [e37c0a005] +- Updated dependencies [a768a07fb] +- Updated dependencies [f00ca3cb8] +- Updated dependencies [6579769df] +- Updated dependencies [5adfc005e] +- Updated dependencies [8c2b76e45] +- Updated dependencies [440a17b39] +- Updated dependencies [fa56f4615] +- Updated dependencies [8afce088a] +- Updated dependencies [b3d57961c] +- Updated dependencies [7bbeb049f] + - @backstage/catalog-model@0.2.0 + - @backstage/backend-common@0.2.0 diff --git a/plugins/techdocs-backend/README.md b/plugins/techdocs-backend/README.md index b7eca2c5cb..625f0910b5 100644 --- a/plugins/techdocs-backend/README.md +++ b/plugins/techdocs-backend/README.md @@ -33,7 +33,7 @@ Currently the build process of techdocs-backend is split up in these three stage - Generators - Publishers -Preparers read your entity data and creates a working directory with your documentation source code. For example if you have set your `backstage.io/techdocs-ref` to `github:https://github.com/spotify/backstage.git` it will clone that repository to a temp folder and pass that on to the generator. +Preparers read your entity data and creates a working directory with your documentation source code. For example if you have set your `backstage.io/techdocs-ref` to `github:https://github.com/backstage/backstage.git` it will clone that repository to a temp folder and pass that on to the generator. Generators takes the prepared source and runs the `techdocs-container` on it. It then passes on the output folder of that build to the publisher. @@ -43,5 +43,5 @@ Any of these can be extended. If we want to publish to a external static file se ## Links -- [Frontend part of the plugin](https://github.com/spotify/backstage/tree/master/plugins/techdocs) +- [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/techdocs) - [The Backstage homepage](https://backstage.io) diff --git a/plugins/techdocs-backend/examples/documented-component/documented-component.yaml b/plugins/techdocs-backend/examples/documented-component/documented-component.yaml index 045ff89013..800116344f 100644 --- a/plugins/techdocs-backend/examples/documented-component/documented-component.yaml +++ b/plugins/techdocs-backend/examples/documented-component/documented-component.yaml @@ -4,7 +4,7 @@ metadata: name: documented-component description: A Service with TechDocs documentation annotations: - backstage.io/techdocs-ref: 'github:https://github.com/spotify/backstage/blob/master/plugins/techdocs-backend/examples/documented-component' + backstage.io/techdocs-ref: 'github:https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend/examples/documented-component' spec: type: service lifecycle: experimental diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 50eb0253cc..c1d1f6ad27 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.26", - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/config": "^0.1.1-alpha.26", + "@backstage/backend-common": "^0.2.0", + "@backstage/catalog-model": "^0.2.0", + "@backstage/config": "^0.1.1", "@types/dockerode": "^2.5.34", "@types/express": "^4.17.6", "command-exists-promise": "^2.0.2", @@ -37,7 +37,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", "supertest": "^4.0.2" }, "files": [ diff --git a/plugins/techdocs-backend/src/techdocs/stages/prepare/commonGit.test.ts b/plugins/techdocs-backend/src/techdocs/stages/prepare/commonGit.test.ts index cec1110f97..843df476e9 100644 --- a/plugins/techdocs-backend/src/techdocs/stages/prepare/commonGit.test.ts +++ b/plugins/techdocs-backend/src/techdocs/stages/prepare/commonGit.test.ts @@ -51,7 +51,7 @@ describe('commonGit preparer', () => { const mockEntity = createMockEntity({ 'backstage.io/techdocs-ref': - 'github:https://github.com/spotify/backstage/blob/master/plugins/techdocs-backend/examples/documented-component', + 'github:https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend/examples/documented-component', }); const tempDocsPath = await preparer.prepare(mockEntity); diff --git a/plugins/techdocs-backend/src/techdocs/stages/prepare/dir.test.ts b/plugins/techdocs-backend/src/techdocs/stages/prepare/dir.test.ts index 4412e6bf73..dc2b1d7d48 100644 --- a/plugins/techdocs-backend/src/techdocs/stages/prepare/dir.test.ts +++ b/plugins/techdocs-backend/src/techdocs/stages/prepare/dir.test.ts @@ -78,7 +78,7 @@ describe('directory preparer', () => { const mockEntity = createMockEntity({ 'backstage.io/managed-by-location': - 'github:https://github.com/spotify/backstage/blob/master/catalog-info.yaml', + 'github:https://github.com/backstage/backstage/blob/master/catalog-info.yaml', 'backstage.io/techdocs-ref': 'dir:./docs', }); diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md new file mode 100644 index 0000000000..387e4a8d90 --- /dev/null +++ b/plugins/techdocs/CHANGELOG.md @@ -0,0 +1,65 @@ +# @backstage/plugin-techdocs + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI +- 8351ad79b: Add a message if techdocs takes long time to load + + Fixes #2416. + + The UI after the change should look like this: + + ![techdocs-progress-bar](https://user-images.githubusercontent.com/33940798/94189286-296ac980-fec8-11ea-9051-1b3db938d12f.gif) + +### Patch Changes + +- 782f3b354: add test case for Progress component +- 57b54c8ed: While techdocs fetches site name and metadata for the component, the page title was displayed as '[object Object] | Backstage'. This has now been fixed to display the component ID if site name is not present or being fetched. +- Updated dependencies [28edd7d29] +- Updated dependencies [819a70229] +- Updated dependencies [3a4236570] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [cbbd271c4] +- Updated dependencies [482b6313d] +- Updated dependencies [e0be86b6f] +- Updated dependencies [f70a52868] +- Updated dependencies [12b5fe940] +- Updated dependencies [368fd8243] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [a768a07fb] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [5adfc005e] +- Updated dependencies [f0aa01bcc] +- Updated dependencies [0aecfded0] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [8b9c8196f] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [60d40892c] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [2ebcfac8d] +- Updated dependencies [fa56f4615] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [b3d57961c] +- Updated dependencies [0b956f21b] +- Updated dependencies [26e69ab1a] +- Updated dependencies [97c2cb19b] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [cbab5bbf8] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/plugin-catalog@0.2.0 + - @backstage/core-api@0.2.0 + - @backstage/core@0.2.0 + - @backstage/catalog-model@0.2.0 + - @backstage/theme@0.2.0 + - @backstage/test-utils@0.1.2 diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 9d14f0a919..ce0700c1a8 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,12 +22,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.26", - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/core-api": "^0.1.1-alpha.26", - "@backstage/plugin-catalog": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.2.0", + "@backstage/core": "^0.2.0", + "@backstage/core-api": "^0.2.0", + "@backstage/plugin-catalog": "^0.2.0", + "@backstage/test-utils": "^0.1.2", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -40,9 +40,9 @@ "sanitize-html": "^1.27.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx b/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx index 7754f227fc..d5d0e19e08 100644 --- a/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TechDocsHome } from './TechDocsHome'; -import React from 'react'; -import { render } from '@testing-library/react'; -import { wrapInTestApp } from '@backstage/test-utils'; -import { ApiRegistry, ApiProvider } from '@backstage/core-api'; -import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog'; import { Entity } from '@backstage/catalog-model'; +import { ApiProvider, ApiRegistry } from '@backstage/core-api'; +import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { render } from '@testing-library/react'; +import React from 'react'; +import { TechDocsHome } from './TechDocsHome'; describe('TechDocs Home', () => { const catalogApi: Partial = { diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md new file mode 100644 index 0000000000..2522a3af03 --- /dev/null +++ b/plugins/user-settings/CHANGELOG.md @@ -0,0 +1,32 @@ +# @backstage/plugin-user-settings + +## 0.2.0 + +### Minor Changes + +- 4fc1d440e: Add settings button to sidebar + +### Patch Changes + +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 6f96d7b2fd..2f098eae2e 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/core": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -32,9 +32,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/user-settings/src/components/AuthProviders/index.ts b/plugins/user-settings/src/components/AuthProviders/index.ts index 2f6a2b5ab1..dd7fbcf79b 100644 --- a/plugins/user-settings/src/components/AuthProviders/index.ts +++ b/plugins/user-settings/src/components/AuthProviders/index.ts @@ -16,3 +16,4 @@ export { AuthProviders } from './AuthProviders'; export { DefaultProviderSettings } from './DefaultProviderSettings'; +export { ProviderSettingsItem } from './ProviderSettingsItem'; diff --git a/plugins/user-settings/src/components/index.ts b/plugins/user-settings/src/components/index.ts new file mode 100644 index 0000000000..fe92b14adb --- /dev/null +++ b/plugins/user-settings/src/components/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ +export { Settings } from './Settings'; +export { SettingsPage as Router } from './SettingsPage'; +export * from './AuthProviders'; diff --git a/plugins/user-settings/src/index.ts b/plugins/user-settings/src/index.ts index 113930902a..9b0ce4262c 100644 --- a/plugins/user-settings/src/index.ts +++ b/plugins/user-settings/src/index.ts @@ -14,5 +14,4 @@ * limitations under the License. */ export { plugin } from './plugin'; -export { Settings } from './components/Settings'; -export { SettingsPage as Router } from './components/SettingsPage'; +export * from './components/'; diff --git a/plugins/welcome/CHANGELOG.md b/plugins/welcome/CHANGELOG.md new file mode 100644 index 0000000000..2932d41d75 --- /dev/null +++ b/plugins/welcome/CHANGELOG.md @@ -0,0 +1,32 @@ +# @backstage/plugin-welcome + +## 0.2.0 + +### Minor Changes + +- 28edd7d29: Create backend plugin through CLI + +### Patch Changes + +- Updated dependencies [819a70229] +- Updated dependencies [ae5983387] +- Updated dependencies [0d4459c08] +- Updated dependencies [482b6313d] +- Updated dependencies [1c60f716e] +- Updated dependencies [144c66d50] +- Updated dependencies [b79017fd3] +- Updated dependencies [6d97d2d6f] +- Updated dependencies [93a3fa3ae] +- Updated dependencies [782f3b354] +- Updated dependencies [2713f28f4] +- Updated dependencies [406015b0d] +- Updated dependencies [82759d3e4] +- Updated dependencies [ac8d5d5c7] +- Updated dependencies [ebca83d48] +- Updated dependencies [aca79334f] +- Updated dependencies [c0d5242a0] +- Updated dependencies [3beb5c9fc] +- Updated dependencies [754e31db5] +- Updated dependencies [1611c6dbc] + - @backstage/core@0.2.0 + - @backstage/theme@0.2.0 diff --git a/plugins/welcome/package.json b/plugins/welcome/package.json index 380a4b0a46..148b5734ee 100644 --- a/plugins/welcome/package.json +++ b/plugins/welcome/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-welcome", - "version": "0.1.1-alpha.26", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -21,8 +21,8 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.26", - "@backstage/theme": "^0.1.1-alpha.26", + "@backstage/core": "^0.2.0", + "@backstage/theme": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -32,9 +32,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.26", - "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/cli": "^0.2.0", + "@backstage/dev-utils": "^0.1.2", + "@backstage/test-utils": "^0.1.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx b/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx index 7b94024948..4cd2c34ec1 100644 --- a/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx +++ b/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx @@ -69,7 +69,7 @@ const WelcomePage = () => { of these phases. The best way to keep track of the progress is through the  Milestones @@ -116,7 +116,7 @@ const WelcomePage = () => { We suggest you either check out the documentation for{' '} creating a plugin @@ -127,7 +127,7 @@ const WelcomePage = () => { {' '} in the directory{' '} plugins/ @@ -144,7 +144,7 @@ const WelcomePage = () => { Create a plugin diff --git a/scripts/verify-links.js b/scripts/verify-links.js index 6126f693e4..0422352d4e 100755 --- a/scripts/verify-links.js +++ b/scripts/verify-links.js @@ -27,7 +27,7 @@ async function verifyUrl(basePath, absUrl, docPages) { // Avoid having absolute URL links within docs/, so that links work on the site if ( absUrl.match( - /https:\/\/github.com\/spotify\/backstage\/(tree|blob)\/master\/docs\//, + /https:\/\/github.com\/backstage\/backstage\/(tree|blob)\/master\/docs\//, ) && basePath.match(/^(?:docs|microsite)\//) ) { @@ -37,7 +37,7 @@ async function verifyUrl(basePath, absUrl, docPages) { const url = absUrl .replace(/#.*$/, '') .replace( - /https:\/\/github.com\/spotify\/backstage\/(tree|blob)\/master/, + /https:\/\/github.com\/backstage\/backstage\/(tree|blob)\/master/, '', ); if (!url) { diff --git a/yarn.lock b/yarn.lock index 06cab2d9ed..c265aecd6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@apidevtools/json-schema-ref-parser@9.0.6", "@apidevtools/json-schema-ref-parser@^9.0.6": +"@apidevtools/json-schema-ref-parser@^9.0.6": version "9.0.6" resolved "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#5d9000a3ac1fd25404da886da6b266adcd99cf1c" integrity sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg== @@ -56,10 +56,10 @@ dependencies: tslib "~2.0.1" -"@asyncapi/avro-schema-parser@^0.1.2": - version "0.1.2" - resolved "https://registry.npmjs.org/@asyncapi/avro-schema-parser/-/avro-schema-parser-0.1.2.tgz#f6c340ccaa24bc36399d3a0f1a6e02790a948453" - integrity sha512-K4GlakiE42J9AWwAu3BWn3Qbf+N8C6vE4eEm5LEx7HqAhHG+FA0U7/3vvXoj31rnS/8sgPQpc2msLWQlmCtZyw== +"@asyncapi/avro-schema-parser@^0.2.0": + version "0.2.0" + resolved "https://registry.npmjs.org/@asyncapi/avro-schema-parser/-/avro-schema-parser-0.2.0.tgz#c9da2bb2858aca5a3b9e9a0e600084afd3765551" + integrity sha512-/oPDPudF82RGFXz5uhF77PSDZkAR+yHpdxUEbJ5jwk/X3RB74VRk8dqSgTqhUO+pLh+/Hut3x3VFacA8C9L2QA== "@asyncapi/openapi-schema-parser@^2.0.0": version "2.0.0" @@ -68,13 +68,13 @@ dependencies: "@openapi-contrib/openapi-schema-to-json-schema" "^3.0.0" -"@asyncapi/parser@^1.0.0-rc.1": - version "1.0.0-rc.2" - resolved "https://registry.npmjs.org/@asyncapi/parser/-/parser-1.0.0-rc.2.tgz#87d2e83c1d390e21d53f868e6209cbc584d35449" - integrity sha512-nZYJLnMiq48q7YHa+AI9ZaDc5UqoqKR7MDhTiIKsIJj6X5fF6hpwBrTP0bQn76Pc1oGBXRB69PcD/Y+Et1qFyw== +"@asyncapi/parser@^1.0.1": + version "1.1.0" + resolved "https://registry.npmjs.org/@asyncapi/parser/-/parser-1.1.0.tgz#b366c85a6322e182e040d60f36400a0b5c26393c" + integrity sha512-0+NeTiW5sPNYaFf4P2VCcy7Z7MLMP7H969cgOp3gvVTKroI5idkYnWo/C16tKAxs+2oOQ9WnPolsNgc+jb/qtg== dependencies: "@apidevtools/json-schema-ref-parser" "^9.0.6" - "@asyncapi/specs" "^2.7.4" + "@asyncapi/specs" "^2.7.5" "@fmvilas/pseudo-yaml-ast" "^0.3.1" ajv "^6.10.1" js-yaml "^3.13.1" @@ -82,18 +82,10 @@ node-fetch "^2.6.0" tiny-merge-patch "^0.1.2" -"@asyncapi/raml-dt-schema-parser@^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-2.0.0.tgz#6e9eff89032aa7b82a963d8e72e320e493fc3835" - integrity sha512-ve41LIvbqDU8s0ZeDrWy+dyQZ/XSb7vKiJUHNgy8xcgxsz4YuttbEJbyGJvarw3qf2y+0y6cA1KUFiXoE+AIUg== - dependencies: - js-yaml "^3.13.1" - ramldt2jsonschema "^1.1.0" - -"@asyncapi/specs@^2.7.4": - version "2.7.4" - resolved "https://registry.npmjs.org/@asyncapi/specs/-/specs-2.7.4.tgz#5db4390b68aeb40d70c1723d8f46b0a091110afc" - integrity sha512-3Np9ip1Qn5AgnxTrbI0CMW2F/WUorpiAKz+GUfEy4a6GPk0eTSI6CIcbx2/jej5P91nhEyny9+D3oIzn2MreTA== +"@asyncapi/specs@^2.7.5": + version "2.7.5" + resolved "https://registry.npmjs.org/@asyncapi/specs/-/specs-2.7.5.tgz#3a516d198fc41a1103695bd889fdd4fbbebe7f5d" + integrity sha512-T1Ham9sqZKCtSowXRPaBCRy2oz3KHglqqrKiaO7lEudpP6lwH5SwXaq4qliyKzWaqd22srJHE4szdsorbFZKlw== "@babel/code-frame@7.0.0": version "7.0.0" @@ -1770,32 +1762,33 @@ dependencies: yaml-ast-parser "0.0.43" -"@gitbeaker/core@^23.5.0": - version "23.5.0" - resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-23.5.0.tgz#e0be44eecd0d7bf5418c161997c36d45b0c1ba81" - integrity sha512-5geLk7SxAttABBJZxfuSp72lSYWRyRId583vGCpKB6ISkoDhP+vJxdE6ypmtOJPV4CaSRZhluAGAZd968pi9ng== +"@gitbeaker/core@^25.2.0": + version "25.2.0" + resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-25.2.0.tgz#c2f46b65ed88aebfa69afd2e58dbf4ebe2efb2c7" + integrity sha512-dhCvZItI8FIzHtJ9EySQ43GmNg3j39MxDGMCpDHn+Qb1o54QS+J6XPVQrMRmJioZIyj+WZQPX/IP+/mRkx8vhg== dependencies: - "@gitbeaker/requester-utils" "^23.5.0" + "@gitbeaker/requester-utils" "^25.2.0" form-data "^3.0.0" li "^1.3.0" xcase "^2.0.1" -"@gitbeaker/node@^23.5.0": - version "23.5.0" - resolved "https://registry.npmjs.org/@gitbeaker/node/-/node-23.5.0.tgz#0243be78aad148e7d6b5d79b7acc340748b5fa94" - integrity sha512-GEyhcrF1Lm8YmsmwntfzuhXnq00TrG14wNZP2Hg+DGgexG25eBbbcyFXuFZlBFSaGMQlsc8aPeuEyfyGmgpwnw== +"@gitbeaker/node@^25.2.0": + version "25.2.0" + resolved "https://registry.npmjs.org/@gitbeaker/node/-/node-25.2.0.tgz#cc91e83328ec32de0b1a0dac23accd2385734a66" + integrity sha512-FWchXYJ5agn0ptAQxtkkSKSg1ObbP2xfMzHLECxINFRBHYhg0ms8Fp8Qb+71pxJz7IMlvajyEtZaPfHBmyuh9Q== dependencies: - "@gitbeaker/core" "^23.5.0" - "@gitbeaker/requester-utils" "^23.5.0" - got "^11.1.4" + "@gitbeaker/core" "^25.2.0" + "@gitbeaker/requester-utils" "^25.2.0" + got "^11.7.0" xcase "^2.0.1" -"@gitbeaker/requester-utils@^23.5.0": - version "23.5.0" - resolved "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-23.5.0.tgz#e6f5d0216cb978be95e6bf40adf606f23d426f14" - integrity sha512-MdmInOO4unkApvtbv6PnIpDYXosgZgClSOqbxF5S4aJRCZVTJ6oPjMoNP8luhyT9xQeknpKxn9Iv8psEh7IC1Q== +"@gitbeaker/requester-utils@^25.2.0": + version "25.2.0" + resolved "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-25.2.0.tgz#f71c44e0073617877f9875dd00c4ae0d74897b09" + integrity sha512-pjuFIVlbxSTPdN+zFT/LBP4ym8k0OBYwUpc5WkzoOtvdTGuDX05r8ufnV07kibLDJkwDmjwnH4Hsc66yevSQTw== dependencies: - query-string "^6.12.1" + form-data "^3.0.0" + query-string "^6.13.3" xcase "^2.0.1" "@graphql-codegen/cli@^1.17.7": @@ -2500,19 +2493,17 @@ dependencies: stream "^0.0.2" -"@kyma-project/asyncapi-react@^0.13.1": - version "0.13.1" - resolved "https://registry.npmjs.org/@kyma-project/asyncapi-react/-/asyncapi-react-0.13.1.tgz#8a92ee2df996540240c0afa17adfa566e4cee18d" - integrity sha512-d+52fzfBHpcC32WvrfB6sSyQFgzda/lHrKSn5klXP6tEiOU5uaLEIQzvZLCL8kXtuHiknozHO3h/BfviqEkwww== +"@kyma-project/asyncapi-react@^0.14.2": + version "0.14.2" + resolved "https://registry.npmjs.org/@kyma-project/asyncapi-react/-/asyncapi-react-0.14.2.tgz#6d99ef878f0481b05db0f3be7c94f4534176675f" + integrity sha512-lf3zcIuCTaVEIkCpF7Vwulrucgdfp1zXUIvkqjYPteOJjOuT6BAvnYwgvFUYibitmD/ADkvK8ybIeKdNJcyaPw== dependencies: - "@asyncapi/avro-schema-parser" "^0.1.2" + "@asyncapi/avro-schema-parser" "^0.2.0" "@asyncapi/openapi-schema-parser" "^2.0.0" - "@asyncapi/parser" "^1.0.0-rc.1" - "@asyncapi/raml-dt-schema-parser" "^2.0.0" + "@asyncapi/parser" "^1.0.1" constate "^1.2.0" - dompurify "^1.0.11" - json-schema-ref-parser "^9.0.6" - markdown-it "^9.1.0" + dompurify "^2.1.1" + markdown-it "^11.0.1" merge "^1.2.1" openapi-sampler "^1.0.0-beta.15" react-use "^12.2.0" @@ -3660,14 +3651,14 @@ resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-2.4.0.tgz#1b5859298bf3f61137d7b05084f058a775d6fd73" integrity sha512-U8F/suzg4MuV+8mK1/ufs0Y6c3O8hc1wnuD2IKoOVJvegGfz5JCafyoyGAW6iyuT1DZBMPzVWEqfiuYPmoE7pw== -"@roadiehq/backstage-plugin-github-insights@^0.2.10": - version "0.2.10" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-0.2.10.tgz#f58298486183e2af36b2c292d6145f2a35eb6fdb" - integrity sha512-vmIbjehJpoXjuLNX5cYbZTG6U0tHVQWrGUA5fYWQtAIVC0cmwbkuvW8WoNymAietGmlshm+0rV6MK0/vd2iu4A== +"@roadiehq/backstage-plugin-github-insights@^0.2.12": + version "0.2.12" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-0.2.12.tgz#aeda6306769f376cf6b5b9d74268b060a0f4e764" + integrity sha512-f9g5ajVWQkywoYo0zDUZV3g0SPxOTi3MvMuhUvgaZ/XKJr9mBZTe5qHnEYBSHOCB88l0Y2g0qHNdbjXhbFpokQ== dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.25" - "@backstage/core" "^0.1.1-alpha.25" - "@backstage/theme" "^0.1.1-alpha.25" + "@backstage/catalog-model" "^0.2.0" + "@backstage/core" "^0.2.0" + "@backstage/theme" "^0.2.0" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.45" @@ -3681,15 +3672,15 @@ react-use "^15.3.3" remark-gfm "^1.0.0" -"@roadiehq/backstage-plugin-github-pull-requests@^0.6.0": - version "0.6.0" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-0.6.0.tgz#5d39eb237aa39b76bb7e5e867355abeccac7e5ff" - integrity sha512-cwTofvhSzb3FyyJ/HRixPkn9Ayg3x4tv6FlHSswlMEDx8EJv0hmfNXVps2QAG/82JgACTxmXKNQRnPQ0+TLiOw== +"@roadiehq/backstage-plugin-github-pull-requests@^0.6.1": + version "0.6.1" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-0.6.1.tgz#bce3ce93af7b2f6c38d4665c8a0d8a6b2eaa4212" + integrity sha512-3r0BBV6kRlbrlfVA/G7Tc0xbw9A+9roihspCaV/yhhqXgk/ik5v6ftEautlx45+gKaFMp+jgmfKHqFgOdSyhZw== dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.25" - "@backstage/core" "^0.1.1-alpha.25" - "@backstage/plugin-catalog" "^0.1.1-alpha.25" - "@backstage/theme" "^0.1.1-alpha.25" + "@backstage/catalog-model" "^0.2.0" + "@backstage/core" "^0.2.0" + "@backstage/plugin-catalog" "^0.2.0" + "@backstage/theme" "^0.2.0" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "^4.0.0-alpha.56" @@ -3703,16 +3694,16 @@ react-router "6.0.0-beta.0" react-use "^15.3.3" -"@roadiehq/backstage-plugin-travis-ci@^0.2.5": - version "0.2.5" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.2.5.tgz#588cd8b4a4dd4bd426c0012f8d35eae4504b55f4" - integrity sha512-4aJizmvIeunpl8D/YDvzagNzikPU51DSZFz1tN0XCwRR+buTPknV141qsKP+yxUbs6nx3Xuh+T/vNkb9lk6FlA== +"@roadiehq/backstage-plugin-travis-ci@^0.2.7": + version "0.2.7" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.2.7.tgz#bc7968b461016b2710794d10766266de9ab4f759" + integrity sha512-uXF5t2uZqd9TNGFSMYlyk6NAweVb5KLlM4GMiltattzxRWiqbCp5VumubrLTTsA8dvsWCrXWfhe95MStcUnl+A== dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.24" - "@backstage/core" "^0.1.1-alpha.24" - "@backstage/core-api" "^0.1.1-alpha.24" - "@backstage/plugin-catalog" "^0.1.1-alpha.24" - "@backstage/theme" "^0.1.1-alpha.24" + "@backstage/catalog-model" "^0.2.0" + "@backstage/core" "^0.2.0" + "@backstage/core-api" "^0.2.0" + "@backstage/plugin-catalog" "^0.2.0" + "@backstage/theme" "^0.2.0" "@material-ui/core" "^4.9.1" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.45" @@ -3798,6 +3789,11 @@ resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-3.1.2.tgz#548650de521b344e3781fbdb0ece4aa6f729afb8" integrity sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ== +"@sindresorhus/is@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz#2ff674e9611b45b528896d820d3d7a812de2f0e4" + integrity sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ== + "@sinonjs/commons@^1.7.0": version "1.7.1" resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.1.tgz#da5fd19a5f71177a53778073978873964f49acf1" @@ -3812,10 +3808,10 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@spotify/eslint-config-base@^8.0.0": - version "8.0.0" - resolved "https://registry.npmjs.org/@spotify/eslint-config-base/-/eslint-config-base-8.0.0.tgz#c3d10d8a05ad9129d579952cb80063e4c4fa216e" - integrity sha512-07Fo+KoTMl4AaZJPD6deFnYmG634wzgeqfFcWdFlIrOLAasvWSH8Lp6ZE9cJBKuffOAy8kuEE1SwFo34+5X8bQ== +"@spotify/eslint-config-base@^9.0.0": + version "9.0.0" + resolved "https://registry.npmjs.org/@spotify/eslint-config-base/-/eslint-config-base-9.0.0.tgz#e122b2e6d1a11750170badc5be6774ded95953d2" + integrity sha512-LNGY6bBM0IlosvMIx9Ic5gqatpa5LPvrJhN4RnrUnP9oaXNLgPTKDE89p3eC5Tnh78ADdX4HD+rbHDSyP2tBgg== "@spotify/eslint-config-oss@^1.0.1": version "1.0.2" @@ -3824,15 +3820,15 @@ dependencies: eslint-plugin-notice "^0.9.10" -"@spotify/eslint-config-react@^8.0.0": - version "8.0.2" - resolved "https://registry.npmjs.org/@spotify/eslint-config-react/-/eslint-config-react-8.0.2.tgz#91af3c58b22d49a96795336ed66927e722cda430" - integrity sha512-V0gzO/jWmjhODLINAfeunHj+OBdj/cQeVDw+92ZUlkonAg6BZLjX6Vy8jeIUFjfgmVOtI9eKbcApxaurj1jN6g== +"@spotify/eslint-config-react@^9.0.0": + version "9.0.0" + resolved "https://registry.npmjs.org/@spotify/eslint-config-react/-/eslint-config-react-9.0.0.tgz#9c032e257090a5b3f5b08b28c1311485bf0fbae3" + integrity sha512-3w+cmbUljBLxZGLk4dn1oJD8v4uxW7bKackkcpZhac6VkQmg01EDN04Bx9qmbNe5S/2uHwrOJGcWlge5R8Ml1Q== -"@spotify/eslint-config-typescript@^8.0.0": - version "8.1.1" - resolved "https://registry.npmjs.org/@spotify/eslint-config-typescript/-/eslint-config-typescript-8.1.1.tgz#a8c6f74ef9445fe740008ae3a26003a2eef78f93" - integrity sha512-0NkE6ZiSRf9IBWwCxzn/l7UdwcL/KZsbzjjOSweafyYueajEn+eIpKjOgDGUL/ebxSrOtjEp+YeFc4lSPkP0qg== +"@spotify/eslint-config-typescript@^9.0.0": + version "9.0.0" + resolved "https://registry.npmjs.org/@spotify/eslint-config-typescript/-/eslint-config-typescript-9.0.0.tgz#be68cfaf212599f0bfeb6536c7c58ec05d2b6fba" + integrity sha512-ZsXTwMA68ZCz943U4N8XwprdWcc7ErOO/IW8PewLK5lycCZtLnmRkOvAbae7O5qNJPD8b/l0iUMTLaZuwjXWwg== "@spotify/prettier-config@^8.0.0": version "8.0.0" @@ -4986,16 +4982,38 @@ dependencies: postcss "5 - 7" +"@types/d3-color@*": + version "2.0.0" + resolved "https://registry.npmjs.org/@types/d3-color/-/d3-color-2.0.0.tgz#febdfadade56e215a4c3f612fe3000d92999f5d5" + integrity sha512-Bs0maTeU47rdZT+n42iQ0C4gnbnJlIDJkqHFtIsDx2tPPITDeoSdIrm+00UYXzegzArYC2GsG80eHNMwz08IAw== + "@types/d3-force@^1.2.1": version "1.2.1" resolved "https://registry.npmjs.org/@types/d3-force/-/d3-force-1.2.1.tgz#c28803ea36fe29788db69efa0ad6c2dc09544e83" integrity sha512-jqK+I36uz4kTBjyk39meed5y31Ab+tXYN/x1dn3nZEus9yOHCLc+VrcIYLc/aSQ0Y7tMPRlIhLetulME76EiiA== +"@types/d3-interpolate@*": + version "2.0.0" + resolved "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-2.0.0.tgz#325029216dc722c1c68c33ccda759f1209d35823" + integrity sha512-Wt1v2zTlEN8dSx8hhx6MoOhWQgTkz0Ukj7owAEIOF2QtI0e219paFX9rf/SLOr/UExWb1TcUzatU8zWwFby6gg== + dependencies: + "@types/d3-color" "*" + "@types/d3-path@*": version "1.0.8" resolved "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.8.tgz#48e6945a8ff43ee0a1ce85c8cfa2337de85c7c79" integrity sha512-AZGHWslq/oApTAHu9+yH/Bnk63y9oFOMROtqPAtxl5uB6qm1x2lueWdVEjsjjV3Qc2+QfuzKIwIR5MvVBakfzA== +"@types/d3-path@^1": + version "1.0.9" + resolved "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz#73526b150d14cd96e701597cbf346cfd1fd4a58c" + integrity sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ== + +"@types/d3-selection@*", "@types/d3-selection@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-2.0.0.tgz#59df94a8e47ed1050a337d4ffb4d4d213aa590a8" + integrity sha512-EF0lWZ4tg7oDFg4YQFlbOU3936e3a9UmoQ2IXlBy1+cv2c2Pv7knhKUzGlH5Hq2sF/KeDTH1amiRPey2rrLMQA== + "@types/d3-shape@*": version "1.3.2" resolved "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.2.tgz#a41d9d6b10d02e221696b240caf0b5d0f5a588ec" @@ -5003,6 +5021,26 @@ dependencies: "@types/d3-path" "*" +"@types/d3-shape@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-2.0.0.tgz#61aa065726f3c2641aedc59c3603475ab11aeb2f" + integrity sha512-NLzD02m5PiD1KLEDjLN+MtqEcFYn4ZL9+Rqc9ZwARK1cpKZXd91zBETbe6wpBB6Ia0D0VZbpmbW3+BsGPGnCpA== + dependencies: + "@types/d3-path" "^1" + +"@types/d3-zoom@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-2.0.0.tgz#ef8b87464e8ebc7c66b70f6383d1ae841e78e7fc" + integrity sha512-daL0PJm4yT0ISTGa7p2lHX0kvv9FO/IR1ooWbHR/7H4jpbaKiLux5FslyS/OvISPiJ5SXb4sOqYhO6fMB6hKRw== + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/dagre@^0.7.44": + version "0.7.44" + resolved "https://registry.npmjs.org/@types/dagre/-/dagre-0.7.44.tgz#8f4b796b118ca29c132da7068fbc0d0351ee5851" + integrity sha512-N6HD+79w77ZVAaVO7JJDW5yJ9LAxM62FpgNGO9xEde+KVYjDRyhIMzfiErXpr1g0JPon9kwlBzoBK6s4fOww9Q== + "@types/diff@^4.0.2": version "4.0.2" resolved "https://registry.npmjs.org/@types/diff/-/diff-4.0.2.tgz#2e9bb89f9acc3ab0108f0f3dc4dbdcf2fff8a99c" @@ -5734,13 +5772,6 @@ resolved "https://registry.npmjs.org/@types/semver/-/semver-6.2.1.tgz#a236185670a7860f1597cf73bea2e16d001461ba" integrity sha512-+beqKQOh9PYxuHvijhVl+tIHvT6tuwOrE9m14zd+MT2A38KoKZhh7pYJ0SNleLtwDsiIxHDsIk9bv01oOxvSvA== -"@types/serve-handler@^6.1.0": - version "6.1.0" - resolved "https://registry.npmjs.org/@types/serve-handler/-/serve-handler-6.1.0.tgz#6952aaf864e542297ce8a2480b3e0d9ea59de7f6" - integrity sha512-F9BpWotLZrQvq1CdE3oCnVmQUb6dWq20HSB/qjF4mG7WkZjPQ6fye8veznMKoBPhFJve4yz9C1NOITdTcoLngQ== - dependencies: - "@types/node" "*" - "@types/serve-static@*": version "1.13.3" resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" @@ -6452,26 +6483,6 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@6.5.2: - version "6.5.2" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz#678495f9b82f7cca6be248dd92f59bff5e1f4360" - integrity sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.1" - -ajv@^5.0.0: - version "5.5.2" - resolved "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.1, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5, ajv@^6.7.0: version "6.12.5" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da" @@ -8984,11 +8995,6 @@ contains-path@^0.1.0: resolved "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= - content-disposition@0.5.3: version "0.5.3" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -9681,11 +9687,29 @@ d3-color@1: resolved "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz#c52002bf8846ada4424d55d97982fef26eb3bc8a" integrity sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q== +"d3-color@1 - 2": + version "2.0.0" + resolved "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e" + integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ== + "d3-dispatch@1 - 2": version "2.0.0" resolved "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz#8a18e16f76dd3fcaef42163c97b926aa9b55e7cf" integrity sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA== +d3-drag@2: + version "2.0.0" + resolved "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz#9eaf046ce9ed1c25c88661911c1d5a4d8eb7ea6d" + integrity sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w== + dependencies: + d3-dispatch "1 - 2" + d3-selection "2" + +"d3-ease@1 - 2": + version "2.0.0" + resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz#fd1762bfca00dae4bacea504b1d628ff290ac563" + integrity sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ== + d3-force@^2.0.1: version "2.1.1" resolved "https://registry.npmjs.org/d3-force/-/d3-force-2.1.1.tgz#f20ccbf1e6c9e80add1926f09b51f686a8bc0937" @@ -9707,11 +9731,23 @@ d3-interpolate@1, d3-interpolate@^1.3.0: dependencies: d3-color "1" +"d3-interpolate@1 - 2": + version "2.0.1" + resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163" + integrity sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ== + dependencies: + d3-color "1 - 2" + d3-path@1: version "1.0.9" resolved "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== +"d3-path@1 - 2": + version "2.0.0" + resolved "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz#55d86ac131a0548adae241eebfb56b4582dd09d8" + integrity sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA== + "d3-quadtree@1 - 2": version "2.0.0" resolved "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-2.0.0.tgz#edbad045cef88701f6fee3aee8e93fb332d30f9d" @@ -9729,6 +9765,11 @@ d3-scale@^2.1.0: d3-time "1" d3-time-format "2" +d3-selection@2, d3-selection@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz#94a11638ea2141b7565f883780dabc7ef6a61066" + integrity sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA== + d3-shape@^1.2.0: version "1.3.7" resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" @@ -9736,6 +9777,13 @@ d3-shape@^1.2.0: dependencies: d3-path "1" +d3-shape@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-2.0.0.tgz#2331b62fa784a2a1daac47a7233cfd69301381fd" + integrity sha512-djpGlA779ua+rImicYyyjnOjeubyhql1Jyn1HK0bTyawuH76UQRWXd+pftr67H6Fa8hSwetkgb/0id3agKWykw== + dependencies: + d3-path "1 - 2" + d3-time-format@2: version "2.3.0" resolved "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz#107bdc028667788a8924ba040faf1fbccd5a7850" @@ -9753,6 +9801,28 @@ d3-time@1: resolved "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz#055edb1d170cfe31ab2da8968deee940b56623e6" integrity sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA== +d3-transition@2: + version "2.0.0" + resolved "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz#366ef70c22ef88d1e34105f507516991a291c94c" + integrity sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog== + dependencies: + d3-color "1 - 2" + d3-dispatch "1 - 2" + d3-ease "1 - 2" + d3-interpolate "1 - 2" + d3-timer "1 - 2" + +d3-zoom@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz#f04d0afd05518becce879d04709c47ecd93fba54" + integrity sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw== + dependencies: + d3-dispatch "1 - 2" + d3-drag "2" + d3-interpolate "1 - 2" + d3-selection "2" + d3-transition "2" + d@1, d@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" @@ -9761,6 +9831,14 @@ d@1, d@^1.0.1: es5-ext "^0.10.50" type "^1.0.1" +dagre@^0.8.5: + version "0.8.5" + resolved "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee" + integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw== + dependencies: + graphlib "^2.1.8" + lodash "^4.17.15" + damerau-levenshtein@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791" @@ -10364,11 +10442,6 @@ domhandler@^3.0, domhandler@^3.0.0: dependencies: domelementtype "^2.0.1" -dompurify@^1.0.11: - version "1.0.11" - resolved "https://registry.npmjs.org/dompurify/-/dompurify-1.0.11.tgz#fe0f4a40d147f7cebbe31a50a1357539cfc1eb4d" - integrity sha512-XywCTXZtc/qCX3iprD1pIklRVk/uhl8BKpkTxr+ZyMVUzSUg7wkQXRBp/euJ5J5moa1QvfpvaPQVP71z1O59dQ== - dompurify@^2.0.12: version "2.1.1" resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.1.1.tgz#b5aa988676b093a9c836d8b855680a8598af25fe" @@ -10379,6 +10452,11 @@ dompurify@^2.0.7: resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.0.12.tgz#284a2b041e1c60b8e72d7b4d2fadad36141254ae" integrity sha512-Fl8KseK1imyhErHypFPA8qpq9gPzlsJ/EukA6yk9o0gX23p1TzC+rh9LqNg1qvErRTc0UNMYlKxEGSfSh43NDg== +dompurify@^2.1.1: + version "2.2.0" + resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.2.0.tgz#51d34e76faa38b5d6b4e83a0678530f27fe3965c" + integrity sha512-bqFOQ7XRmmozp0VsKdIEe8UwZYxj0yttz7l80GBtBqdVRY48cOpXH2J/CVO7AEkV51qY0EBVXfilec18mdmQ/w== + domutils@1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" @@ -10634,7 +10712,7 @@ enquirer@^2.3.0, enquirer@^2.3.5: dependencies: ansi-colors "^4.1.1" -entities@^1.1.1, entities@^1.1.2, entities@~1.1.1: +entities@^1.1.1, entities@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== @@ -11442,11 +11520,6 @@ fast-deep-equal@2.0.1, fast-deep-equal@^2.0.1: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= - fast-deep-equal@^3.0.0, fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -11508,13 +11581,6 @@ fast-shallow-equal@^1.0.0: resolved "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b" integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw== -fast-url-parser@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= - dependencies: - punycode "^1.3.2" - fastest-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz#9122d406d4c9d98bea644a6b6853d5874b87b028" @@ -12522,23 +12588,6 @@ got@^10.7.0: to-readable-stream "^2.0.0" type-fest "^0.10.0" -got@^11.1.4: - version "11.6.2" - resolved "https://registry.npmjs.org/got/-/got-11.6.2.tgz#79d7bb8c11df212b97f25565407a1f4ae73210ec" - integrity sha512-/21qgUePCeus29Jk7MEti8cgQUNXFSWfIevNIk4H7u1wmXNDrGPKPY6YsPY+o9CIT/a2DjCjRz0x1nM9FtS2/A== - dependencies: - "@sindresorhus/is" "^3.1.1" - "@szmarczak/http-timer" "^4.0.5" - "@types/cacheable-request" "^6.0.1" - "@types/responselike" "^1.0.0" - cacheable-lookup "^5.0.3" - cacheable-request "^7.0.1" - decompress-response "^6.0.0" - http2-wrapper "^1.0.0-beta.5.2" - lowercase-keys "^2.0.0" - p-cancelable "^2.0.0" - responselike "^2.0.0" - got@^11.5.2: version "11.6.0" resolved "https://registry.npmjs.org/got/-/got-11.6.0.tgz#4978c78f3cbc3a45ee95381f8bb6efd1db1f4638" @@ -12573,6 +12622,23 @@ got@^11.6.2: p-cancelable "^2.0.0" responselike "^2.0.0" +got@^11.7.0: + version "11.8.0" + resolved "https://registry.npmjs.org/got/-/got-11.8.0.tgz#be0920c3586b07fd94add3b5b27cb28f49e6545f" + integrity sha512-k9noyoIIY9EejuhaBNLyZ31D5328LeqnyPNXJQb2XlJZcKakLqN5m6O/ikhq/0lw56kUYS54fVm+D1x57YC9oQ== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.1" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + got@^9.6.0: version "9.6.0" resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -12616,6 +12682,13 @@ graphiql@^1.0.0-alpha.10: regenerator-runtime "^0.13.5" theme-ui "^0.3.1" +graphlib@^2.1.8: + version "2.1.8" + resolved "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" + integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== + dependencies: + lodash "^4.17.15" + graphql-config@^3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/graphql-config/-/graphql-config-3.0.3.tgz#58907c65ed7d6e04132321450b60e57863ea9a5f" @@ -14880,25 +14953,6 @@ json-schema-merge-allof@^0.6.0: json-schema-compare "^0.2.2" lodash "^4.17.4" -json-schema-migrate@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-0.2.0.tgz#ba47a5b0072fc72396460e1bd60b44d52178bbc6" - integrity sha1-ukelsAcvxyOWRg4b1gtE1SF4u8Y= - dependencies: - ajv "^5.0.0" - -json-schema-ref-parser@^9.0.6: - version "9.0.6" - resolved "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#fc89a5e6b853f2abe8c0af30d3874196526adb60" - integrity sha512-z0JGv7rRD3CnJbZY/qCpscyArdtLJhr/wRBmFUdoZ8xMjsFyNdILSprG2degqRLjBjyhZHAEBpGOxniO9rKTxA== - dependencies: - "@apidevtools/json-schema-ref-parser" "9.0.6" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -15394,6 +15448,13 @@ linkify-it@^2.0.0: dependencies: uc.micro "^1.0.1" +linkify-it@^3.0.1: + version "3.0.2" + resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8" + integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ== + dependencies: + uc.micro "^1.0.1" + lint-staged@^10.1.0: version "10.2.11" resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-10.2.11.tgz#713c80877f2dc8b609b05bc59020234e766c9720" @@ -16013,14 +16074,14 @@ markdown-it@^10.0.0: mdurl "^1.0.1" uc.micro "^1.0.5" -markdown-it@^9.1.0: - version "9.1.0" - resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-9.1.0.tgz#df9601c168568704d554b1fff9af0c5b561168d9" - integrity sha512-xHKG4C8iPriyfu/jc2hsCC045fKrMQ0VexX2F1FGYiRxDxqMB2aAhF8WauJ3fltn2kb90moGBkiiEdooGIg55w== +markdown-it@^11.0.1: + version "11.0.1" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.1.tgz#b54f15ec2a2193efa66dda1eb4173baea08993d6" + integrity sha512-aU1TzmBKcWNNYvH9pjq6u92BML+Hz3h5S/QpfTFwiQF852pLT+9qHsrhM9JYipkOXZxGn+sGH8oyJE9FD9WezQ== dependencies: argparse "^1.0.7" - entities "~1.1.1" - linkify-it "^2.0.0" + entities "~2.0.0" + linkify-it "^3.0.1" mdurl "^1.0.1" uc.micro "^1.0.5" @@ -16390,18 +16451,6 @@ mime-db@1.44.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== - -mime-types@2.1.18: - version "2.1.18" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== - dependencies: - mime-db "~1.33.0" - mime-types@^2.1.12, mime-types@^2.1.26, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" @@ -18065,6 +18114,15 @@ passport-okta-oauth@^0.0.1: pkginfo "0.2.x" uid2 "0.0.3" +passport-onelogin-oauth@^0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/passport-onelogin-oauth/-/passport-onelogin-oauth-0.0.1.tgz#6e991ac6720783fdd80d4caa08c36cc71ef19962" + integrity sha512-EXFBqlJdHf5AX4QaiZsLfhgQUOR6z3zGA5479SUJF4I4rnAt7yasZEbs27pg8MRiQh/uLZEWLGMoVXr6LHV9mQ== + dependencies: + passport-oauth "1.0.0" + pkginfo "0.2.x" + uid2 "0.0.3" + passport-saml@^1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/passport-saml/-/passport-saml-1.3.3.tgz#cbea1a2b21ff32b3bc4bfd84dc39c3a370df9935" @@ -18124,7 +18182,7 @@ path-is-absolute@^1.0.0: resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@1.0.2, path-is-inside@^1.0.2: +path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= @@ -18161,11 +18219,6 @@ path-to-regexp@0.1.7: resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= -path-to-regexp@2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" - integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== - path-to-regexp@^1.7.0: version "1.8.0" resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" @@ -18244,11 +18297,16 @@ pg-connection-string@0.1.3, pg-connection-string@^0.1.3: resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= -pg-connection-string@2.3.0, pg-connection-string@^2.3.0: +pg-connection-string@2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.3.0.tgz#c13fcb84c298d0bfa9ba12b40dd6c23d946f55d6" integrity sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w== +pg-connection-string@^2.3.0, pg-connection-string@^2.4.0: + version "2.4.0" + resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz#c979922eb47832999a204da5dbe1ebf2341b6a10" + integrity sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ== + pg-int8@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" @@ -18262,15 +18320,15 @@ pg-pool@1.*: generic-pool "2.4.3" object-assign "4.1.0" -pg-pool@^3.2.1: - version "3.2.1" - resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz#5f4afc0f58063659aeefa952d36af49fa28b30e0" - integrity sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA== +pg-pool@^3.2.2: + version "3.2.2" + resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz#a560e433443ed4ad946b84d774b3f22452694dff" + integrity sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA== -pg-protocol@^1.2.5: - version "1.2.5" - resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.5.tgz#28a1492cde11646ff2d2d06bdee42a3ba05f126c" - integrity sha512-1uYCckkuTfzz/FCefvavRywkowa6M5FohNMF5OjKrqo9PSR8gYc8poVmwwYQaBxhmQdBjhtP514eXy9/Us2xKg== +pg-protocol@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.3.0.tgz#3c8fb7ca34dbbfcc42776ce34ac5f537d6e34770" + integrity sha512-64/bYByMrhWULUaCd+6/72c9PMWhiVFs3EVxl9Ct6a3v/U8+rKgqP2w+kKg/BIGgMJyB+Bk/eNivT32Al+Jghw== pg-types@1.*: version "1.13.0" @@ -18309,18 +18367,17 @@ pg@^6.1.0: semver "4.3.2" pg@^8.3.0: - version "8.3.0" - resolved "https://registry.npmjs.org/pg/-/pg-8.3.0.tgz#941383300d38eef51ecb88a0188cec441ab64d81" - integrity sha512-jQPKWHWxbI09s/Z9aUvoTbvGgoj98AU7FDCcQ7kdejupn/TcNpx56v2gaOTzXkzOajmOEJEdi9eTh9cA2RVAjQ== + version "8.4.2" + resolved "https://registry.npmjs.org/pg/-/pg-8.4.2.tgz#2aa58166a23391e91d56a7ea57c6d99931c0642a" + integrity sha512-E9FlUrrc7w3+sbRmL1CSw99vifACzB2TjhMM9J5w9D1LIg+6un0jKkpHS1EQf2CWhKhec2bhrBLVMmUBDbjPRQ== dependencies: buffer-writer "2.0.0" packet-reader "1.0.0" - pg-connection-string "^2.3.0" - pg-pool "^3.2.1" - pg-protocol "^1.2.5" + pg-connection-string "^2.4.0" + pg-pool "^3.2.2" + pg-protocol "^1.3.0" pg-types "^2.1.0" pgpass "1.x" - semver "4.3.2" pgpass@1.*, pgpass@1.x: version "1.0.2" @@ -19209,7 +19266,7 @@ punycode@1.3.2: resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.3.2: +punycode@^1.2.4: version "1.4.1" resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -19254,10 +19311,10 @@ query-string@^4.1.0: object-assign "^4.1.0" strict-uri-encode "^1.0.0" -query-string@^6.12.1: - version "6.13.1" - resolved "https://registry.npmjs.org/query-string/-/query-string-6.13.1.tgz#d913ccfce3b4b3a713989fe6d39466d92e71ccad" - integrity sha512-RfoButmcK+yCta1+FuU8REvisx1oEzhMKwhLUNcepQTPGcNMp1sIqjnfCtfnvGSQZQEhaBHvccujtWoUV3TTbA== +query-string@^6.13.3: + version "6.13.6" + resolved "https://registry.npmjs.org/query-string/-/query-string-6.13.6.tgz#e5ac7c74f2a5da43fbca0b883b4f0bafba439966" + integrity sha512-/WWZ7d9na6s2wMEGdVCVgKWE9Rt7nYyNIf7k8xmHXcesPMlEzicWo3lbYwHyA4wBktI2KrXxxZeACLbE84hvSQ== dependencies: decode-uri-component "^0.2.0" split-on-first "^1.0.0" @@ -19325,16 +19382,6 @@ ramda@^0.26, ramda@~0.26.1: resolved "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== -ramldt2jsonschema@^1.1.0: - version "1.2.3" - resolved "https://registry.npmjs.org/ramldt2jsonschema/-/ramldt2jsonschema-1.2.3.tgz#8d45a7f306a1169a3bde91cab725d1d6d0ff7d55" - integrity sha512-+wLDAV2NNv9NkfEUOYStaDu/6RYgYXeC1zLtXE+dMU/jDfjpN4iJnBGycDwFTFaIQGosOQhxph7fEX6Mpwxdug== - dependencies: - commander "^5.0.0" - js-yaml "^3.14.0" - json-schema-migrate "^0.2.0" - webapi-parser "^0.5.0" - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -19350,11 +19397,6 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -range-parser@1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= - range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -19677,7 +19719,7 @@ react-markdown@^4.3.1: unist-util-visit "^1.3.0" xtend "^4.0.1" -react-markdown@^5.0.0: +react-markdown@^5.0.0, react-markdown@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/react-markdown/-/react-markdown-5.0.2.tgz#d15a8beb37b4ec34fc23dd892e7755eb7040b8db" integrity sha512-kmkB4JbV7LqkDAjvaKRKtodB3n3Id76/DalaDun1U8FuLB0SenPfvH+jAQ5Pcpo54cACRQc1LB1yXmuuuIVecw== @@ -21089,20 +21131,6 @@ serve-favicon@^2.5.0: parseurl "~1.3.2" safe-buffer "5.1.1" -serve-handler@^6.1.3: - version "6.1.3" - resolved "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" - integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== - dependencies: - bytes "3.0.0" - content-disposition "0.5.2" - fast-url-parser "1.1.3" - mime-types "2.1.18" - minimatch "3.0.4" - path-is-inside "1.0.2" - path-to-regexp "2.2.1" - range-parser "1.2.0" - serve-index@^1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -23442,7 +23470,7 @@ upper-case@2.0.1, upper-case@^2.0.1: dependencies: tslib "^1.10.0" -uri-js@^4.2.1, uri-js@^4.2.2: +uri-js@^4.2.2: version "4.2.2" resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== @@ -23828,13 +23856,6 @@ wcwidth@^1.0.0, wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -webapi-parser@^0.5.0: - version "0.5.0" - resolved "https://registry.npmjs.org/webapi-parser/-/webapi-parser-0.5.0.tgz#2632185c5d8f3e6addb2520857af89ea9844dc14" - integrity sha512-fPt6XuMqLSvBz8exwX4QE1UT+pROLHa00EMDCdO0ybICduwQ1V4f7AWX4pNOpCp+x+0FjczEsOxtQU0d8L3QKw== - dependencies: - ajv "6.5.2" - webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"