Merge branch 'master' into timbonicus/docker-tweaks

This commit is contained in:
Tim Hansen
2021-03-04 07:57:38 -07:00
175 changed files with 2253 additions and 1129 deletions
-7
View File
@@ -1,7 +0,0 @@
---
'@backstage/plugin-kubernetes': patch
---
k8s plugin now surfaces k8s components with only label selector query annotation.
Previously backstage.io/kubernetes-label-selector catalog entity annotation would only work if you also included backstage.io/kubernetes-id.
But backstage.io/kubernetes-id value was ignored
-7
View File
@@ -1,7 +0,0 @@
---
'@backstage/plugin-circleci': patch
'@backstage/plugin-cloudbuild': patch
'@backstage/plugin-github-actions': patch
---
Use Breadcrumbs from @backstage/core rather than material-ui
-6
View File
@@ -1,6 +0,0 @@
---
'@backstage/plugin-scaffolder': patch
'@backstage/plugin-scaffolder-backend': patch
---
Move logic for constructing the template form to the backend, using a new `./parameter-schema` endpoint that returns the form schema for a given template.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Bump `@svgr/webpack` from `5.4.x` to `5.5.x`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-techdocs-backend': patch
---
Forward authorization header on backend request if present
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-backend': patch
---
GithubDiscoveryProcessor outputs locations as optional to avoid outputting errors for missing locations (see https://github.com/backstage/backstage/issues/4730).
-6
View File
@@ -1,6 +0,0 @@
---
'@backstage/plugin-api-docs': patch
'@backstage/plugin-catalog': patch
---
Update messaging when no entities are in a table.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog': patch
---
Make the external `createComponent` route optional, hiding the "Create Component" button if it isn't bound.
-7
View File
@@ -1,7 +0,0 @@
---
'@backstage/catalog-model': patch
'@backstage/plugin-catalog-backend': patch
'@backstage/plugin-scaffolder-backend': patch
---
Add version `backstage.io/v1beta2` schema for Template entities.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-sonarqube': patch
---
Collect all available metric types if the number exceeds the default page size of 100.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/backend-common': patch
---
Add optional `logClientErrors` to errorHandler to log 4XX errors
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-proxy-backend': patch
---
Added a verification for well formed URLs when processing proxy targets. Otherwise users gets a cryptic error message thrown from Express which makes it hard to debug.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Consider both authentication methods for both `onprem` and `cloud` BitBucket
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-techdocs-backend': patch
---
Use external url for static docs
-10
View File
@@ -1,10 +0,0 @@
---
'@backstage/techdocs-common': patch
'@backstage/plugin-auth-backend': patch
'@backstage/plugin-kafka-backend': patch
'@backstage/plugin-kubernetes-backend': patch
'@backstage/plugin-scaffolder-backend': patch
'@backstage/plugin-techdocs-backend': patch
---
remove usage of res.send() for res.json() and res.end() to ensure content types are more consistently application/json on backend responses and error cases
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/backend-common': patch
---
Change debug log format to print as color grey
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-scaffolder': patch
---
Tweak the template cards to be even more compliant with MUI examples, and a little bit more dense.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-api-docs': patch
---
Add organization name to the API Explorer page title
-23
View File
@@ -1,23 +0,0 @@
---
'@backstage/create-app': patch
---
The api-docs plugin has been migrated to use an [external route reference](https://backstage.io/docs/plugins/composability#binding-external-routes-in-the-app) to dynamically link to the create component page.
If you want to have a button that links to the scaffolder plugin from the API explorer, apply the following changes to `packages/app/src/App.tsx`:
```diff
+ import { apiDocsPlugin } from '@backstage/plugin-api-docs';
import { scaffolderPlugin } from '@backstage/plugin-scaffolder';
const app = createApp({
// ...
bindRoutes({ bind }) {
+ bind(apiDocsPlugin.externalRoutes, {
+ createComponent: scaffolderPlugin.routes.root,
+ });
},
});
```
If you choose to not bind the routes, the button to create new APIs is not displayed.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-kubernetes-backend': patch
---
Allow apps to pass in a KubernetesClustersSupplier
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-kubernetes': patch
---
Support AWS auth provider on kubernetes FE plugin
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-proxy-backend': patch
---
Fix for proxy-backend plugin when global-agent is enabled
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog': patch
---
Use entity relation for the owner of an entity in the catalog entity page header.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Bump `@testing-library/react` in the plugin template from `^10.4.1` to `^11.2.5`. To apply this to an existing plugin, update the dependency in your `package.json`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-techdocs': minor
---
Add authorization header on techdocs api requests. Breaking change as clients now needs the Identity API.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Fixed an issue where the `backend:dev` command would get stuck executing the backend process multiple times, causing port conflict issues.
-37
View File
@@ -1,37 +0,0 @@
---
'@backstage/plugin-scaffolder': minor
'@backstage/plugin-scaffolder-backend': minor
---
The scaffolder has been updated to support the new `v1beta2` template schema which allows for custom template actions!
See documentation for more information how to create and register new template actions.
**Breaking changes**
The backend scaffolder plugin now needs a `UrlReader` which can be pulled from the PluginEnvironment.
The following change is required in `backend/src/plugins/scaffolder.ts`
```diff
export default async function createPlugin({
logger,
config,
database,
+ reader,
}: PluginEnvironment): Promise<Router> {
// omitted code
return await createRouter({
preparers,
templaters,
publishers,
logger,
config,
dockerClient,
database,
catalogClient,
+ reader,
});
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-import': patch
---
Bump react-hook-form version constraint to "^6.15.4"
-6
View File
@@ -1,6 +0,0 @@
---
'@backstage/core-api': patch
'@backstage/core': patch
---
Added support for optional external route references. By setting `optional: true` when creating an `ExternalRouteRef` it is no longer a requirement to bind the route in the app. If the app isn't bound `useRouteRef` will return `undefined`.
-23
View File
@@ -1,23 +0,0 @@
---
'@backstage/plugin-api-docs': patch
---
The api-docs plugin has been migrated to use an [external route reference](https://backstage.io/docs/plugins/composability#binding-external-routes-in-the-app) to dynamically link to the create component page. This means you need to migrate the api docs plugin to use the new extension components, as well as bind the external route.
To bind the external route from the api docs plugin to the scaffolder template index page, make sure you have the appropriate imports and add the following to the `createApp` call:
```ts
import { apiDocsPlugin } from '@backstage/plugin-api-docs';
import { scaffolderPlugin } from '@backstage/plugin-scaffolder';
const app = createApp({
// ...
bindRoutes({ bind }) {
bind(apiDocsPlugin.externalRoutes, {
createComponent: scaffolderPlugin.routes.root,
});
},
});
```
If you choose to not bind the routes, the button to create new APIs is not displayed.
-6
View File
@@ -1,6 +0,0 @@
---
'@backstage/core-api': patch
'@backstage/core': patch
---
Internal refactor of how component data is access to avoid polluting components and make it possible to bridge across versions.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core': patch
---
Improve rendering of multiple support item links in the `SupportButton`
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-sonarqube': patch
---
Display '-' instead of 'undefined' if no code coverage is reported.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
New config command to export the configuration schema. When running backstage-cli with yarn, consider using `yarn --silent backstage-cli config:schema` to get a clean output on `stdout`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core': patch
---
Added the color prop to TrendLine from the Sparklines props types to be able to have custom colors.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core': patch
---
Added a new useSupportConfig hook that reads a new `app.support` config key. Also updated the SupportButton and ErrorPage components to use the new config.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Fixed file path resolution for templates with a file location
-31
View File
@@ -1,31 +0,0 @@
---
'@backstage/core': minor
'@backstage/plugin-pagerduty': patch
---
- Adds onClick and other props to IconLinkVertical;
- Allows TriggerButton component to render when pager duty key is missing;
- Refactors TriggerButton and PagerDutyCard not to have shared state;
- Removes the `action` prop of the IconLinkVertical component while adding `onClick`.
Instead of having an action including a button with onClick, now the whole component can be clickable making it easier to implement and having a better UX.
Before:
```ts
const myLink: IconLinkVerticalProps = {
label: 'Click me',
action: <Button onClick={myAction} />,
icon: <MyIcon onClick={myAction} />,
};
```
After:
```ts
const myLink: IconLinkVerticalProps = {
label: 'Click me',
onClick: myAction,
icon: <MyIcon />,
};
```
-22
View File
@@ -1,22 +0,0 @@
---
'@backstage/plugin-scaffolder-backend': minor
---
Removed support for deprecated publisher auth configuration within the `scaffolder` configuration block, such as `scaffolder.github.token`. Access should instead be configured through `integrations` configuration.
For example, replace the following configuration in `app-config.yaml`
```yaml
scaffolder:
github:
token: my-token
```
with
```yaml
integrations:
github:
- host: github.com
token: my-token
```
-56
View File
@@ -1,56 +0,0 @@
---
'@backstage/create-app': patch
---
Migrated away from using deprecated routes and router components at top-level in the app, and instead use routable extension pages.
To apply this change to an existing app, make the following changes to `packages/app/src/App.tsx`:
Update imports and remove the usage of the deprecated `app.getRoutes()`.
```diff
-import { Router as DocsRouter } from '@backstage/plugin-techdocs';
+import { TechdocsPage } from '@backstage/plugin-techdocs';
import { CatalogImportPage } from '@backstage/plugin-catalog-import';
-import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar';
-import { SearchPage as SearchRouter } from '@backstage/plugin-search';
-import { Router as SettingsRouter } from '@backstage/plugin-user-settings';
+import { TechRadarPage } from '@backstage/plugin-tech-radar';
+import { SearchPage } from '@backstage/plugin-search';
+import { UserSettingsPage } from '@backstage/plugin-user-settings';
+import { ApiExplorerPage } from '@backstage/plugin-api-docs';
import { EntityPage } from './components/catalog/EntityPage';
import { scaffolderPlugin, ScaffolderPage } from '@backstage/plugin-scaffolder';
const AppProvider = app.getProvider();
const AppRouter = app.getRouter();
-const deprecatedAppRoutes = app.getRoutes();
```
As well as update or add the following routes:
```diff
<Route path="/create" element={<ScaffolderPage />} />
- <Route path="/docs" element={<DocsRouter />} />
+ <Route path="/docs" element={<TechdocsPage />} />
+ <Route path="/api-docs" element={<ApiExplorerPage />} />
<Route
path="/tech-radar"
- element={<TechRadarRouter width={1500} height={800} />}
+ element={<TechRadarPage width={1500} height={800} />}
/>
<Route path="/catalog-import" element={<CatalogImportPage />} />
- <Route
- path="/search"
- element={<SearchRouter/>}
- />
- <Route path="/settings" element={<SettingsRouter />} />
- {deprecatedAppRoutes}
+ <Route path="/search" element={<SearchPage />} />
+ <Route path="/settings" element={<UserSettingsPage />} />
```
If you have added additional plugins with registered routes or are using `Router` components from other plugins, these should be migrated to use the `*Page` components as well. See [this commit](https://github.com/backstage/backstage/commit/abd655e42d4ed416b70848ffdb1c4b99d189f13b) for more examples of how to migrate.
For more information and the background to this change, see the [composability system migration docs](https://backstage.io/docs/plugins/composability).
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-cloudbuild': patch
---
Change terminology for cloudbuild
-25
View File
@@ -1,25 +0,0 @@
---
'@backstage/create-app': patch
---
Updated the default `App` test to work better on Windows.
To apply this change to an existing app, replace the `process.env.APP_CONFIG` definition in `packages/app/src/App.test.tsx` with the following:
```ts
process.env = {
NODE_ENV: 'test',
APP_CONFIG: [
{
data: {
app: { title: 'Test' },
backend: { baseUrl: 'http://localhost:7000' },
techdocs: {
storageUrl: 'http://localhost:7000/api/techdocs/static/docs',
},
},
context: 'test',
},
] as any,
};
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-auth-backend': patch
---
Expose a configuration option for the oidc scope
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog': patch
---
Removed fullScreen property from UnregisterEntity Dialog modal.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-github-actions': patch
---
Use Breadcrumbs from @backstage/core
-7
View File
@@ -1,7 +0,0 @@
---
'@backstage/plugin-jenkins': patch
---
- Add Jenkins logo to project page.
- Move to new Backstage breadcrumb component.
- Change references of deprecated "Job" terminology to "Project" per [Jenkins Glossary](https://www.jenkins.io/doc/book/glossary/).
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Bump `ts-loader` dependency range from `^7.0.4` to `^8.0.17`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-react': patch
---
Fixed EntityProvider setting 'loading' bool erroneously to true
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-lighthouse': patch
---
Change setup wording of intro card to latest
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/techdocs-common': patch
---
Remove read-store-upload loop when uploading S3 objects for TechDocs
+69
View File
@@ -1,5 +1,74 @@
# example-app
## 0.2.18
### Patch Changes
- Updated dependencies [ba21797ca]
- Updated dependencies [b2a5320a4]
- Updated dependencies [12d8f27a6]
- Updated dependencies [507513fed]
- Updated dependencies [32a003973]
- Updated dependencies [40c0fdbaa]
- Updated dependencies [12d8f27a6]
- Updated dependencies [cfc83cac1]
- Updated dependencies [bc327dc42]
- Updated dependencies [2386de1d3]
- Updated dependencies [42c8ebb79]
- Updated dependencies [10362e9eb]
- Updated dependencies [e37d2de99]
- Updated dependencies [813c6a4f2]
- Updated dependencies [11c6208fe]
- Updated dependencies [8106c9528]
- Updated dependencies [05183f202]
- Updated dependencies [40c0fdbaa]
- Updated dependencies [f71589800]
- Updated dependencies [2a271d89e]
- Updated dependencies [bece09057]
- Updated dependencies [d4f0a1406]
- Updated dependencies [169f48deb]
- Updated dependencies [8a1566719]
- Updated dependencies [9d455f69a]
- Updated dependencies [4c049a1a1]
- Updated dependencies [d21058c34]
- Updated dependencies [b33e553b2]
- Updated dependencies [04667f571]
- Updated dependencies [b93538acc]
- Updated dependencies [0452ba238]
- Updated dependencies [8871e7523]
- Updated dependencies [02816ecd7]
- Updated dependencies [dbea11072]
- @backstage/plugin-kubernetes@0.3.12
- @backstage/plugin-circleci@0.2.11
- @backstage/plugin-cloudbuild@0.2.12
- @backstage/plugin-github-actions@0.3.5
- @backstage/plugin-scaffolder@0.7.0
- @backstage/cli@0.6.3
- @backstage/plugin-api-docs@0.4.8
- @backstage/plugin-catalog@0.4.1
- @backstage/catalog-model@0.7.3
- @backstage/plugin-explore@0.3.0
- @backstage/plugin-techdocs@0.6.0
- @backstage/plugin-catalog-import@0.4.3
- @backstage/core@0.7.0
- @backstage/plugin-catalog-react@0.1.1
- @backstage/plugin-pagerduty@0.3.2
- @backstage/plugin-jenkins@0.3.12
- @backstage/plugin-lighthouse@0.2.13
- @backstage/plugin-cost-insights@0.8.3
- @backstage/plugin-gcp-projects@0.2.5
- @backstage/plugin-gitops-profiles@0.2.6
- @backstage/plugin-graphiql@0.2.8
- @backstage/plugin-kafka@0.2.5
- @backstage/plugin-newrelic@0.2.6
- @backstage/plugin-org@0.3.9
- @backstage/plugin-register-component@0.2.12
- @backstage/plugin-rollbar@0.3.3
- @backstage/plugin-search@0.3.3
- @backstage/plugin-sentry@0.3.8
- @backstage/plugin-tech-radar@0.3.7
- @backstage/plugin-user-settings@0.2.7
## 0.2.17
### Patch Changes
+32 -32
View File
@@ -1,39 +1,39 @@
{
"name": "example-app",
"version": "0.2.17",
"version": "0.2.18",
"private": true,
"bundled": true,
"dependencies": {
"@backstage/catalog-model": "^0.7.2",
"@backstage/cli": "^0.6.2",
"@backstage/core": "^0.6.3",
"@backstage/plugin-api-docs": "^0.4.7",
"@backstage/plugin-catalog": "^0.4.0",
"@backstage/plugin-catalog-import": "^0.4.2",
"@backstage/plugin-catalog-react": "^0.1.0",
"@backstage/plugin-circleci": "^0.2.10",
"@backstage/plugin-cloudbuild": "^0.2.11",
"@backstage/plugin-cost-insights": "^0.8.2",
"@backstage/plugin-explore": "^0.2.7",
"@backstage/plugin-gcp-projects": "^0.2.4",
"@backstage/plugin-github-actions": "^0.3.4",
"@backstage/plugin-gitops-profiles": "^0.2.5",
"@backstage/plugin-graphiql": "^0.2.7",
"@backstage/plugin-jenkins": "^0.3.11",
"@backstage/plugin-kafka": "^0.2.4",
"@backstage/plugin-kubernetes": "^0.3.11",
"@backstage/plugin-lighthouse": "^0.2.12",
"@backstage/plugin-newrelic": "^0.2.5",
"@backstage/plugin-org": "^0.3.8",
"@backstage/plugin-pagerduty": "0.3.1",
"@backstage/plugin-register-component": "^0.2.11",
"@backstage/plugin-rollbar": "^0.3.2",
"@backstage/plugin-scaffolder": "^0.6.0",
"@backstage/plugin-sentry": "^0.3.7",
"@backstage/plugin-search": "^0.3.2",
"@backstage/plugin-tech-radar": "^0.3.6",
"@backstage/plugin-techdocs": "^0.5.8",
"@backstage/plugin-user-settings": "^0.2.6",
"@backstage/catalog-model": "^0.7.3",
"@backstage/cli": "^0.6.3",
"@backstage/core": "^0.7.0",
"@backstage/plugin-api-docs": "^0.4.8",
"@backstage/plugin-catalog": "^0.4.1",
"@backstage/plugin-catalog-import": "^0.4.3",
"@backstage/plugin-catalog-react": "^0.1.1",
"@backstage/plugin-circleci": "^0.2.11",
"@backstage/plugin-cloudbuild": "^0.2.12",
"@backstage/plugin-cost-insights": "^0.8.3",
"@backstage/plugin-explore": "^0.3.0",
"@backstage/plugin-gcp-projects": "^0.2.5",
"@backstage/plugin-github-actions": "^0.3.5",
"@backstage/plugin-gitops-profiles": "^0.2.6",
"@backstage/plugin-graphiql": "^0.2.8",
"@backstage/plugin-jenkins": "^0.3.12",
"@backstage/plugin-kafka": "^0.2.5",
"@backstage/plugin-kubernetes": "^0.3.12",
"@backstage/plugin-lighthouse": "^0.2.13",
"@backstage/plugin-newrelic": "^0.2.6",
"@backstage/plugin-org": "^0.3.9",
"@backstage/plugin-pagerduty": "0.3.2",
"@backstage/plugin-register-component": "^0.2.12",
"@backstage/plugin-rollbar": "^0.3.3",
"@backstage/plugin-scaffolder": "^0.7.0",
"@backstage/plugin-sentry": "^0.3.8",
"@backstage/plugin-search": "^0.3.3",
"@backstage/plugin-tech-radar": "^0.3.7",
"@backstage/plugin-techdocs": "^0.6.0",
"@backstage/plugin-user-settings": "^0.2.7",
"@backstage/theme": "^0.2.3",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -41,7 +41,7 @@
"@roadiehq/backstage-plugin-buildkite": "^0.1.3",
"@roadiehq/backstage-plugin-github-insights": "^0.2.16",
"@roadiehq/backstage-plugin-github-pull-requests": "^0.7.6",
"@roadiehq/backstage-plugin-travis-ci": "^0.2.8",
"@roadiehq/backstage-plugin-travis-ci": "^0.4.5",
"history": "^5.0.0",
"prop-types": "^15.7.2",
"react": "^16.12.0",
+4 -1
View File
@@ -33,7 +33,7 @@ import {
CostInsightsPage,
CostInsightsProjectGrowthInstructionsPage,
} from '@backstage/plugin-cost-insights';
import { ExplorePage } from '@backstage/plugin-explore';
import { ExplorePage, explorePlugin } from '@backstage/plugin-explore';
import { GcpProjectsPage } from '@backstage/plugin-gcp-projects';
import { GraphiQLPage } from '@backstage/plugin-graphiql';
import { LighthousePage } from '@backstage/plugin-lighthouse';
@@ -79,6 +79,9 @@ const app = createApp({
bind(apiDocsPlugin.externalRoutes, {
createComponent: scaffolderPlugin.routes.root,
});
bind(explorePlugin.externalRoutes, {
catalogEntity: catalogPlugin.routes.catalogEntity,
});
},
});
+7
View File
@@ -1,5 +1,12 @@
# @backstage/backend-common
## 0.5.5
### Patch Changes
- 497859088: Add optional `logClientErrors` to errorHandler to log 4XX errors
- 8adb48df4: Change debug log format to print as color grey
## 0.5.4
### Patch Changes
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-common",
"description": "Common functionality library for Backstage backends",
"version": "0.5.4",
"version": "0.5.5",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -68,7 +68,7 @@
}
},
"devDependencies": {
"@backstage/cli": "^0.6.1",
"@backstage/cli": "^0.6.3",
"@backstage/test-utils": "^0.1.7",
"@types/archiver": "^5.1.0",
"@types/compression": "^1.7.0",
+32
View File
@@ -1,5 +1,37 @@
# example-backend
## 0.2.18
### Patch Changes
- Updated dependencies [12d8f27a6]
- Updated dependencies [52b5bc3e2]
- Updated dependencies [ecdd407b1]
- Updated dependencies [4fbc9df79]
- Updated dependencies [12d8f27a6]
- Updated dependencies [497859088]
- Updated dependencies [1987c9341]
- Updated dependencies [f31b76b44]
- Updated dependencies [15eee03bc]
- Updated dependencies [f43192207]
- Updated dependencies [8adb48df4]
- Updated dependencies [e3adec2bd]
- Updated dependencies [9ce68b677]
- Updated dependencies [8106c9528]
- Updated dependencies [d0ed25196]
- Updated dependencies [96ccc8f69]
- Updated dependencies [3af994c81]
- @backstage/plugin-scaffolder-backend@0.9.0
- @backstage/plugin-techdocs-backend@0.6.3
- @backstage/plugin-catalog-backend@0.6.4
- @backstage/plugin-kafka-backend@0.2.1
- @backstage/catalog-model@0.7.3
- @backstage/backend-common@0.5.5
- @backstage/plugin-proxy-backend@0.2.5
- @backstage/plugin-auth-backend@0.3.3
- @backstage/plugin-kubernetes-backend@0.2.8
- example-app@0.2.18
## 0.2.17
### Patch Changes
+12 -12
View File
@@ -1,6 +1,6 @@
{
"name": "example-backend",
"version": "0.2.17",
"version": "0.2.18",
"main": "dist/index.cjs.js",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -27,25 +27,25 @@
"migrate:create": "knex migrate:make -x ts"
},
"dependencies": {
"@backstage/backend-common": "^0.5.3",
"@backstage/backend-common": "^0.5.5",
"@backstage/catalog-client": "^0.3.6",
"@backstage/catalog-model": "^0.7.2",
"@backstage/catalog-model": "^0.7.3",
"@backstage/config": "^0.1.3",
"@backstage/plugin-app-backend": "^0.3.8",
"@backstage/plugin-auth-backend": "^0.3.2",
"@backstage/plugin-catalog-backend": "^0.6.3",
"@backstage/plugin-auth-backend": "^0.3.3",
"@backstage/plugin-catalog-backend": "^0.6.4",
"@backstage/plugin-graphql-backend": "^0.1.5",
"@backstage/plugin-kubernetes-backend": "^0.2.7",
"@backstage/plugin-kafka-backend": "^0.2.0",
"@backstage/plugin-proxy-backend": "^0.2.4",
"@backstage/plugin-kubernetes-backend": "^0.2.8",
"@backstage/plugin-kafka-backend": "^0.2.1",
"@backstage/plugin-proxy-backend": "^0.2.5",
"@backstage/plugin-rollbar-backend": "^0.1.7",
"@backstage/plugin-scaffolder-backend": "^0.8.0",
"@backstage/plugin-techdocs-backend": "^0.6.2",
"@backstage/plugin-scaffolder-backend": "^0.9.0",
"@backstage/plugin-techdocs-backend": "^0.6.3",
"@gitbeaker/node": "^28.0.2",
"@octokit/rest": "^18.0.12",
"azure-devops-node-api": "^10.1.1",
"dockerode": "^3.2.1",
"example-app": "^0.2.17",
"example-app": "^0.2.18",
"express": "^4.17.1",
"express-promise-router": "^3.0.3",
"knex": "^0.21.6",
@@ -55,7 +55,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/cli": "^0.6.3",
"@types/dockerode": "^3.2.1",
"@types/express": "^4.17.6",
"@types/express-serve-static-core": "^4.17.5"
+6
View File
@@ -1,5 +1,11 @@
# @backstage/catalog-model
## 0.7.3
### Patch Changes
- 12d8f27a6: Add version `backstage.io/v1beta2` schema for Template entities.
## 0.7.2
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/catalog-model",
"version": "0.7.2",
"version": "0.7.3",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -39,7 +39,7 @@
"yup": "^0.29.3"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/cli": "^0.6.3",
"@types/express": "^4.17.6",
"@types/jest": "^26.0.7",
"@types/lodash": "^4.14.151",
+11
View File
@@ -1,5 +1,16 @@
# @backstage/cli
## 0.6.3
### Patch Changes
- 507513fed: Bump `@svgr/webpack` from `5.4.x` to `5.5.x`.
- e37d2de99: Bump `@testing-library/react` in the plugin template from `^10.4.1` to `^11.2.5`. To apply this to an existing plugin, update the dependency in your `package.json`.
- 11c6208fe: Fixed an issue where the `backend:dev` command would get stuck executing the backend process multiple times, causing port conflict issues.
- d4f0a1406: New config command to export the configuration schema. When running backstage-cli with yarn, consider using `yarn --silent backstage-cli config:schema` to get a clean output on `stdout`.
- b93538acc: Fix for type declaration input being required for build even if types aren't being built.
- 8871e7523: Bump `ts-loader` dependency range from `^7.0.4` to `^8.0.17`.
## 0.6.2
### Patch Changes
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/cli",
"description": "CLI for developing Backstage plugins and apps",
"version": "0.6.2",
"version": "0.6.3",
"private": false,
"publishConfig": {
"access": "public"
@@ -117,10 +117,10 @@
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/backend-common": "^0.5.4",
"@backstage/backend-common": "^0.5.5",
"@backstage/config": "^0.1.3",
"@backstage/core": "^0.6.3",
"@backstage/dev-utils": "^0.1.12",
"@backstage/core": "^0.7.0",
"@backstage/dev-utils": "^0.1.13",
"@backstage/test-utils": "^0.1.8",
"@backstage/theme": "^0.2.3",
"@types/diff": "^5.0.0",
+16 -16
View File
@@ -36,22 +36,6 @@ import { svgrTemplate } from '../svgrTemplate';
export const makeConfigs = async (
options: BuildOptions,
): Promise<RollupOptions[]> => {
const typesInput = paths.resolveTargetRoot(
'dist-types',
relativePath(paths.targetRoot, paths.targetDir),
'src/index.d.ts',
);
const declarationsExist = await fs.pathExists(typesInput);
if (!declarationsExist) {
const path = relativePath(paths.targetDir, typesInput);
throw new Error(
`No declaration files found at ${path}, be sure to run ${chalk.bgRed.white(
'yarn tsc',
)} to generate .d.ts files before packaging`,
);
}
const configs = new Array<RollupOptions>();
if (options.outputs.has(Output.cjs) || options.outputs.has(Output.esm)) {
@@ -112,6 +96,22 @@ export const makeConfigs = async (
}
if (options.outputs.has(Output.types)) {
const typesInput = paths.resolveTargetRoot(
'dist-types',
relativePath(paths.targetRoot, paths.targetDir),
'src/index.d.ts',
);
const declarationsExist = await fs.pathExists(typesInput);
if (!declarationsExist) {
const path = relativePath(paths.targetDir, typesInput);
throw new Error(
`No declaration files found at ${path}, be sure to run ${chalk.bgRed.white(
'yarn tsc',
)} to generate .d.ts files before packaging`,
);
}
configs.push({
input: typesInput,
output: {
@@ -1,11 +1,10 @@
import React from 'react';
import { render } from '@testing-library/react';
import { ExampleComponent } from './ExampleComponent';
import { ThemeProvider } from '@material-ui/core';
import { lightTheme } from '@backstage/theme';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { msw } from '@backstage/test-utils';
import { msw, renderInTestApp } from '@backstage/test-utils';
describe('ExampleComponent', () => {
const server = setupServer();
@@ -19,8 +18,8 @@ describe('ExampleComponent', () => {
);
});
it('should render', () => {
const rendered = render(
it('should render', async () => {
const rendered = await renderInTestApp(
<ThemeProvider theme={lightTheme}>
<ExampleComponent />
</ThemeProvider>,
+7
View File
@@ -1,5 +1,12 @@
# @backstage/core-api
## 0.2.12
### Patch Changes
- 40c0fdbaa: Added support for optional external route references. By setting `optional: true` when creating an `ExternalRouteRef` it is no longer a requirement to bind the route in the app. If the app isn't bound `useRouteRef` will return `undefined`.
- 2a271d89e: Internal refactor of how component data is access to avoid polluting components and make it possible to bridge across versions.
## 0.2.11
### Patch Changes
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core-api",
"description": "Internal Core API used by Backstage plugins and apps",
"version": "0.2.11",
"version": "0.2.12",
"private": false,
"publishConfig": {
"access": "public",
@@ -42,7 +42,7 @@
"zen-observable": "^0.8.15"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/cli": "^0.6.3",
"@backstage/test-utils": "^0.1.8",
"@backstage/test-utils-core": "^0.1.1",
"@testing-library/jest-dom": "^5.10.1",
+91 -37
View File
@@ -50,23 +50,30 @@ describe('generateBoundRoutes', () => {
describe('Integration Test', () => {
const plugin1RouteRef = createRouteRef({ path: '/blah1', title: '' });
const plugin2RouteRef = createRouteRef({ path: '/blah2', title: '' });
const externalRouteRef = createExternalRouteRef({ id: '3' });
const optionalBarExternalRouteRef = createExternalRouteRef({
id: 'bar',
const plugin2RouteRef = createRouteRef({
path: '/blah2',
title: '',
params: ['x'],
});
const err = createExternalRouteRef({ id: 'err' });
const errParams = createExternalRouteRef({ id: 'errParams', params: ['x'] });
const errOptional = createExternalRouteRef({
id: 'errOptional',
optional: true,
});
const optionalBazExternalRouteRef = createExternalRouteRef({
id: 'baz',
const errParamsOptional = createExternalRouteRef({
id: 'errParamsOptional',
optional: true,
params: ['x'],
});
const plugin1 = createPlugin({
id: 'blob',
externalRoutes: {
foo: externalRouteRef,
bar: optionalBarExternalRouteRef,
baz: optionalBazExternalRouteRef,
err,
errParams,
errOptional,
errParamsOptional,
},
});
@@ -85,14 +92,19 @@ describe('Integration Test', () => {
createRoutableExtension({
component: () =>
Promise.resolve((_: PropsWithChildren<{ path?: string }>) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const externalLink = useRouteRef(externalRouteRef);
const barLink = useRouteRef(optionalBarExternalRouteRef);
const bazLink = useRouteRef(optionalBazExternalRouteRef);
const errLink = useRouteRef(err);
const errParamsLink = useRouteRef(errParams);
const errOptionalLink = useRouteRef(errOptional);
const errParamsOptionalLink = useRouteRef(errParamsOptional);
return (
<div>
Our routes are: {externalLink()}, bar: {barLink?.() ?? 'none'},
baz: {bazLink?.() ?? 'none'}
<span>err: {errLink()}</span>
<span>errParams: {errParamsLink({ x: 'a' })}</span>
<span>errOptional: {errOptionalLink?.() ?? '<none>'}</span>
<span>
errParamsOptional:{' '}
{errParamsOptionalLink?.({ x: 'b' }) ?? '<none>'}
</span>
</div>
);
}),
@@ -100,14 +112,14 @@ describe('Integration Test', () => {
}),
);
it('runs happy paths', async () => {
const components = {
NotFoundErrorPage: () => null,
BootErrorPage: () => null,
Progress: () => null,
Router: BrowserRouter,
};
const components = {
NotFoundErrorPage: () => null,
BootErrorPage: () => null,
Progress: () => null,
Router: BrowserRouter,
};
it('runs happy paths', async () => {
const app = new PrivateAppImpl({
apis: [],
defaultApis: [],
@@ -124,8 +136,10 @@ describe('Integration Test', () => {
components,
bindRoutes: ({ bind }) => {
bind(plugin1.externalRoutes, {
foo: plugin2RouteRef,
bar: plugin2RouteRef,
err: plugin1RouteRef,
errParams: plugin2RouteRef,
errOptional: plugin1RouteRef,
errParamsOptional: plugin2RouteRef,
});
},
});
@@ -138,25 +152,19 @@ describe('Integration Test', () => {
<Router>
<Routes>
<ExposedComponent path="/" />
<HiddenComponent path="/foo/bar" />
<HiddenComponent path="/foo" />
</Routes>
</Router>
</Provider>,
);
expect(
screen.getByText('Our routes are: /foo/bar, bar: /foo/bar, baz: none'),
).toBeInTheDocument();
expect(screen.getByText('err: /')).toBeInTheDocument();
expect(screen.getByText('errParams: /foo')).toBeInTheDocument();
expect(screen.getByText('errOptional: /')).toBeInTheDocument();
expect(screen.getByText('errParamsOptional: /foo')).toBeInTheDocument();
});
it('should throw some error when the route has duplicate params', () => {
const components = {
NotFoundErrorPage: () => null,
BootErrorPage: () => null,
Progress: () => null,
Router: BrowserRouter,
};
it('runs happy paths without optional routes', async () => {
const app = new PrivateAppImpl({
apis: [],
defaultApis: [],
@@ -172,7 +180,53 @@ describe('Integration Test', () => {
plugins: [],
components,
bindRoutes: ({ bind }) => {
bind(plugin1.externalRoutes, { foo: plugin2RouteRef });
bind(plugin1.externalRoutes, {
err: plugin1RouteRef,
errParams: plugin2RouteRef,
});
},
});
const Provider = app.getProvider();
const Router = app.getRouter();
await renderWithEffects(
<Provider>
<Router>
<Routes>
<ExposedComponent path="/" />
<HiddenComponent path="/foo" />
</Routes>
</Router>
</Provider>,
);
expect(screen.getByText('err: /')).toBeInTheDocument();
expect(screen.getByText('errParams: /foo')).toBeInTheDocument();
expect(screen.getByText('errOptional: <none>')).toBeInTheDocument();
expect(screen.getByText('errParamsOptional: <none>')).toBeInTheDocument();
});
it('should throw some error when the route has duplicate params', () => {
const app = new PrivateAppImpl({
apis: [],
defaultApis: [],
themes: [
{
id: 'light',
title: 'Light Theme',
variant: 'light',
theme: lightTheme,
},
],
icons: defaultSystemIcons,
plugins: [],
components,
bindRoutes: ({ bind }) => {
bind(plugin1.externalRoutes, {
err: plugin1RouteRef,
errParams: plugin2RouteRef,
});
},
});
+3 -3
View File
@@ -50,14 +50,14 @@ import {
} from '../extensions/traversal';
import { IconComponent, IconComponentMap, IconKey } from '../icons';
import { BackstagePlugin } from '../plugin';
import { RouteRef } from '../routing';
import { AnyRoutes } from '../plugin/types';
import { RouteRef, ExternalRouteRef } from '../routing';
import {
routeObjectCollector,
routeParentCollector,
routePathCollector,
} from '../routing/collectors';
import { RoutingProvider, validateRoutes } from '../routing/hooks';
import { ExternalRouteRef } from '../routing/RouteRef';
import { AppContextProvider } from './AppContext';
import { AppIdentity } from './AppIdentity';
import { AppThemeProvider } from './AppThemeProvider';
@@ -78,7 +78,7 @@ export function generateBoundRoutes(
const result = new Map<ExternalRouteRef, RouteRef>();
if (bindRoutes) {
const bind: AppRouteBinder = (externalRoutes, targetRoutes) => {
const bind: AppRouteBinder = (externalRoutes, targetRoutes: AnyRoutes) => {
for (const [key, value] of Object.entries(targetRoutes)) {
const externalRoute = externalRoutes[key];
if (!externalRoute) {
+21 -31
View File
@@ -16,7 +16,7 @@
import { ComponentType } from 'react';
import { IconComponent, IconComponentMap, IconKey } from '../icons';
import { BackstagePlugin } from '../plugin/types';
import { AnyExternalRoutes, BackstagePlugin } from '../plugin/types';
import { ExternalRouteRef, RouteRef } from '../routing';
import { AnyApiFactory } from '../apis';
import { AppTheme, ProfileInfo } from '../apis/definitions';
@@ -79,49 +79,39 @@ export type AppComponents = {
*/
export type AppConfigLoader = () => Promise<AppConfig[]>;
/**
* Extracts the Optional type of a map of ExternalRouteRefs, leaving only the boolean in place as value
*/
type ExternalRouteRefsToOptionalMap<
T extends { [name in string]: ExternalRouteRef<boolean> }
> = {
[name in keyof T]: T[name] extends ExternalRouteRef<infer U> ? U : never;
};
/**
* Extracts a union of the keys in a map whose value extends the given type
*/
type ExtractKeysWithType<Obj extends { [key in string]: any }, Type> = {
type KeysWithType<Obj extends { [key in string]: any }, Type> = {
[key in keyof Obj]: Obj[key] extends Type ? key : never;
}[keyof Obj];
/**
* Given a map of boolean values denoting whether a route is optional, create a
* map of needed RouteRefs.
*
* For example { foo: false, bar: true } gives { foo: RouteRef<any>, bar?: RouteRef<any> }
* Takes a map Map required values and makes all keys matching Keys optional
*/
type CombineOptionalAndRequiredRoutes<
OptionalMap extends { [key in string]: boolean }
> = {
[name in ExtractKeysWithType<OptionalMap, false>]: RouteRef<any>;
} &
{ [name in keyof OptionalMap]?: RouteRef<any> };
type PartialKeys<
Map extends { [name in string]: any },
Keys extends keyof Map
> = Partial<Pick<Map, Keys>> & Required<Omit<Map, Keys>>;
/**
* Creates a map of required target routes based on whether the input external
* routes are optional or not. The external routes that are marked as optional
* will also be optional in the target routes map.
* Creates a map of target routes with matching parameters based on a map of external routes.
*/
type TargetRoutesMap<
T extends { [name in string]: ExternalRouteRef<boolean> }
> = CombineOptionalAndRequiredRoutes<ExternalRouteRefsToOptionalMap<T>>;
type TargetRouteMap<ExternalRoutes extends AnyExternalRoutes> = {
[name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef<
infer Params,
any
>
? RouteRef<Params>
: never;
};
export type AppRouteBinder = <
ExternalRoutes extends { [name in string]: ExternalRouteRef<boolean> }
>(
export type AppRouteBinder = <ExternalRoutes extends AnyExternalRoutes>(
externalRoutes: ExternalRoutes,
targetRoutes: TargetRoutesMap<ExternalRoutes>,
targetRoutes: PartialKeys<
TargetRouteMap<ExternalRoutes>,
KeysWithType<ExternalRoutes, ExternalRouteRef<any, true>>
>,
) => void;
export type AppOptions = {
@@ -100,19 +100,16 @@ describe('elementData', () => {
const element = <Component />;
const container = (global as any)[
'__@backstage/component-data-store__'
].store.get(element.type);
].get(element.type);
expect(container.map.get('my-data')).toBe(data);
});
it('should should be able to attach data for newer versions', () => {
const data = { foo: 'bar' };
const Component = () => null;
(global as any)['__@backstage/component-data-store__'].store.set(
Component,
{
map: new Map([['my-data', data]]),
},
);
(global as any)['__@backstage/component-data-store__'].set(Component, {
map: new Map([['my-data', data]]),
});
const element = <Component />;
expect(getComponentData(element, 'my-data')).toBe(data);
@@ -33,9 +33,10 @@ type MaybeComponentNode = ReactNode & {
};
// The store is bridged across versions using the global object
const { store } = getGlobalSingleton('component-data-store', () => ({
store: new WeakMap<ComponentType<any>, DataContainer>(),
}));
const store = getGlobalSingleton(
'component-data-store',
() => new WeakMap<ComponentType<any>, DataContainer>(),
);
export function attachComponentData<P>(
component: ComponentType<P>,
+1 -2
View File
@@ -15,9 +15,8 @@
*/
import { ComponentType } from 'react';
import { RouteRef } from '../routing';
import { RouteRef, ExternalRouteRef } from '../routing';
import { AnyApiFactory } from '../apis/system';
import { ExternalRouteRef } from '../routing/RouteRef';
export type RouteOptions = {
// Whether the route path must match exactly, defaults to true.
+65 -28
View File
@@ -14,19 +14,40 @@
* limitations under the License.
*/
import { RouteRef } from './types';
import {
RouteRef,
ExternalRouteRef,
routeRefType,
AnyParams,
ParamKeys,
} from './types';
import { IconComponent } from '../icons';
export type RouteRefConfig<Params extends { [param in string]: string }> = {
params?: Array<keyof Params>;
/** @deprecated Route refs no longer decide their own path */
// TODO(Rugvip): Remove this once we get rid of the deprecated fields, it's not exported
export type RouteRefConfig<Params extends AnyParams> = {
params?: ParamKeys<Params>;
path?: string;
icon?: IconComponent;
title: string;
};
export class AbsoluteRouteRef<Params extends { [param in string]: string }> {
constructor(private readonly config: RouteRefConfig<Params>) {}
class RouteRefBase {
constructor(type: string, id: string) {
this.toString = () => `routeRef{type=${type},id=${id}}`;
}
}
export class RouteRefImpl<Params extends AnyParams> extends RouteRefBase
implements RouteRef<Params> {
readonly [routeRefType] = 'absolute';
constructor(private readonly config: RouteRefConfig<Params>) {
super('absolute', config.title);
}
get params(): ParamKeys<Params> {
return this.config.params as any;
}
get icon() {
return this.config.icon;
@@ -40,12 +61,12 @@ export class AbsoluteRouteRef<Params extends { [param in string]: string }> {
get title() {
return this.config.title;
}
toString() {
return `routeRef{title=${this.title}}`;
}
}
type OptionalParams<
Params extends { [param in string]: string }
> = Params[keyof Params] extends never ? undefined : Params;
export function createRouteRef<
// Params is the type that we care about and the one to be embedded in the route ref.
// For example, given the params ['name', 'kind'], Params will be {name: string, kind: string}
@@ -58,27 +79,47 @@ export function createRouteRef<
params?: ParamKey[];
/** @deprecated Route refs no longer decide their own path */
path?: string;
/** @deprecated Route refs no longer decide their own icon */
icon?: IconComponent;
/** @deprecated Route refs no longer decide their own title */
title: string;
}): RouteRef<Params> {
return new AbsoluteRouteRef<Params>(config);
}): RouteRef<OptionalParams<Params>> {
return new RouteRefImpl<OptionalParams<Params>>({
...config,
params: (config.params ?? []) as ParamKeys<OptionalParams<Params>>,
});
}
export class ExternalRouteRef<Optional extends boolean = true> {
readonly optional: boolean;
export class ExternalRouteRefImpl<
Params extends AnyParams,
Optional extends boolean
> extends RouteRefBase implements ExternalRouteRef<Params, Optional> {
readonly [routeRefType] = 'external';
private constructor({ id, optional }: ExternalRouteRefOptions<Optional>) {
this.toString = () => `externalRouteRef{${id}}`;
this.optional = Boolean(optional);
constructor(
id: string,
readonly params: ParamKeys<Params>,
readonly optional: Optional,
) {
super('external', id);
}
}
export type ExternalRouteRefOptions<Optional extends boolean = false> = {
export function createExternalRouteRef<
Params extends { [param in ParamKey]: string },
Optional extends boolean = false,
ParamKey extends string = never
>(options: {
/**
* An identifier for this route, used to identify it in error messages
*/
id: string;
/**
* The parameters that will be provided to the external route reference.
*/
params?: ParamKey[];
/**
* Whether or not this route is optional, defaults to false.
*
@@ -86,14 +127,10 @@ export type ExternalRouteRefOptions<Optional extends boolean = false> = {
* if they aren't, `useRouteRef` will return `undefined`.
*/
optional?: Optional;
};
export function createExternalRouteRef<Optional extends boolean = false>(
options: ExternalRouteRefOptions<Optional>,
): ExternalRouteRef<Optional> {
return new ((ExternalRouteRef as unknown) as {
new (options: ExternalRouteRefOptions<Optional>): ExternalRouteRef<
Optional
>;
})(options);
}): ExternalRouteRef<OptionalParams<Params>, Optional> {
return new ExternalRouteRefImpl<OptionalParams<Params>, Optional>(
options.id,
(options.params ?? []) as ParamKeys<OptionalParams<Params>>,
Boolean(options.optional) as Optional,
);
}
+11 -5
View File
@@ -38,10 +38,9 @@ import {
import {
createRouteRef,
createExternalRouteRef,
ExternalRouteRef,
RouteRefConfig,
} from './RouteRef';
import { AnyRouteRef, RouteRef } from './types';
import { AnyRouteRef, RouteRef, ExternalRouteRef } from './types';
const mockConfig = (extra?: Partial<RouteRefConfig<{}>>) => ({
path: '/unused',
@@ -58,12 +57,19 @@ const ref1 = createRouteRef(mockConfig({ path: '/wat1' }));
const ref2 = createRouteRef(mockConfig({ path: '/wat2' }));
const ref3 = createRouteRef(mockConfig({ path: '/wat3' }));
const ref4 = createRouteRef(mockConfig({ path: '/wat4' }));
const ref5 = createRouteRef(mockConfig({ path: '/wat5' }));
const ref5 = createRouteRef({
...mockConfig({ path: '/wat5' }),
params: ['x'],
});
const eRefA = createExternalRouteRef({ id: '1' });
const eRefB = createExternalRouteRef({ id: '2' });
const eRefC = createExternalRouteRef({ id: '3' });
const eRefC = createExternalRouteRef({ id: '3', params: ['y'] });
const eRefD = createExternalRouteRef({ id: '4', optional: true });
const eRefE = createExternalRouteRef({ id: '5', optional: true });
const eRefE = createExternalRouteRef({
id: '5',
optional: true,
params: ['z'],
});
const MockRouteSource = <T extends { [name in string]: string }>(props: {
path?: string;
+17 -14
View File
@@ -15,19 +15,22 @@
*/
import React, { createContext, ReactNode, useContext, useMemo } from 'react';
import { AnyRouteRef, BackstageRouteObject, RouteRef } from './types';
import {
AnyRouteRef,
BackstageRouteObject,
RouteRef,
ExternalRouteRef,
AnyParams,
} from './types';
import { generatePath, matchRoutes, useLocation } from 'react-router-dom';
import { ExternalRouteRef } from './RouteRef';
// The extra TS magic here is to require a single params argument if the RouteRef
// had at least one param defined, but require 0 arguments if there are no params defined.
// Without this we'd have to pass in empty object to all parameter-less RouteRefs
// just to make TypeScript happy, or we would have to make the argument optional in
// which case you might forget to pass it in when it is actually required.
export type RouteFunc<Params extends { [param in string]: string }> = (
...[params]: Params[keyof Params] extends never
? readonly []
: readonly [Params]
export type RouteFunc<Params extends AnyParams> = (
...[params]: Params extends undefined ? readonly [] : readonly [Params]
) => string;
class RouteResolver {
@@ -38,8 +41,8 @@ class RouteResolver {
private readonly routeBindings: Map<RouteRef | ExternalRouteRef, RouteRef>,
) {}
resolve<Params extends { [param in string]: string }>(
routeRefOrExternalRouteRef: RouteRef<Params> | ExternalRouteRef,
resolve<Params extends AnyParams>(
routeRefOrExternalRouteRef: RouteRef<Params> | ExternalRouteRef<Params>,
sourceLocation: ReturnType<typeof useLocation>,
): RouteFunc<Params> | undefined {
const routeRef =
@@ -112,14 +115,14 @@ class RouteResolver {
const RoutingContext = createContext<RouteResolver | undefined>(undefined);
export function useRouteRef<Optional extends boolean>(
routeRef: ExternalRouteRef<Optional>,
): Optional extends true ? RouteFunc<{}> | undefined : RouteFunc<{}>;
export function useRouteRef<Params extends { [param in string]: string } = {}>(
export function useRouteRef<Optional extends boolean, Params extends AnyParams>(
routeRef: ExternalRouteRef<Params, Optional>,
): Optional extends true ? RouteFunc<Params> | undefined : RouteFunc<Params>;
export function useRouteRef<Params extends AnyParams>(
routeRef: RouteRef<Params>,
): RouteFunc<Params>;
export function useRouteRef<Params extends { [param in string]: string } = {}>(
routeRef: RouteRef<Params> | ExternalRouteRef,
export function useRouteRef<Params extends AnyParams>(
routeRef: RouteRef<Params> | ExternalRouteRef<Params, any>,
): RouteFunc<Params> | undefined {
const sourceLocation = useLocation();
const resolver = useContext(RoutingContext);
+2 -5
View File
@@ -19,12 +19,9 @@ export type {
AbsoluteRouteRef,
ConcreteRoute,
MutableRouteRef,
ExternalRouteRef,
} from './types';
export { FlatRoutes } from './FlatRoutes';
export {
createRouteRef,
createExternalRouteRef,
ExternalRouteRef,
} from './RouteRef';
export { createRouteRef, createExternalRouteRef } from './RouteRef';
export type { RouteRefConfig } from './RouteRef';
export { useRouteRef } from './hooks';
+36 -20
View File
@@ -15,35 +15,51 @@
*/
import { IconComponent } from '../icons';
import { ExternalRouteRef } from './RouteRef';
import { getGlobalSingleton } from '../lib/globalObject';
// @ts-ignore, we're just embedding the Params type for usage in other places
export type RouteRef<Params extends { [param in string]: string } = {}> = {
// TODO(Rugvip): Remove path, look up via registry instead
export type AnyParams = { [param in string]: string } | undefined;
export type ParamKeys<Params extends AnyParams> = keyof Params extends never
? []
: (keyof Params)[];
export const routeRefType: unique symbol = getGlobalSingleton<any>(
'route-ref-type',
() => Symbol('route-ref-type'),
);
export type RouteRef<Params extends AnyParams = any> = {
readonly [routeRefType]: 'absolute';
params: ParamKeys<Params>;
// TODO(Rugvip): Remove all of these once plugins don't rely on the path
/** @deprecated paths are no longer accessed directly from RouteRefs, use useRouteRef instead */
path: string;
/** @deprecated icons are no longer accessed via RouteRefs */
icon?: IconComponent;
title: string;
/** @deprecated titles are no longer accessed via RouteRefs */
title?: string;
};
export type AnyRouteRef = RouteRef<any> | ExternalRouteRef<any>;
export type ExternalRouteRef<
Params extends AnyParams = any,
Optional extends boolean = any
> = {
readonly [routeRefType]: 'external';
/**
* This type should not be used
* @deprecated
*/
params: ParamKeys<Params>;
optional?: Optional;
};
export type AnyRouteRef = RouteRef<any> | ExternalRouteRef<any, any>;
// TODO(Rugvip): None of these should be found in the wild anymore, remove in next minor release
/** @deprecated */
export type ConcreteRoute = {};
/**
* This type should not be used, use RouteRef instead
* @deprecated
*/
/** @deprecated */
export type AbsoluteRouteRef = RouteRef<{}>;
/**
* This type should not be used, use RouteRef instead
* @deprecated
*/
/** @deprecated */
export type MutableRouteRef = RouteRef<{}>;
// A duplicate of the react-router RouteObject, but with routeRef added
+43
View File
@@ -1,5 +1,48 @@
# @backstage/core
## 0.7.0
### Minor Changes
- 4c049a1a1: - Adds onClick and other props to IconLinkVertical;
- Allows TriggerButton component to render when pager duty key is missing;
- Refactors TriggerButton and PagerDutyCard not to have shared state;
- Removes the `action` prop of the IconLinkVertical component while adding `onClick`.
Instead of having an action including a button with onClick, now the whole component can be clickable making it easier to implement and having a better UX.
Before:
```ts
const myLink: IconLinkVerticalProps = {
label: 'Click me',
action: <Button onClick={myAction} />,
icon: <MyIcon onClick={myAction} />,
};
```
After:
```ts
const myLink: IconLinkVerticalProps = {
label: 'Click me',
onClick: myAction,
icon: <MyIcon />,
};
```
### Patch Changes
- 40c0fdbaa: Added support for optional external route references. By setting `optional: true` when creating an `ExternalRouteRef` it is no longer a requirement to bind the route in the app. If the app isn't bound `useRouteRef` will return `undefined`.
- 2a271d89e: Internal refactor of how component data is access to avoid polluting components and make it possible to bridge across versions.
- bece09057: Improve rendering of multiple support item links in the `SupportButton`
- 169f48deb: Added the color prop to TrendLine from the Sparklines props types to be able to have custom colors.
- 8a1566719: Added a new useSupportConfig hook that reads a new `app.support` config key. Also updated the SupportButton and ErrorPage components to use the new config.
- Updated dependencies [40c0fdbaa]
- Updated dependencies [2a271d89e]
- @backstage/core-api@0.2.12
## 0.6.3
### Patch Changes
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core",
"description": "Core API used by Backstage plugins and apps",
"version": "0.6.3",
"version": "0.7.0",
"private": false,
"publishConfig": {
"access": "public",
@@ -30,7 +30,7 @@
},
"dependencies": {
"@backstage/config": "^0.1.3",
"@backstage/core-api": "^0.2.11",
"@backstage/core-api": "^0.2.12",
"@backstage/theme": "^0.2.3",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -68,7 +68,7 @@
"zen-observable": "^0.8.15"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/cli": "^0.6.3",
"@backstage/test-utils": "^0.1.8",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
+162
View File
@@ -1,5 +1,167 @@
# @backstage/create-app
## 0.3.12
### Patch Changes
- f71589800: The api-docs plugin has been migrated to use an [external route reference](https://backstage.io/docs/plugins/composability#binding-external-routes-in-the-app) to dynamically link to the create component page.
If you want to have a button that links to the scaffolder plugin from the API explorer, apply the following changes to `packages/app/src/App.tsx`:
```diff
+ import { apiDocsPlugin } from '@backstage/plugin-api-docs';
import { scaffolderPlugin } from '@backstage/plugin-scaffolder';
const app = createApp({
// ...
bindRoutes({ bind }) {
+ bind(apiDocsPlugin.externalRoutes, {
+ createComponent: scaffolderPlugin.routes.root,
+ });
},
});
```
If you choose to not bind the routes, the button to create new APIs is not displayed.
- 7a1b2ba0e: Migrated away from using deprecated routes and router components at top-level in the app, and instead use routable extension pages.
To apply this change to an existing app, make the following changes to `packages/app/src/App.tsx`:
Update imports and remove the usage of the deprecated `app.getRoutes()`.
```diff
-import { Router as DocsRouter } from '@backstage/plugin-techdocs';
+import { TechdocsPage } from '@backstage/plugin-techdocs';
import { CatalogImportPage } from '@backstage/plugin-catalog-import';
-import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar';
-import { SearchPage as SearchRouter } from '@backstage/plugin-search';
-import { Router as SettingsRouter } from '@backstage/plugin-user-settings';
+import { TechRadarPage } from '@backstage/plugin-tech-radar';
+import { SearchPage } from '@backstage/plugin-search';
+import { UserSettingsPage } from '@backstage/plugin-user-settings';
+import { ApiExplorerPage } from '@backstage/plugin-api-docs';
import { EntityPage } from './components/catalog/EntityPage';
import { scaffolderPlugin, ScaffolderPage } from '@backstage/plugin-scaffolder';
```
const AppProvider = app.getProvider();
const AppRouter = app.getRouter();
-const deprecatedAppRoutes = app.getRoutes();
````
As well as update or add the following routes:
```diff
<Route path="/create" element={<ScaffolderPage />} />
- <Route path="/docs" element={<DocsRouter />} />
+ <Route path="/docs" element={<TechdocsPage />} />
+ <Route path="/api-docs" element={<ApiExplorerPage />} />
<Route
path="/tech-radar"
- element={<TechRadarRouter width={1500} height={800} />}
+ element={<TechRadarPage width={1500} height={800} />}
/>
<Route path="/catalog-import" element={<CatalogImportPage />} />
- <Route
- path="/search"
- element={<SearchRouter/>}
- />
- <Route path="/settings" element={<SettingsRouter />} />
- {deprecatedAppRoutes}
+ <Route path="/search" element={<SearchPage />} />
+ <Route path="/settings" element={<UserSettingsPage />} />
````
If you have added additional plugins with registered routes or are using `Router` components from other plugins, these should be migrated to use the `*Page` components as well. See [this commit](https://github.com/backstage/backstage/commit/abd655e42d4ed416b70848ffdb1c4b99d189f13b) for more examples of how to migrate.
For more information and the background to this change, see the [composability system migration docs](https://backstage.io/docs/plugins/composability).
- 415a3a42d: Updated the default `App` test to work better on Windows.
To apply this change to an existing app, replace the `process.env.APP_CONFIG` definition in `packages/app/src/App.test.tsx` with the following:
```ts
process.env = {
NODE_ENV: 'test',
APP_CONFIG: [
{
data: {
app: { title: 'Test' },
backend: { baseUrl: 'http://localhost:7000' },
techdocs: {
storageUrl: 'http://localhost:7000/api/techdocs/static/docs',
},
},
context: 'test',
},
] as any,
};
```
- Updated dependencies [b2a5320a4]
- Updated dependencies [12d8f27a6]
- Updated dependencies [507513fed]
- Updated dependencies [52b5bc3e2]
- Updated dependencies [ecdd407b1]
- Updated dependencies [32a003973]
- Updated dependencies [40c0fdbaa]
- Updated dependencies [12d8f27a6]
- Updated dependencies [497859088]
- Updated dependencies [1987c9341]
- Updated dependencies [f31b76b44]
- Updated dependencies [15eee03bc]
- Updated dependencies [f43192207]
- Updated dependencies [cfc83cac1]
- Updated dependencies [8adb48df4]
- Updated dependencies [bc327dc42]
- Updated dependencies [2386de1d3]
- Updated dependencies [9ce68b677]
- Updated dependencies [10362e9eb]
- Updated dependencies [e37d2de99]
- Updated dependencies [813c6a4f2]
- Updated dependencies [11c6208fe]
- Updated dependencies [8106c9528]
- Updated dependencies [05183f202]
- Updated dependencies [40c0fdbaa]
- Updated dependencies [f71589800]
- Updated dependencies [2a271d89e]
- Updated dependencies [bece09057]
- Updated dependencies [d4f0a1406]
- Updated dependencies [169f48deb]
- Updated dependencies [8a1566719]
- Updated dependencies [d0ed25196]
- Updated dependencies [4c049a1a1]
- Updated dependencies [96ccc8f69]
- Updated dependencies [3af994c81]
- Updated dependencies [b33e553b2]
- Updated dependencies [04667f571]
- Updated dependencies [b93538acc]
- Updated dependencies [8871e7523]
- Updated dependencies [dbea11072]
- @backstage/plugin-circleci@0.2.11
- @backstage/plugin-github-actions@0.3.5
- @backstage/plugin-scaffolder@0.7.0
- @backstage/plugin-scaffolder-backend@0.9.0
- @backstage/cli@0.6.3
- @backstage/plugin-techdocs-backend@0.6.3
- @backstage/plugin-catalog-backend@0.6.4
- @backstage/plugin-api-docs@0.4.8
- @backstage/plugin-catalog@0.4.1
- @backstage/catalog-model@0.7.3
- @backstage/backend-common@0.5.5
- @backstage/plugin-proxy-backend@0.2.5
- @backstage/plugin-auth-backend@0.3.3
- @backstage/plugin-explore@0.3.0
- @backstage/plugin-techdocs@0.6.0
- @backstage/plugin-catalog-import@0.4.3
- @backstage/core@0.7.0
- @backstage/plugin-lighthouse@0.2.13
- @backstage/plugin-search@0.3.3
- @backstage/plugin-tech-radar@0.3.7
- @backstage/plugin-user-settings@0.2.7
## 0.3.11
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/create-app",
"description": "Create app package for Backstage",
"version": "0.3.11",
"version": "0.3.12",
"private": false,
"publishConfig": {
"access": "public"
+17
View File
@@ -1,5 +1,22 @@
# @backstage/dev-utils
## 0.1.13
### Patch Changes
- Updated dependencies [12d8f27a6]
- Updated dependencies [40c0fdbaa]
- Updated dependencies [2a271d89e]
- Updated dependencies [bece09057]
- Updated dependencies [169f48deb]
- Updated dependencies [8a1566719]
- Updated dependencies [9d455f69a]
- Updated dependencies [4c049a1a1]
- Updated dependencies [02816ecd7]
- @backstage/catalog-model@0.7.3
- @backstage/core@0.7.0
- @backstage/plugin-catalog-react@0.1.1
## 0.1.12
### Patch Changes
+5 -5
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/dev-utils",
"description": "Utilities for developing Backstage plugins.",
"version": "0.1.12",
"version": "0.1.13",
"private": false,
"publishConfig": {
"access": "public",
@@ -29,9 +29,9 @@
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/core": "^0.6.3",
"@backstage/catalog-model": "^0.7.2",
"@backstage/plugin-catalog-react": "^0.1.0",
"@backstage/core": "^0.7.0",
"@backstage/catalog-model": "^0.7.3",
"@backstage/plugin-catalog-react": "^0.1.1",
"@backstage/test-utils": "^0.1.8",
"@backstage/theme": "^0.2.3",
"@material-ui/core": "^4.11.0",
@@ -47,7 +47,7 @@
"react-router-dom": "6.0.0-beta.0"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/cli": "^0.6.3",
"@types/jest": "^26.0.7",
"@types/node": "^12.0.0"
},
+30 -19
View File
@@ -42,33 +42,44 @@ const templatePackagePaths = [
];
export async function run() {
const rootDir = await fs.mkdtemp(resolvePath(os.tmpdir(), 'backstage-e2e-'));
print(`CLI E2E test root: ${rootDir}\n`);
try {
const rootDir = await fs.mkdtemp(
resolvePath(os.tmpdir(), 'backstage-e2e-'),
);
print(`CLI E2E test root: ${rootDir}\n`);
print('Building dist workspace');
const workspaceDir = await buildDistWorkspace('workspace', rootDir);
print('Building dist workspace');
const workspaceDir = await buildDistWorkspace('workspace', rootDir);
const isPostgres = Boolean(process.env.POSTGRES_USER);
print('Creating a Backstage App');
const appDir = await createApp('test-app', isPostgres, workspaceDir, rootDir);
const isPostgres = Boolean(process.env.POSTGRES_USER);
print('Creating a Backstage App');
const appDir = await createApp(
'test-app',
isPostgres,
workspaceDir,
rootDir,
);
print('Creating a Backstage Plugin');
const pluginName = await createPlugin('test-plugin', appDir);
print('Creating a Backstage Plugin');
const pluginName = await createPlugin('test-plugin', appDir);
print('Creating a Backstage Backend Plugin');
await createPlugin('test-plugin', appDir, ['--backend']);
print('Creating a Backstage Backend Plugin');
await createPlugin('test-plugin', appDir, ['--backend']);
print('Starting the app');
await testAppServe(pluginName, appDir);
print('Starting the app');
await testAppServe(pluginName, appDir);
print('Testing the backend startup');
await testBackendStart(appDir, isPostgres);
print('Testing the backend startup');
await testBackendStart(appDir, isPostgres);
print('All tests successful, removing test dir');
await fs.remove(rootDir);
print('All tests successful, removing test dir');
await fs.remove(rootDir);
// Just in case some child process was left hanging
process.exit(0);
// Just in case some child process was left hanging
process.exit(0);
} catch {
process.exit(1);
}
}
/**
+12
View File
@@ -1,5 +1,17 @@
# @backstage/techdocs-common
## 0.4.3
### Patch Changes
- f43192207: remove usage of res.send() for res.json() and res.end() to ensure content types are more consistently application/json on backend responses and error cases
- 61299519f: Remove read-store-upload loop when uploading S3 objects for TechDocs
- Updated dependencies [12d8f27a6]
- Updated dependencies [497859088]
- Updated dependencies [8adb48df4]
- @backstage/catalog-model@0.7.3
- @backstage/backend-common@0.5.5
## 0.4.2
### Patch Changes
@@ -17,11 +17,13 @@ import type {
BlobUploadCommonResponse,
ContainerGetPropertiesResponse,
} from '@azure/storage-blob';
import { EventEmitter } from 'events';
import fs from 'fs-extra';
import os from 'os';
import path from 'path';
const rootDir = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir';
/**
* @param sourceFile Relative path to entity root dir. Contains either / or \ as file separator
* depending upon the OS.
@@ -48,6 +50,9 @@ export class BlockBlobClient {
}
uploadFile(source: string): Promise<BlobUploadCommonResponse> {
if (!fs.existsSync(source)) {
return Promise.reject(new Error(`The file ${source} does not exist`));
}
return Promise.resolve({
_response: {
request: {
@@ -62,6 +67,25 @@ export class BlockBlobClient {
exists() {
return checkFileExists(this.blobName);
}
download() {
const filePath = path.join(rootDir, this.blobName);
const emitter = new EventEmitter();
process.nextTick(() => {
if (fs.existsSync(filePath)) {
emitter.emit('data', Buffer.from(fs.readFileSync(filePath)));
emitter.emit('end');
} else {
emitter.emit(
'error',
new Error(`The file ${filePath} does not exist !`),
);
}
});
return Promise.resolve({
readableStreamBody: emitter,
});
}
}
class BlockBlobClientFailUpload extends BlockBlobClient {
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/techdocs-common",
"description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli",
"version": "0.4.2",
"version": "0.4.3",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -38,8 +38,8 @@
"dependencies": {
"@azure/identity": "^1.2.2",
"@azure/storage-blob": "^12.4.0",
"@backstage/backend-common": "^0.5.4",
"@backstage/catalog-model": "^0.7.2",
"@backstage/backend-common": "^0.5.5",
"@backstage/catalog-model": "^0.7.3",
"@backstage/config": "^0.1.3",
"@backstage/integration": "^0.5.0",
"@google-cloud/storage": "^5.6.0",
@@ -60,7 +60,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/cli": "^0.6.3",
"@types/fs-extra": "^9.0.5",
"@types/git-url-parse": "^9.0.0",
"@types/js-yaml": "^3.12.5",
@@ -14,13 +14,17 @@
* limitations under the License.
*/
import { getVoidLogger } from '@backstage/backend-common';
import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model';
import {
Entity,
EntityName,
ENTITY_DEFAULT_NAMESPACE,
} from '@backstage/catalog-model';
import { ConfigReader } from '@backstage/config';
import mockFs from 'mock-fs';
import os from 'os';
import path from 'path';
import { AzureBlobStoragePublish } from './azureBlobStorage';
import { PublisherBase } from './types';
import { PublisherBase, TechDocsMetadata } from './types';
// NOTE: /packages/techdocs-common/__mocks__ is being used to mock Azure client library
@@ -38,7 +42,14 @@ const createMockEntity = (annotations = {}) => {
};
};
const createMockEntityName = (): EntityName => ({
kind: 'TestKind',
name: 'test-component-name',
namespace: 'test-namespace',
});
const rootDir = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir';
const getEntityRootDir = (entity: Entity) => {
const {
kind,
@@ -163,6 +174,72 @@ describe('publishing with valid credentials', () => {
expect(await publisher.hasDocsBeenGenerated(entity)).toBe(false);
});
});
describe('fetchTechDocsMetadata', () => {
it('should return tech docs metadata', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);
mockFs({
[entityRootDir]: {
'techdocs_metadata.json':
'{"site_name": "backstage", "site_description": "site_content"}',
},
});
const expectedMetadata: TechDocsMetadata = {
site_name: 'backstage',
site_description: 'site_content',
};
expect(
await publisher.fetchTechDocsMetadata(entityNameMock),
).toStrictEqual(expectedMetadata);
mockFs.restore();
});
it('should return tech docs metadata when json encoded with single quotes', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);
mockFs({
[entityRootDir]: {
'techdocs_metadata.json': `{'site_name': 'backstage', 'site_description': 'site_content'}`,
},
});
const expectedMetadata: TechDocsMetadata = {
site_name: 'backstage',
site_description: 'site_content',
};
expect(
await publisher.fetchTechDocsMetadata(entityNameMock),
).toStrictEqual(expectedMetadata);
mockFs.restore();
});
it('should return an error if the techdocs_metadata.json file is not present', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);
let error;
try {
await publisher.fetchTechDocsMetadata(entityNameMock);
} catch (e) {
error = e;
}
expect(error).toEqual(
new Error(
`TechDocs metadata fetch failed, The file ${path.join(
entityRootDir,
'techdocs_metadata.json',
)} does not exist !`,
),
);
});
});
});
describe('error reporting', () => {
@@ -255,4 +332,63 @@ describe('error reporting', () => {
mockFs.restore();
});
describe('fetchTechDocsMetadata', () => {
it('should return tech docs metadata', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);
mockFs({
[entityRootDir]: {
'techdocs_metadata.json':
'{"site_name": "backstage", "site_description": "site_content"}',
},
});
const expectedMetadata: TechDocsMetadata = {
site_name: 'backstage',
site_description: 'site_content',
};
expect(
await publisher.fetchTechDocsMetadata(entityNameMock),
).toStrictEqual(expectedMetadata);
mockFs.restore();
});
it('should return tech docs metadata when json encoded with single quotes', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);
mockFs({
[entityRootDir]: {
'techdocs_metadata.json': `{'site_name': 'backstage', 'site_description': 'site_content'}`,
},
});
const expectedMetadata: TechDocsMetadata = {
site_name: 'backstage',
site_description: 'site_content',
};
expect(
await publisher.fetchTechDocsMetadata(entityNameMock),
).toStrictEqual(expectedMetadata);
mockFs.restore();
});
it('should return an error if the techdocs_metadata.json file is not present', async () => {
const entityNameMock = createMockEntityName();
let error;
try {
await publisher.fetchTechDocsMetadata(entityNameMock);
} catch (e) {
error = e;
}
expect(error.message).toEqual(
expect.stringContaining('TechDocs metadata fetch'),
);
});
});
});
@@ -201,10 +201,7 @@ export class AzureBlobStoragePublish implements PublisherBase {
return;
}
body
.on('error', e => {
this.logger.error(e.message);
reject(e.message);
})
.on('error', reject)
.on('data', chunk => {
fileStreamChunks.push(chunk);
})
@@ -220,16 +217,21 @@ export class AzureBlobStoragePublish implements PublisherBase {
): Promise<TechDocsMetadata> {
const entityRootDir = `${entityName.namespace}/${entityName.kind}/${entityName.name}`;
try {
return await new Promise<TechDocsMetadata>(resolve => {
const download = this.download(
this.containerName,
`${entityRootDir}/techdocs_metadata.json`,
const techdocsMetadataJson = await this.download(
this.containerName,
`${entityRootDir}/techdocs_metadata.json`,
);
if (!techdocsMetadataJson) {
throw new Error(
`Unable to parse the techdocs metadata file ${entityRootDir}/techdocs_metadata.json.`,
);
resolve(JSON5.parse(download.toString()));
});
}
const techdocsMetadata = JSON5.parse(
techdocsMetadataJson.toString('utf-8'),
);
return techdocsMetadata;
} catch (e) {
this.logger.error(e.message);
throw e;
throw new Error(`TechDocs metadata fetch failed, ${e.message}`);
}
}
+39
View File
@@ -1,5 +1,44 @@
# @backstage/plugin-api-docs
## 0.4.8
### Patch Changes
- 32a003973: Update messaging when no entities are in a table.
- 2386de1d3: Add organization name to the API Explorer page title
- f71589800: The api-docs plugin has been migrated to use an [external route reference](https://backstage.io/docs/plugins/composability#binding-external-routes-in-the-app) to dynamically link to the create component page. This means you need to migrate the api docs plugin to use the new extension components, as well as bind the external route.
To bind the external route from the api docs plugin to the scaffolder template index page, make sure you have the appropriate imports and add the following to the `createApp` call:
```ts
import { apiDocsPlugin } from '@backstage/plugin-api-docs';
import { scaffolderPlugin } from '@backstage/plugin-scaffolder';
const app = createApp({
// ...
bindRoutes({ bind }) {
bind(apiDocsPlugin.externalRoutes, {
createComponent: scaffolderPlugin.routes.root,
});
},
});
```
If you choose to not bind the routes, the button to create new APIs is not displayed.
- Updated dependencies [12d8f27a6]
- Updated dependencies [40c0fdbaa]
- Updated dependencies [2a271d89e]
- Updated dependencies [bece09057]
- Updated dependencies [169f48deb]
- Updated dependencies [8a1566719]
- Updated dependencies [9d455f69a]
- Updated dependencies [4c049a1a1]
- Updated dependencies [02816ecd7]
- @backstage/catalog-model@0.7.3
- @backstage/core@0.7.0
- @backstage/plugin-catalog-react@0.1.1
## 0.4.7
### Patch Changes
+62
View File
@@ -23,6 +23,68 @@ Other formats are displayed as plain text, but this can easily be extended.
To fill the catalog with APIs, [provide entities of kind API](https://backstage.io/docs/features/software-catalog/descriptor-format#kind-api).
To link that a component provides or consumes an API, see the [`providesApis`](https://backstage.io/docs/features/software-catalog/descriptor-format#specprovidesapis-optional) and [`consumesApis`](https://backstage.io/docs/features/software-catalog/descriptor-format#specconsumesapis-optional) properties on the Component kind.
## Implementing OAuth 2 Authorization Code flow with Swagger UI
### Adding `oauth2-redirect.html` to support OAuth2 `redirect_uri` route
The Swagger UI package by expects to have a route to `/oauth2-redirect.html` which processes
the redirect callback for the OAuth2 Authorization Code flow, however, this file is not installed
by this plugin.
Grab a copy of [oauth2-redirect.html](https://github.com/swagger-api/swagger-ui/blob/master/dist/oauth2-redirect.html)
and put it in the `app/public/` directory in order to enable Swagger UI to complete this redirection.
### Configuring your OAuth2 Client
You'll need to make sure your OAuth2 client has been registered in your OAuth2 Authentication Server (AS)
with the appropriate `redirect_uris`, `scopes` and `grant_types`. For example, if your AS supports
the [OAuth 2.0 Dynamic Client Registration Protocol](https://tools.ietf.org/html/rfc7591), an example
POST request body would look like this:
```json
{
"client_name": "Example Backstage api-docs plugin Swagger UI Client",
"redirect_uris": [
"https://www.getpostman.com/oauth2/callback",
"http://localhost:3000/oauth2-redirect.html"
"https://<yourhost>/oauth2-redirect.html"
],
"scope": "read_pets write_pets",
"grant_types": [
"authorization_code"
]
}
```
The above `redirect_uris` are:
- [Postman](https://www.postman.com/) testing: `https://www.getpostman.com/oauth2/callback`
- Local Backstage app development: `http://localhost:3000/oauth2-redirect.html`
- Backstage app production: `https://<yourhost>/oauth2-redirect.html`
### Configuring OAuth2 in your OpenAPI 3.0 schema
To configure [OAuth 2 Authorization Code](https://swagger.io/docs/specification/authentication/oauth2/) flow
in your OpenAPI 3.0 schema you'll need something like this snippet:
```yaml
components:
securitySchemes:
oauth:
type: oauth2
description: OAuth2 service
flows:
authorizationCode:
authorizationUrl: https://api.example.com/oauth2/authorize
tokenUrl: https://api.example.com/oauth2/token
scopes:
read_pets: read your pets
write_pets: modify pets in your account
security:
oauth:
- [read_pets, write_pets]
```
## Links
- [The Backstage homepage](https://backstage.io)
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-api-docs",
"version": "0.4.7",
"version": "0.4.8",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -30,9 +30,9 @@
},
"dependencies": {
"@asyncapi/react-component": "^0.19.2",
"@backstage/catalog-model": "^0.7.2",
"@backstage/core": "^0.6.3",
"@backstage/plugin-catalog-react": "^0.1.0",
"@backstage/catalog-model": "^0.7.3",
"@backstage/core": "^0.7.0",
"@backstage/plugin-catalog-react": "^0.1.1",
"@backstage/theme": "^0.2.3",
"@material-icons/font": "^1.0.2",
"@material-ui/core": "^4.11.0",
@@ -49,8 +49,8 @@
"swagger-ui-react": "^3.37.2"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/dev-utils": "^0.1.12",
"@backstage/cli": "^0.6.3",
"@backstage/dev-utils": "^0.1.13",
"@backstage/test-utils": "^0.1.8",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
+12
View File
@@ -1,5 +1,17 @@
# @backstage/plugin-auth-backend
## 0.3.3
### Patch Changes
- f43192207: remove usage of res.send() for res.json() and res.end() to ensure content types are more consistently application/json on backend responses and error cases
- 3af994c81: Expose a configuration option for the oidc scope
- Updated dependencies [12d8f27a6]
- Updated dependencies [497859088]
- Updated dependencies [8adb48df4]
- @backstage/catalog-model@0.7.3
- @backstage/backend-common@0.5.5
## 0.3.2
### Patch Changes
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-auth-backend",
"version": "0.3.2",
"version": "0.3.3",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -29,9 +29,9 @@
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/backend-common": "^0.5.4",
"@backstage/backend-common": "^0.5.5",
"@backstage/catalog-client": "^0.3.6",
"@backstage/catalog-model": "^0.7.2",
"@backstage/catalog-model": "^0.7.3",
"@backstage/config": "^0.1.3",
"@backstage/test-utils": "^0.1.8",
"@types/express": "^4.17.6",
@@ -67,7 +67,7 @@
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/cli": "^0.6.3",
"@types/body-parser": "^1.19.0",
"@types/cookie-parser": "^1.4.2",
"@types/express-session": "^1.17.2",
+12
View File
@@ -1,5 +1,17 @@
# @backstage/plugin-catalog-backend
## 0.6.4
### Patch Changes
- ecdd407b1: GithubDiscoveryProcessor outputs locations as optional to avoid outputting errors for missing locations (see https://github.com/backstage/backstage/issues/4730).
- 12d8f27a6: Add version `backstage.io/v1beta2` schema for Template entities.
- Updated dependencies [12d8f27a6]
- Updated dependencies [497859088]
- Updated dependencies [8adb48df4]
- @backstage/catalog-model@0.7.3
- @backstage/backend-common@0.5.5
## 0.6.3
### Patch Changes
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-catalog-backend",
"version": "0.6.3",
"version": "0.6.4",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -30,8 +30,8 @@
},
"dependencies": {
"@azure/msal-node": "^1.0.0-beta.3",
"@backstage/backend-common": "^0.5.4",
"@backstage/catalog-model": "^0.7.2",
"@backstage/backend-common": "^0.5.5",
"@backstage/catalog-model": "^0.7.3",
"@backstage/config": "^0.1.3",
"@backstage/integration": "^0.5.0",
"@octokit/graphql": "^4.5.8",
@@ -59,7 +59,7 @@
"yup": "^0.29.3"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/cli": "^0.6.3",
"@backstage/test-utils": "^0.1.8",
"@types/core-js": "^2.5.4",
"@types/git-url-parse": "^9.0.0",
+18
View File
@@ -1,5 +1,23 @@
# @backstage/plugin-catalog-import
## 0.4.3
### Patch Changes
- 05183f202: Bump react-hook-form version constraint to "^6.15.4"
- Updated dependencies [12d8f27a6]
- Updated dependencies [40c0fdbaa]
- Updated dependencies [2a271d89e]
- Updated dependencies [bece09057]
- Updated dependencies [169f48deb]
- Updated dependencies [8a1566719]
- Updated dependencies [9d455f69a]
- Updated dependencies [4c049a1a1]
- Updated dependencies [02816ecd7]
- @backstage/catalog-model@0.7.3
- @backstage/core@0.7.0
- @backstage/plugin-catalog-react@0.1.1
## 0.4.2
### Patch Changes
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-catalog-import",
"version": "0.4.2",
"version": "0.4.3",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -30,11 +30,11 @@
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/catalog-model": "^0.7.2",
"@backstage/catalog-model": "^0.7.3",
"@backstage/catalog-client": "^0.3.6",
"@backstage/core": "^0.6.3",
"@backstage/core": "^0.7.0",
"@backstage/integration": "^0.5.0",
"@backstage/plugin-catalog-react": "^0.1.0",
"@backstage/plugin-catalog-react": "^0.1.1",
"@backstage/theme": "^0.2.3",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -51,8 +51,8 @@
"yaml": "^1.10.0"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/dev-utils": "^0.1.12",
"@backstage/cli": "^0.6.3",
"@backstage/dev-utils": "^0.1.13",
"@backstage/test-utils": "^0.1.8",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
+16
View File
@@ -1,5 +1,21 @@
# @backstage/plugin-catalog-react
## 0.1.1
### Patch Changes
- 9d455f69a: Introduce parameters for namespace, kind, and name to `entityRouteRef`.
- 02816ecd7: Fixed EntityProvider setting 'loading' bool erroneously to true
- Updated dependencies [12d8f27a6]
- Updated dependencies [40c0fdbaa]
- Updated dependencies [2a271d89e]
- Updated dependencies [bece09057]
- Updated dependencies [169f48deb]
- Updated dependencies [8a1566719]
- Updated dependencies [4c049a1a1]
- @backstage/catalog-model@0.7.3
- @backstage/core@0.7.0
## 0.1.0
### Minor Changes
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-catalog-react",
"version": "0.1.0",
"version": "0.1.1",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -29,8 +29,8 @@
},
"dependencies": {
"@backstage/catalog-client": "^0.3.6",
"@backstage/catalog-model": "^0.7.2",
"@backstage/core": "^0.6.3",
"@backstage/catalog-model": "^0.7.3",
"@backstage/core": "^0.7.0",
"@material-ui/core": "^4.11.0",
"@types/react": "^16.9",
"react": "^16.13.1",
@@ -39,8 +39,8 @@
"react-use": "^15.3.3"
},
"devDependencies": {
"@backstage/cli": "^0.6.2",
"@backstage/dev-utils": "^0.1.12",
"@backstage/cli": "^0.6.3",
"@backstage/dev-utils": "^0.1.13",
"@backstage/test-utils": "^0.1.8",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
+21
View File
@@ -1,5 +1,26 @@
# @backstage/plugin-catalog
## 0.4.1
### Patch Changes
- 32a003973: Update messaging when no entities are in a table.
- 40c0fdbaa: Make the external `createComponent` route optional, hiding the "Create Component" button if it isn't bound.
- 10362e9eb: Use entity relation for the owner of an entity in the catalog entity page header.
- b33e553b2: Removed fullScreen property from UnregisterEntity Dialog modal.
- Updated dependencies [12d8f27a6]
- Updated dependencies [40c0fdbaa]
- Updated dependencies [2a271d89e]
- Updated dependencies [bece09057]
- Updated dependencies [169f48deb]
- Updated dependencies [8a1566719]
- Updated dependencies [9d455f69a]
- Updated dependencies [4c049a1a1]
- Updated dependencies [02816ecd7]
- @backstage/catalog-model@0.7.3
- @backstage/core@0.7.0
- @backstage/plugin-catalog-react@0.1.1
## 0.4.0
### Minor Changes

Some files were not shown because too many files have changed in this diff Show More