Merge branch 'master' into rugvip/ports
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
---
|
||||
|
||||
Export _api_ (Client, API, ref) from the catalog import plugin.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Migrated to new composability API, exporting the plugin as `scaffolderPlugin`. The template list page (`/create`) is exported as the `TemplateIndexPage` extension, and the templating page itself is exported as `TemplatePage`.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/techdocs-common': patch
|
||||
'@backstage/plugin-techdocs-backend': patch
|
||||
---
|
||||
|
||||
1. Added option to use Azure Blob Storage as a choice to store the static generated files for TechDocs.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-cost-insights': minor
|
||||
---
|
||||
|
||||
add alert hooks
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Update `create-plugin` template to use the new composability API, by switching to exporting a single routable extension component.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-graphiql': patch
|
||||
---
|
||||
|
||||
Finalized composability API migration, now exporting the plugin as `graphiqlPlugin`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/core': patch
|
||||
---
|
||||
|
||||
Add className to the SidebarItem
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/core': patch
|
||||
---
|
||||
|
||||
Update `WarningPanel` component to use accordion-style expansion
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-api-docs': patch
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-org': patch
|
||||
---
|
||||
|
||||
Display owner and system as entity page links in the tables of the `api-docs`
|
||||
plugin.
|
||||
|
||||
Move `isOwnerOf` and `getEntityRelations` from `@backstage/plugin-catalog` to
|
||||
`@backstage/plugin-catalog-react` and export it from there to use it by other
|
||||
plugins.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/theme': patch
|
||||
---
|
||||
|
||||
Updates warning text color to align to updated `WarningPanel` styling
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
---
|
||||
|
||||
Migrated to new composability API, exporting the plugin instance as `catalogImportPlugin`, and the page as `CatalogImportPage`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-lighthouse': patch
|
||||
---
|
||||
|
||||
Migrate to new composability API, exporting the plugin instance as `lighthousePlugin`, the top-level page as `LighthousePage`, the entity card as `EntityLastLighthouseAuditCard`, and the entity content as `EntityLighthouseContent`.
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Updated the `rootLogger` in `@backstage/backend-common` to support custom logging options. This is useful when you want to make some changes without re-implementing the entire logger and calling `setRootLogger` or `logger.configure`. For example you can add additional `defaultMeta` tags to each log entry. The following changes are included:
|
||||
|
||||
- Added `createRootLogger` which accepts winston `LoggerOptions`. These options allow overriding the default keys.
|
||||
|
||||
Example Usage:
|
||||
|
||||
```ts
|
||||
// Create the logger
|
||||
const logger = createRootLogger({
|
||||
defaultMeta: { appName: 'backstage', appEnv: 'prod' },
|
||||
});
|
||||
|
||||
// Add a custom logger transport
|
||||
logger.add(new MyCustomTransport());
|
||||
|
||||
const config = await loadBackendConfig({
|
||||
argv: process.argv,
|
||||
logger: getRootLogger(), // already set to new logger instance
|
||||
});
|
||||
```
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-user-settings': patch
|
||||
---
|
||||
|
||||
Migrate to new composability API, exporting the plugin as `userSettingsPlugin` and the page as `UserSettingsPage`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/catalog-model': patch
|
||||
---
|
||||
|
||||
Adds a new optional `links` metadata field to the Entity class within the `catalog-model` package (as discussed in [[RFC] Entity Links](https://github.com/backstage/backstage/issues/3787)). This PR adds support for the entity links only. Follow up PR's will introduce the UI component to display them.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Add `children` option to `addPage`, which will be rendered as the children of the `Route`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Attempt to fix windows test errors in master
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/catalog-model': patch
|
||||
---
|
||||
|
||||
Replace `yup` with `ajv`, for validation of catalog entities.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Fixed module resolution of external libraries during backend development. Modules used to be resolved relative to the backend entrypoint, but are now resolved relative to each individual module.
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
'@backstage/core': minor
|
||||
---
|
||||
|
||||
Closes #3556
|
||||
The scroll bar of collapsed sidebar is now hidden without full screen.
|
||||
|
||||

|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-org': patch
|
||||
---
|
||||
|
||||
Migrate to new composability API, exporting the plugin instance as `orgPlugin`, and the entity cards as `EntityGroupProfileCard`, `EntityMembersListCard`, `EntityOwnershipCard`, and `EntityUserProfileCard`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/config-loader': patch
|
||||
---
|
||||
|
||||
Bump `config-loader` to `ajv` 7, to enable v7 feature use elsewhere
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/dev-utils': patch
|
||||
---
|
||||
|
||||
Added `path` option to `addPage` that can be used to set a specific path for the page rather than a generated one. Also omit sidebar item altogether if `title` option is not set.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/integration': patch
|
||||
---
|
||||
|
||||
Properly forward errors that occur when looking up GitLab project IDs.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/config-loader': patch
|
||||
---
|
||||
|
||||
Each piece of the configuration schema is now validated upfront, in order to produce more informative errors.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-app-backend': patch
|
||||
---
|
||||
|
||||
Failures to load the frontend configuration schema now throws an error that includes more context and instructions for how to fix the issue.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/core': patch
|
||||
---
|
||||
|
||||
Add a `prop` union for `SignInPage` that allows it to be used for just a single provider, with inline errors, and optionally with automatic sign-in.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Add check for outdated/duplicate packages to yarn start
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-gcp-projects': patch
|
||||
---
|
||||
|
||||
Migrate to new composability API, exporting the plugin as `gcpProjectsPlugin` and page as `GcpProjectsPage`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Throw `NotAllowedError` when registering locations with entities of disallowed kinds
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-fossa': minor
|
||||
---
|
||||
|
||||
Port FOSSA plugin to new extension model.
|
||||
|
||||
If you are using the FOSSA plugin adjust the plugin import from `plugin` to
|
||||
`fossaPlugin` and replace `<FossaCard entity={...} ...>` with `<EntityFossaCard />`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-api-docs': patch
|
||||
---
|
||||
|
||||
Migrate to new composability API, exporting the plugin as `apiDocsPlugin`, index page as `ApiExplorerPage`, and entity page cards as `EntityApiDefinitionCard`, `EntityConsumedApisCard`, `EntityConsumingComponentsCard`, `EntityProvidedApisCard`, and `EntityProvidingComponentsCard`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Finalize migration to new composability API, with the plugin instance now exported `catalogPlugin`.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-tech-radar': patch
|
||||
---
|
||||
|
||||
Fix mapping RadarEntry and Entry for moved and url attributes
|
||||
Fix clicking of links in the radar legend
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/core': patch
|
||||
---
|
||||
|
||||
Fix check that determines whether popup was closed or the messaging was misconfigured.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-sonarqube': patch
|
||||
---
|
||||
|
||||
Migrate to new composability API, exporting the plugin as `sonarQubePlugin` and card as `EntitySonarQubeCard`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/catalog-model': patch
|
||||
---
|
||||
|
||||
Introduce json schema variants of the `yup` validation schemas
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
# Repo visibility for GitLab and BitBucket repos
|
||||
|
||||
**NOTE: This changes default repo visibility from `private` to `public` for GitLab and BitBucket** which
|
||||
is consistent with the GitHub default. If you were counting on `private` visibility, you'll need to update
|
||||
your scaffolder config to use `private`.
|
||||
|
||||
This adds repo visibility feature parity with GitHub for GitLab and BitBucket.
|
||||
|
||||
To configure the repo visibility, set scaffolder._type_.visibility as in this example:
|
||||
|
||||
```yaml
|
||||
scaffolder:
|
||||
github:
|
||||
visibility: private # 'public' or 'internal' or 'private' (default is 'public')
|
||||
gitlab:
|
||||
visibility: public # 'public' or 'internal' or 'private' (default is 'public')
|
||||
bitbucket:
|
||||
visibility: public # 'public' or 'private' (default is 'public')
|
||||
```
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-welcome': patch
|
||||
---
|
||||
|
||||
Migrated to new composability API, exporting the plugin as `welcomePlugin` and the page as `WelcomePage`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/techdocs-common': patch
|
||||
---
|
||||
|
||||
dir preparer will use URL Reader in its implementation.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-user-settings': patch
|
||||
---
|
||||
|
||||
Keep the Pin Sidebar setting visible on small screens.
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-api-docs': patch
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
'@backstage/plugin-circleci': patch
|
||||
'@backstage/plugin-cloudbuild': patch
|
||||
'@backstage/plugin-github-actions': patch
|
||||
'@backstage/plugin-jenkins': patch
|
||||
'@backstage/plugin-kafka': patch
|
||||
'@backstage/plugin-lighthouse': patch
|
||||
'@backstage/plugin-org': patch
|
||||
'@backstage/plugin-register-component': patch
|
||||
'@backstage/plugin-rollbar': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
'@backstage/plugin-search': patch
|
||||
'@backstage/plugin-sentry': patch
|
||||
'@backstage/plugin-techdocs': patch
|
||||
'@backstage/dev-utils': patch
|
||||
---
|
||||
|
||||
Switch dependency from `@backstage/plugin-catalog` to `@backstage/plugin-catalog-react`.
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': minor
|
||||
---
|
||||
|
||||
The scaffolder is updated to generate a unique workspace directory inside the temp folder. This directory is cleaned up by the job processor after each run.
|
||||
|
||||
The prepare/template/publish steps have been refactored to operate on known directories, `template/` and `result/`, inside the temporary workspace path.
|
||||
|
||||
Updated preparers to accept the template url instead of the entire template. This is done primarily to allow for backwards compatibility between v1 and v2 scaffolder templates.
|
||||
|
||||
Fixes broken GitHub actions templating in the Create React App template.
|
||||
|
||||
#### For those with **custom** preparers, templates, or publishers
|
||||
|
||||
The preparer interface has changed, the prepare method now only takes a single argument, and doesn't return anything. As part of this change the preparers were refactored to accept a URL pointing to the target directory, rather than computing that from the template entity.
|
||||
|
||||
The `workingDirectory` option was also removed, and replaced with a `workspacePath` option. The difference between the two is that `workingDirectory` was a place for the preparer to create temporary directories, while the `workspacePath` is the specific folder were the entire templating process for a single template job takes place. Instead of returning a path to the folder were the prepared contents were placed, the contents are put at the `<workspacePath>/template` path.
|
||||
|
||||
```diff
|
||||
type PreparerOptions = {
|
||||
- workingDirectory?: string;
|
||||
+ /**
|
||||
+ * Full URL to the directory containg template data
|
||||
+ */
|
||||
+ url: string;
|
||||
+ /**
|
||||
+ * The workspace path that will eventually be the the root of the new repo
|
||||
+ */
|
||||
+ workspacePath: string;
|
||||
logger: Logger;
|
||||
};
|
||||
|
||||
-prepare(template: TemplateEntityV1alpha1, opts?: PreparerOptions): Promise<string>
|
||||
+prepare(opts: PreparerOptions): Promise<void>;
|
||||
```
|
||||
|
||||
Instead of returning a path to the folder were the templaters contents were placed, the contents are put at the `<workspacePath>/result` path. All templaters now also expect the source template to be present in the `template` directory within the `workspacePath`.
|
||||
|
||||
```diff
|
||||
export type TemplaterRunOptions = {
|
||||
- directory: string;
|
||||
+ workspacePath: string;
|
||||
values: TemplaterValues;
|
||||
logStream?: Writable;
|
||||
dockerClient: Docker;
|
||||
};
|
||||
|
||||
-public async run(options: TemplaterRunOptions): Promise<TemplaterRunResult>
|
||||
+public async run(options: TemplaterRunOptions): Promise<void>
|
||||
```
|
||||
|
||||
Just like the preparer and templaters, the publishers have also switched to using `workspacePath`. The root of the new repo is expected to be located at `<workspacePath>/result`.
|
||||
|
||||
```diff
|
||||
export type PublisherOptions = {
|
||||
values: TemplaterValues;
|
||||
- directory: string;
|
||||
+ workspacePath: string;
|
||||
logger: Logger;
|
||||
};
|
||||
```
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': minor
|
||||
'@backstage/create-app': minor
|
||||
---
|
||||
|
||||
`@backstage/plugin-catalog` stopped exporting hooks and helpers for other
|
||||
plugins. They are migrated to `@backstage/plugin-catalog-react`.
|
||||
Change both your dependencies and imports to the new package.
|
||||
@@ -3,6 +3,7 @@ name: E2E Test Linux
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '.changeset/**'
|
||||
- 'contrib/**'
|
||||
- 'docs/**'
|
||||
- 'microsite/**'
|
||||
|
||||
@@ -74,8 +74,6 @@ organization:
|
||||
|
||||
# Reference documentation http://backstage.io/docs/features/techdocs/configuration
|
||||
techdocs:
|
||||
requestUrl: http://localhost:7000/api/techdocs
|
||||
storageUrl: http://localhost:7000/api/techdocs/static/docs
|
||||
builder: 'local' # Alternatives - 'external'
|
||||
generators:
|
||||
techdocs: 'docker' # Alternatives - 'local'
|
||||
|
||||
@@ -13,15 +13,6 @@ configuration options for TechDocs.
|
||||
# File: app-config.yaml
|
||||
|
||||
techdocs:
|
||||
# TechDocs makes API calls to techdocs-backend using this URL. e.g. get docs of an entity, get metadata, etc.
|
||||
|
||||
requestUrl: http://localhost:7000/api/techdocs
|
||||
|
||||
# Just another route in techdocs-backend where TechDocs requests the static files from. This URL uses an HTTP middleware
|
||||
# to serve files from either a local directory or an External storage provider.
|
||||
|
||||
storageUrl: http://localhost:7000/api/techdocs/static/docs
|
||||
|
||||
# generators.techdocs can have two values: 'docker' or 'local'. This is to determine how to run the generator - whether to
|
||||
# spin up the techdocs-container docker image or to run mkdocs locally (assuming all the dependencies are taken care of).
|
||||
# You want to change this to 'local' if you are running Backstage using your own custom Docker setup and want to avoid running
|
||||
@@ -101,4 +92,15 @@ techdocs:
|
||||
# https://docs.microsoft.com/en-us/azure/storage/common/storage-auth?toc=/azure/storage/blobs/toc.json
|
||||
accountKey:
|
||||
$env: TECHDOCS_AZURE_BLOB_STORAGE_ACCOUNT_KEY
|
||||
|
||||
# (Optional and Legacy) TechDocs makes API calls to techdocs-backend using this URL. e.g. get docs of an entity, get metadata, etc.
|
||||
# You don't have to specify this anymore.
|
||||
|
||||
requestUrl: http://localhost:7000/api/techdocs
|
||||
|
||||
# (Optional and Legacy) Just another route in techdocs-backend where TechDocs requests the static files from. This URL uses an HTTP middleware
|
||||
# to serve files from either a local directory or an External storage provider.
|
||||
# You don't have to specify this anymore.
|
||||
|
||||
storageUrl: http://localhost:7000/api/techdocs/static/docs
|
||||
```
|
||||
|
||||
@@ -150,26 +150,10 @@ app. Now let us tweak some configurations to suit your needs.
|
||||
**See [TechDocs Configuration Options](configuration.md) for complete
|
||||
configuration reference.**
|
||||
|
||||
### Setting TechDocs URLs
|
||||
|
||||
```yaml
|
||||
techdocs:
|
||||
storageUrl: http://localhost:7000/api/techdocs/static/docs
|
||||
requestUrl: http://localhost:7000/api/techdocs/
|
||||
```
|
||||
|
||||
`requestUrl` is used by TechDocs frontend plugin to discover `techdocs-backend`
|
||||
endpoints, and the `storageUrl` is another endpoint in `techdocs-backend` which
|
||||
acts as a middleware between TechDocs and the storage (where the static
|
||||
generated docs site are stored). These default values should mostly work for
|
||||
you. These options will soon be optional to set.
|
||||
|
||||
### Should TechDocs Backend generate docs?
|
||||
|
||||
```yaml
|
||||
techdocs:
|
||||
storageUrl: http://localhost:7000/api/techdocs/static/docs
|
||||
requestUrl: http://localhost:7000/api/techdocs/
|
||||
builder: 'local'
|
||||
```
|
||||
|
||||
@@ -196,8 +180,6 @@ out Backstage for the first time. At a later time, review
|
||||
|
||||
```yaml
|
||||
techdocs:
|
||||
storageUrl: http://localhost:7000/api/techdocs/static/docs
|
||||
requestUrl: http://localhost:7000/api/techdocs/
|
||||
builder: 'local'
|
||||
publisher:
|
||||
type: 'local'
|
||||
@@ -219,6 +201,9 @@ no config is provided.
|
||||
|
||||
```yaml
|
||||
techdocs:
|
||||
builder: 'local'
|
||||
publisher:
|
||||
type: 'local'
|
||||
generators:
|
||||
techdocs: local
|
||||
```
|
||||
|
||||
@@ -90,7 +90,7 @@ $ docker build -t example-deployment .
|
||||
To run the image locally you can run:
|
||||
|
||||
```sh
|
||||
$ docker run -p -it 7000:7000 example-deployment
|
||||
$ docker run -it -p 7000:7000 example-deployment
|
||||
```
|
||||
|
||||
You should then start to get logs in your terminal, and then you can open your
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.11.0",
|
||||
"@changesets/cli": "^2.14.0",
|
||||
"@octokit/openapi-types": "^2.2.0",
|
||||
"@spotify/eslint-config-oss": "^1.0.1",
|
||||
"@spotify/prettier-config": "^9.0.0",
|
||||
|
||||
@@ -1,5 +1,81 @@
|
||||
# example-app
|
||||
|
||||
## 0.2.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 9d6ef14bc: Migrated to new composability API, exporting the plugin instance as `rollbarPlugin`, the entity page content as `EntityRollbarContent`, and entity conditional as `isRollbarAvailable`. Updated the `EntityPage` for the `example-app` to include a composite `ErrorsSwitcher` component that works with both `Sentry` & `Rollbar`. Also removed the unused and undocumented `RollbarHome` related components.
|
||||
- Updated dependencies [ceef4dd89]
|
||||
- Updated dependencies [720149854]
|
||||
- Updated dependencies [19172f5a9]
|
||||
- Updated dependencies [4c6a6dddd]
|
||||
- Updated dependencies [398e1f83e]
|
||||
- Updated dependencies [87b189d00]
|
||||
- Updated dependencies [12ece98cd]
|
||||
- Updated dependencies [d82246867]
|
||||
- Updated dependencies [7fc89bae2]
|
||||
- Updated dependencies [c810082ae]
|
||||
- Updated dependencies [b712841d6]
|
||||
- Updated dependencies [a5628df40]
|
||||
- Updated dependencies [5fa3bdb55]
|
||||
- Updated dependencies [bc5082a00]
|
||||
- Updated dependencies [6e612ce25]
|
||||
- Updated dependencies [e44925723]
|
||||
- Updated dependencies [b37501a3d]
|
||||
- Updated dependencies [9d6ef14bc]
|
||||
- Updated dependencies [025e122c3]
|
||||
- Updated dependencies [e9aab60c7]
|
||||
- Updated dependencies [21e624ba9]
|
||||
- Updated dependencies [0269f4fd9]
|
||||
- Updated dependencies [19fe61c27]
|
||||
- Updated dependencies [da9f53c60]
|
||||
- Updated dependencies [a08c4b0b0]
|
||||
- Updated dependencies [bc5082a00]
|
||||
- Updated dependencies [bc5082a00]
|
||||
- Updated dependencies [b37501a3d]
|
||||
- Updated dependencies [90c8f20b9]
|
||||
- Updated dependencies [32c95605f]
|
||||
- Updated dependencies [7881f2117]
|
||||
- Updated dependencies [8dfdec613]
|
||||
- Updated dependencies [54c7d02f7]
|
||||
- Updated dependencies [de98c32ed]
|
||||
- Updated dependencies [806929fe2]
|
||||
- Updated dependencies [019fe39a0]
|
||||
- Updated dependencies [019fe39a0]
|
||||
- Updated dependencies [11cb5ef94]
|
||||
- @backstage/plugin-catalog-import@0.3.7
|
||||
- @backstage/plugin-scaffolder@0.4.2
|
||||
- @backstage/plugin-cost-insights@0.8.0
|
||||
- @backstage/cli@0.6.0
|
||||
- @backstage/plugin-graphiql@0.2.7
|
||||
- @backstage/core@0.6.0
|
||||
- @backstage/plugin-api-docs@0.4.4
|
||||
- @backstage/plugin-catalog@0.3.0
|
||||
- @backstage/plugin-catalog-react@0.0.2
|
||||
- @backstage/plugin-org@0.3.5
|
||||
- @backstage/theme@0.2.3
|
||||
- @backstage/plugin-lighthouse@0.2.9
|
||||
- @backstage/plugin-techdocs@0.5.5
|
||||
- @backstage/plugin-user-settings@0.2.5
|
||||
- @backstage/catalog-model@0.7.1
|
||||
- @backstage/plugin-rollbar@0.2.9
|
||||
- @backstage/plugin-gcp-projects@0.2.4
|
||||
- @backstage/plugin-tech-radar@0.3.4
|
||||
- @backstage/plugin-welcome@0.2.5
|
||||
- @backstage/plugin-explore@0.2.4
|
||||
- @backstage/plugin-circleci@0.2.7
|
||||
- @backstage/plugin-cloudbuild@0.2.8
|
||||
- @backstage/plugin-github-actions@0.3.1
|
||||
- @backstage/plugin-jenkins@0.3.8
|
||||
- @backstage/plugin-kafka@0.2.1
|
||||
- @backstage/plugin-register-component@0.2.8
|
||||
- @backstage/plugin-search@0.2.7
|
||||
- @backstage/plugin-sentry@0.3.4
|
||||
- @backstage/plugin-gitops-profiles@0.2.4
|
||||
- @backstage/plugin-kubernetes@0.3.8
|
||||
- @backstage/plugin-newrelic@0.2.4
|
||||
- @backstage/plugin-pagerduty@0.2.7
|
||||
|
||||
## 0.2.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
+33
-33
@@ -1,41 +1,41 @@
|
||||
{
|
||||
"name": "example-app",
|
||||
"version": "0.2.13",
|
||||
"version": "0.2.14",
|
||||
"private": true,
|
||||
"bundled": true,
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^0.7.0",
|
||||
"@backstage/cli": "^0.5.0",
|
||||
"@backstage/core": "^0.5.0",
|
||||
"@backstage/plugin-api-docs": "^0.4.3",
|
||||
"@backstage/plugin-catalog": "^0.2.14",
|
||||
"@backstage/plugin-catalog-react": "^0.0.1",
|
||||
"@backstage/plugin-catalog-import": "^0.3.6",
|
||||
"@backstage/plugin-circleci": "^0.2.6",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.7",
|
||||
"@backstage/plugin-cost-insights": "^0.7.0",
|
||||
"@backstage/plugin-explore": "^0.2.3",
|
||||
"@backstage/plugin-gcp-projects": "^0.2.3",
|
||||
"@backstage/plugin-github-actions": "^0.3.0",
|
||||
"@backstage/plugin-gitops-profiles": "^0.2.3",
|
||||
"@backstage/plugin-graphiql": "^0.2.6",
|
||||
"@backstage/plugin-org": "^0.3.4",
|
||||
"@backstage/plugin-jenkins": "^0.3.6",
|
||||
"@backstage/plugin-kafka": "^0.2.0",
|
||||
"@backstage/plugin-kubernetes": "^0.3.7",
|
||||
"@backstage/plugin-lighthouse": "^0.2.8",
|
||||
"@backstage/plugin-newrelic": "^0.2.3",
|
||||
"@backstage/plugin-pagerduty": "0.2.6",
|
||||
"@backstage/plugin-register-component": "^0.2.7",
|
||||
"@backstage/plugin-rollbar": "^0.2.8",
|
||||
"@backstage/plugin-scaffolder": "^0.4.1",
|
||||
"@backstage/plugin-sentry": "^0.3.3",
|
||||
"@backstage/plugin-search": "^0.2.6",
|
||||
"@backstage/plugin-tech-radar": "^0.3.3",
|
||||
"@backstage/plugin-techdocs": "^0.5.4",
|
||||
"@backstage/plugin-user-settings": "^0.2.4",
|
||||
"@backstage/plugin-welcome": "^0.2.4",
|
||||
"@backstage/theme": "^0.2.2",
|
||||
"@backstage/catalog-model": "^0.7.1",
|
||||
"@backstage/cli": "^0.6.0",
|
||||
"@backstage/core": "^0.6.0",
|
||||
"@backstage/plugin-api-docs": "^0.4.4",
|
||||
"@backstage/plugin-catalog": "^0.3.0",
|
||||
"@backstage/plugin-catalog-react": "^0.0.2",
|
||||
"@backstage/plugin-catalog-import": "^0.3.7",
|
||||
"@backstage/plugin-circleci": "^0.2.7",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.8",
|
||||
"@backstage/plugin-cost-insights": "^0.8.0",
|
||||
"@backstage/plugin-explore": "^0.2.4",
|
||||
"@backstage/plugin-gcp-projects": "^0.2.4",
|
||||
"@backstage/plugin-github-actions": "^0.3.1",
|
||||
"@backstage/plugin-gitops-profiles": "^0.2.4",
|
||||
"@backstage/plugin-graphiql": "^0.2.7",
|
||||
"@backstage/plugin-org": "^0.3.5",
|
||||
"@backstage/plugin-jenkins": "^0.3.8",
|
||||
"@backstage/plugin-kafka": "^0.2.1",
|
||||
"@backstage/plugin-kubernetes": "^0.3.8",
|
||||
"@backstage/plugin-lighthouse": "^0.2.9",
|
||||
"@backstage/plugin-newrelic": "^0.2.4",
|
||||
"@backstage/plugin-pagerduty": "0.2.7",
|
||||
"@backstage/plugin-register-component": "^0.2.8",
|
||||
"@backstage/plugin-rollbar": "^0.2.9",
|
||||
"@backstage/plugin-scaffolder": "^0.4.2",
|
||||
"@backstage/plugin-sentry": "^0.3.4",
|
||||
"@backstage/plugin-search": "^0.2.7",
|
||||
"@backstage/plugin-tech-radar": "^0.3.4",
|
||||
"@backstage/plugin-techdocs": "^0.5.5",
|
||||
"@backstage/plugin-user-settings": "^0.2.5",
|
||||
"@backstage/plugin-welcome": "^0.2.5",
|
||||
"@backstage/theme": "^0.2.3",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@octokit/rest": "^18.0.12",
|
||||
|
||||
+15
-14
@@ -15,30 +15,30 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
createApp,
|
||||
AlertDisplay,
|
||||
OAuthRequestDialog,
|
||||
SignInPage,
|
||||
createApp,
|
||||
createRouteRef,
|
||||
FlatRoutes,
|
||||
OAuthRequestDialog,
|
||||
SignInPage,
|
||||
} from '@backstage/core';
|
||||
import React from 'react';
|
||||
import Root from './components/Root';
|
||||
import * as plugins from './plugins';
|
||||
import { apis } from './apis';
|
||||
import { hot } from 'react-hot-loader/root';
|
||||
import { providers } from './identityProviders';
|
||||
import { Router as CatalogRouter } from '@backstage/plugin-catalog';
|
||||
import { Router as DocsRouter } from '@backstage/plugin-techdocs';
|
||||
import { Router as ImportComponentRouter } from '@backstage/plugin-catalog-import';
|
||||
import { ExplorePage } from '@backstage/plugin-explore';
|
||||
import { Router as GraphiQLRouter } from '@backstage/plugin-graphiql';
|
||||
import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar';
|
||||
import { Router as LighthouseRouter } from '@backstage/plugin-lighthouse';
|
||||
import { Router as RegisterComponentRouter } from '@backstage/plugin-register-component';
|
||||
import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar';
|
||||
import { Router as DocsRouter } from '@backstage/plugin-techdocs';
|
||||
import { Router as SettingsRouter } from '@backstage/plugin-user-settings';
|
||||
import { Router as ImportComponentRouter } from '@backstage/plugin-catalog-import';
|
||||
import { Route, Navigate } from 'react-router';
|
||||
|
||||
import React from 'react';
|
||||
import { hot } from 'react-hot-loader/root';
|
||||
import { Navigate, Route } from 'react-router';
|
||||
import { apis } from './apis';
|
||||
import { EntityPage } from './components/catalog/EntityPage';
|
||||
import Root from './components/Root';
|
||||
import { providers } from './identityProviders';
|
||||
import * as plugins from './plugins';
|
||||
|
||||
const app = createApp({
|
||||
apis,
|
||||
@@ -78,6 +78,7 @@ const routes = (
|
||||
element={<CatalogRouter EntityPage={EntityPage} />}
|
||||
/>
|
||||
<Route path="/docs" element={<DocsRouter />} />
|
||||
<Route path="/explore" element={<ExplorePage />} />
|
||||
<Route
|
||||
path="/tech-radar"
|
||||
element={<TechRadarRouter width={1500} height={800} />}
|
||||
|
||||
@@ -20,6 +20,7 @@ import HomeIcon from '@material-ui/icons/Home';
|
||||
import ExtensionIcon from '@material-ui/icons/Extension';
|
||||
import RuleIcon from '@material-ui/icons/AssignmentTurnedIn';
|
||||
import MapIcon from '@material-ui/icons/MyLocation';
|
||||
import LayersIcon from '@material-ui/icons/Layers';
|
||||
import LibraryBooks from '@material-ui/icons/LibraryBooks';
|
||||
import CreateComponentIcon from '@material-ui/icons/AddCircleOutline';
|
||||
import MoneyIcon from '@material-ui/icons/MonetizationOn';
|
||||
@@ -82,6 +83,7 @@ const Root = ({ children }: PropsWithChildren<{}>) => (
|
||||
<SidebarItem icon={HomeIcon} to="/catalog" text="Home" />
|
||||
<SidebarItem icon={ExtensionIcon} to="api-docs" text="APIs" />
|
||||
<SidebarItem icon={LibraryBooks} to="docs" text="Docs" />
|
||||
<SidebarItem icon={LayersIcon} to="explore" text="Explore" />
|
||||
<SidebarItem icon={CreateComponentIcon} to="create" text="Create..." />
|
||||
{/* End global nav */}
|
||||
<SidebarDivider />
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ApiEntity,
|
||||
Entity,
|
||||
@@ -64,6 +65,10 @@ import {
|
||||
isPluginApplicableToEntity as isPagerDutyAvailable,
|
||||
PagerDutyCard,
|
||||
} from '@backstage/plugin-pagerduty';
|
||||
import {
|
||||
isRollbarAvailable,
|
||||
Router as RollbarRouter,
|
||||
} from '@backstage/plugin-rollbar';
|
||||
import { Router as SentryRouter } from '@backstage/plugin-sentry';
|
||||
import { EmbeddedDocsRouter as DocsRouter } from '@backstage/plugin-techdocs';
|
||||
import { Button, Grid } from '@material-ui/core';
|
||||
@@ -153,6 +158,15 @@ const RecentCICDRunsSwitcher = ({ entity }: { entity: Entity }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const ErrorsSwitcher = ({ entity }: { entity: Entity }) => {
|
||||
switch (true) {
|
||||
case isRollbarAvailable(entity):
|
||||
return <RollbarRouter entity={entity} />;
|
||||
default:
|
||||
return <SentryRouter entity={entity} />;
|
||||
}
|
||||
};
|
||||
|
||||
const ComponentOverviewContent = ({ entity }: { entity: Entity }) => (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
@@ -212,9 +226,9 @@ const ServiceEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
element={<CICDSwitcher entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/sentry"
|
||||
title="Sentry"
|
||||
element={<SentryRouter entity={entity} />}
|
||||
path="/errors/*"
|
||||
title="Errors"
|
||||
element={<ErrorsSwitcher entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/api/*"
|
||||
@@ -267,9 +281,9 @@ const WebsiteEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
element={<LighthouseRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/sentry"
|
||||
title="Sentry"
|
||||
element={<SentryRouter entity={entity} />}
|
||||
path="/errors/*"
|
||||
title="Errors"
|
||||
element={<ErrorsSwitcher entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/docs/*"
|
||||
|
||||
@@ -18,7 +18,7 @@ export { plugin as LighthousePlugin } from '@backstage/plugin-lighthouse';
|
||||
export { plugin as CatalogPlugin } from '@backstage/plugin-catalog';
|
||||
export { plugin as ScaffolderPlugin } from '@backstage/plugin-scaffolder';
|
||||
export { plugin as TechRadar } from '@backstage/plugin-tech-radar';
|
||||
export { plugin as Explore } from '@backstage/plugin-explore';
|
||||
export { explorePlugin } from '@backstage/plugin-explore';
|
||||
export { plugin as Circleci } from '@backstage/plugin-circleci';
|
||||
export { plugin as RegisterComponent } from '@backstage/plugin-register-component';
|
||||
export { plugin as Sentry } from '@backstage/plugin-sentry';
|
||||
|
||||
@@ -1,5 +1,39 @@
|
||||
# @backstage/backend-common
|
||||
|
||||
## 0.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 2430ee7c2: Updated the `rootLogger` in `@backstage/backend-common` to support custom logging options. This is useful when you want to make some changes without re-implementing the entire logger and calling `setRootLogger` or `logger.configure`. For example you can add additional `defaultMeta` tags to each log entry. The following changes are included:
|
||||
|
||||
- Added `createRootLogger` which accepts winston `LoggerOptions`. These options allow overriding the default keys.
|
||||
|
||||
Example Usage:
|
||||
|
||||
```ts
|
||||
// Create the logger
|
||||
const logger = createRootLogger({
|
||||
defaultMeta: { appName: 'backstage', appEnv: 'prod' },
|
||||
});
|
||||
|
||||
// Add a custom logger transport
|
||||
logger.add(new MyCustomTransport());
|
||||
|
||||
const config = await loadBackendConfig({
|
||||
argv: process.argv,
|
||||
logger: getRootLogger(), // already set to new logger instance
|
||||
});
|
||||
```
|
||||
|
||||
- Updated dependencies [c4abcdb60]
|
||||
- Updated dependencies [062df71db]
|
||||
- Updated dependencies [064c513e1]
|
||||
- Updated dependencies [e9aab60c7]
|
||||
- Updated dependencies [3149bfe63]
|
||||
- Updated dependencies [2e62aea6f]
|
||||
- @backstage/integration@0.3.2
|
||||
- @backstage/config-loader@0.5.1
|
||||
|
||||
## 0.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-common",
|
||||
"description": "Common functionality library for Backstage backends",
|
||||
"version": "0.5.1",
|
||||
"version": "0.5.2",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -31,8 +31,8 @@
|
||||
"dependencies": {
|
||||
"@backstage/cli-common": "^0.1.1",
|
||||
"@backstage/config": "^0.1.2",
|
||||
"@backstage/config-loader": "^0.5.0",
|
||||
"@backstage/integration": "^0.3.1",
|
||||
"@backstage/config-loader": "^0.5.1",
|
||||
"@backstage/integration": "^0.3.2",
|
||||
"@types/cors": "^2.8.6",
|
||||
"@types/express": "^4.17.6",
|
||||
"archiver": "^5.0.2",
|
||||
@@ -66,7 +66,7 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.5.0",
|
||||
"@backstage/cli": "^0.6.0",
|
||||
"@backstage/test-utils": "^0.1.5",
|
||||
"@types/archiver": "^5.1.0",
|
||||
"@types/compression": "^1.7.0",
|
||||
|
||||
@@ -76,6 +76,8 @@ function withRetries(count: number, fn: () => Promise<void>) {
|
||||
}
|
||||
|
||||
describe('UrlReaders', () => {
|
||||
jest.setTimeout(30_000);
|
||||
|
||||
it(
|
||||
'should read data from azure',
|
||||
withRetries(3, async () => {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import tar, { Parse, ParseStream, ReadEntry } from 'tar';
|
||||
import path from 'path';
|
||||
import platformPath from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import { Readable, pipeline as pipelineCb } from 'stream';
|
||||
import { promisify } from 'util';
|
||||
@@ -147,7 +147,7 @@ export class TarArchiveResponse implements ReadTreeResponse {
|
||||
|
||||
const dir =
|
||||
options?.targetDir ??
|
||||
(await fs.mkdtemp(path.join(this.workDir, 'backstage-')));
|
||||
(await fs.mkdtemp(platformPath.join(this.workDir, 'backstage-')));
|
||||
|
||||
// Equivalent of tar --strip-components=N
|
||||
// When no subPath is given, remove just 1 top level directory
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import platformPath from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import unzipper, { Entry } from 'unzipper';
|
||||
import archiver from 'archiver';
|
||||
@@ -144,7 +144,7 @@ export class ZipArchiveResponse implements ReadTreeResponse {
|
||||
|
||||
const dir =
|
||||
options?.targetDir ??
|
||||
(await fs.mkdtemp(path.join(this.workDir, 'backstage-')));
|
||||
(await fs.mkdtemp(platformPath.join(this.workDir, 'backstage-')));
|
||||
|
||||
await this.stream
|
||||
.pipe(unzipper.Parse())
|
||||
@@ -155,11 +155,11 @@ export class ZipArchiveResponse implements ReadTreeResponse {
|
||||
const entryPath = this.getInnerPath(
|
||||
this.stripTopDirectory(entry.path),
|
||||
);
|
||||
const dirname = path.dirname(entryPath);
|
||||
const dirname = platformPath.dirname(entryPath);
|
||||
if (dirname) {
|
||||
await fs.mkdirp(path.join(dir, dirname));
|
||||
await fs.mkdirp(platformPath.join(dir, dirname));
|
||||
}
|
||||
entry.pipe(fs.createWriteStream(path.join(dir, entryPath)));
|
||||
entry.pipe(fs.createWriteStream(platformPath.join(dir, entryPath)));
|
||||
} else {
|
||||
entry.autodrain();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# example-backend
|
||||
|
||||
## 0.2.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c777df180]
|
||||
- Updated dependencies [2430ee7c2]
|
||||
- Updated dependencies [3149bfe63]
|
||||
- Updated dependencies [6e612ce25]
|
||||
- Updated dependencies [e44925723]
|
||||
- Updated dependencies [9d6ef14bc]
|
||||
- Updated dependencies [a26668913]
|
||||
- Updated dependencies [025e122c3]
|
||||
- Updated dependencies [e9aab60c7]
|
||||
- Updated dependencies [24e47ef1e]
|
||||
- Updated dependencies [7881f2117]
|
||||
- Updated dependencies [529d16d27]
|
||||
- Updated dependencies [cdea0baf1]
|
||||
- Updated dependencies [11cb5ef94]
|
||||
- @backstage/plugin-techdocs-backend@0.5.5
|
||||
- @backstage/backend-common@0.5.2
|
||||
- @backstage/plugin-catalog-backend@0.6.0
|
||||
- @backstage/catalog-model@0.7.1
|
||||
- example-app@0.2.14
|
||||
- @backstage/plugin-scaffolder-backend@0.6.0
|
||||
- @backstage/plugin-app-backend@0.3.6
|
||||
|
||||
## 0.2.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "example-backend",
|
||||
"version": "0.2.13",
|
||||
"version": "0.2.14",
|
||||
"main": "dist/index.cjs.js",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -27,24 +27,24 @@
|
||||
"migrate:create": "knex migrate:make -x ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.5.1",
|
||||
"@backstage/catalog-model": "^0.7.0",
|
||||
"@backstage/backend-common": "^0.5.2",
|
||||
"@backstage/catalog-model": "^0.7.1",
|
||||
"@backstage/config": "^0.1.2",
|
||||
"@backstage/plugin-app-backend": "^0.3.5",
|
||||
"@backstage/plugin-app-backend": "^0.3.6",
|
||||
"@backstage/plugin-auth-backend": "^0.2.12",
|
||||
"@backstage/plugin-catalog-backend": "^0.5.5",
|
||||
"@backstage/plugin-catalog-backend": "^0.6.0",
|
||||
"@backstage/plugin-graphql-backend": "^0.1.5",
|
||||
"@backstage/plugin-kubernetes-backend": "^0.2.6",
|
||||
"@backstage/plugin-kafka-backend": "^0.2.0",
|
||||
"@backstage/plugin-proxy-backend": "^0.2.4",
|
||||
"@backstage/plugin-rollbar-backend": "^0.1.7",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.5.2",
|
||||
"@backstage/plugin-techdocs-backend": "^0.5.4",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.6.0",
|
||||
"@backstage/plugin-techdocs-backend": "^0.5.5",
|
||||
"@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.13",
|
||||
"example-app": "^0.2.14",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^3.0.3",
|
||||
"knex": "^0.21.6",
|
||||
@@ -54,7 +54,7 @@
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.5.0",
|
||||
"@backstage/cli": "^0.6.0",
|
||||
"@types/dockerode": "^3.2.1",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/express-serve-static-core": "^4.17.5"
|
||||
|
||||
@@ -29,12 +29,12 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^0.7.0",
|
||||
"@backstage/catalog-model": "^0.7.1",
|
||||
"@backstage/config": "^0.1.2",
|
||||
"cross-fetch": "^3.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.5.0",
|
||||
"@backstage/cli": "^0.6.0",
|
||||
"@types/jest": "^26.0.7",
|
||||
"msw": "^0.21.2"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @backstage/catalog-model
|
||||
|
||||
## 0.7.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 6e612ce25: Adds a new optional `links` metadata field to the Entity class within the `catalog-model` package (as discussed in [[RFC] Entity Links](https://github.com/backstage/backstage/issues/3787)). This PR adds support for the entity links only. Follow up PR's will introduce the UI component to display them.
|
||||
- 025e122c3: Replace `yup` with `ajv`, for validation of catalog entities.
|
||||
- 7881f2117: Introduce json schema variants of the `yup` validation schemas
|
||||
- 11cb5ef94: Implement matchEntityWithRef for client side filtering of entities by ref matching
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/catalog-model",
|
||||
"version": "0.7.0",
|
||||
"version": "0.7.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -39,7 +39,7 @@
|
||||
"yup": "^0.29.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.5.0",
|
||||
"@backstage/cli": "^0.6.0",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/jest": "^26.0.7",
|
||||
"@types/lodash": "^4.14.151",
|
||||
|
||||
@@ -27,6 +27,7 @@ export type {
|
||||
} from './Entity';
|
||||
export * from './policies';
|
||||
export {
|
||||
compareEntityToRef,
|
||||
getEntityName,
|
||||
parseEntityName,
|
||||
parseEntityRef,
|
||||
|
||||
@@ -16,7 +16,12 @@
|
||||
|
||||
import { ENTITY_DEFAULT_NAMESPACE } from './constants';
|
||||
import { Entity } from './Entity';
|
||||
import { parseEntityName, parseEntityRef, serializeEntityRef } from './ref';
|
||||
import {
|
||||
compareEntityToRef,
|
||||
parseEntityName,
|
||||
parseEntityRef,
|
||||
serializeEntityRef,
|
||||
} from './ref';
|
||||
|
||||
describe('ref', () => {
|
||||
describe('parseEntityName', () => {
|
||||
@@ -381,4 +386,320 @@ describe('ref', () => {
|
||||
).toEqual({ kind: 'a', namespace: 'b', name: 'c/x' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('compareEntityToRef', () => {
|
||||
const entityWithNamespace: Entity = {
|
||||
apiVersion: 'a',
|
||||
kind: 'K',
|
||||
metadata: {
|
||||
name: 'n',
|
||||
namespace: 'ns',
|
||||
},
|
||||
};
|
||||
const entityWithoutNamespace: Entity = {
|
||||
apiVersion: 'a',
|
||||
kind: 'K',
|
||||
metadata: {
|
||||
name: 'n',
|
||||
},
|
||||
};
|
||||
|
||||
it('handles matching string refs', () => {
|
||||
expect(compareEntityToRef(entityWithNamespace, 'K:ns/n')).toBe(true);
|
||||
expect(compareEntityToRef(entityWithNamespace, 'k:nS/N')).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, 'K:n', {
|
||||
defaultNamespace: 'ns',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, 'K:n', {
|
||||
defaultNamespace: 'Ns',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, 'ns/n', { defaultKind: 'K' }),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, 'n', {
|
||||
defaultKind: 'K',
|
||||
defaultNamespace: 'ns',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, 'N', {
|
||||
defaultKind: 'k',
|
||||
defaultNamespace: 'nS',
|
||||
}),
|
||||
).toBe(true);
|
||||
|
||||
expect(compareEntityToRef(entityWithoutNamespace, 'K:default/n')).toBe(
|
||||
true,
|
||||
);
|
||||
expect(compareEntityToRef(entityWithoutNamespace, 'K:deFault/n')).toBe(
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, 'K:n', {
|
||||
defaultNamespace: 'default',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, 'K:n', {
|
||||
defaultNamespace: 'deFault',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(compareEntityToRef(entityWithoutNamespace, 'K:default/n')).toBe(
|
||||
true,
|
||||
);
|
||||
expect(compareEntityToRef(entityWithoutNamespace, 'K:n')).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, 'default/n', {
|
||||
defaultKind: 'K',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, 'n', {
|
||||
defaultKind: 'K',
|
||||
defaultNamespace: 'default',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, 'n', {
|
||||
defaultKind: 'K',
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('handles mismatching string refs', () => {
|
||||
expect(compareEntityToRef(entityWithNamespace, 'X:ns/n')).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, 'ns/n', {
|
||||
defaultKind: 'X',
|
||||
}),
|
||||
).toBe(false);
|
||||
|
||||
expect(compareEntityToRef(entityWithNamespace, 'K:xx/n')).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, 'K:n', {
|
||||
defaultNamespace: 'xx',
|
||||
}),
|
||||
).toBe(false);
|
||||
|
||||
expect(compareEntityToRef(entityWithNamespace, 'K:ns/x')).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, 'x', {
|
||||
defaultKind: 'K',
|
||||
defaultNamespace: 'ns',
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('handles matching compound refs', () => {
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, {
|
||||
kind: 'K',
|
||||
namespace: 'ns',
|
||||
name: 'n',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, {
|
||||
kind: 'k',
|
||||
namespace: 'Ns',
|
||||
name: 'N',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithNamespace,
|
||||
{ kind: 'K', name: 'n' },
|
||||
{
|
||||
defaultNamespace: 'ns',
|
||||
},
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithNamespace,
|
||||
{ namespace: 'ns', name: 'n' },
|
||||
{ defaultKind: 'K' },
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, 'n', {
|
||||
defaultKind: 'K',
|
||||
defaultNamespace: 'ns',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, 'N', {
|
||||
defaultKind: 'k',
|
||||
defaultNamespace: 'nS',
|
||||
}),
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, {
|
||||
kind: 'K',
|
||||
namespace: 'default',
|
||||
name: 'n',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, {
|
||||
kind: 'k',
|
||||
namespace: 'deFault',
|
||||
name: 'N',
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithoutNamespace,
|
||||
{ kind: 'K', name: 'n' },
|
||||
{
|
||||
defaultNamespace: 'default',
|
||||
},
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, { kind: 'K', name: 'n' }),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithoutNamespace,
|
||||
{ namespace: 'default', name: 'n' },
|
||||
{
|
||||
defaultKind: 'K',
|
||||
},
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithoutNamespace,
|
||||
{ name: 'n' },
|
||||
{
|
||||
defaultKind: 'K',
|
||||
defaultNamespace: 'default',
|
||||
},
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithoutNamespace,
|
||||
{ name: 'N' },
|
||||
{
|
||||
defaultKind: 'k',
|
||||
defaultNamespace: 'defAult',
|
||||
},
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithoutNamespace,
|
||||
{ name: 'n' },
|
||||
{
|
||||
defaultKind: 'K',
|
||||
},
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('handles mismatching compound refs', () => {
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, {
|
||||
kind: 'X',
|
||||
namespace: 'ns',
|
||||
name: 'n',
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithNamespace,
|
||||
{
|
||||
namespace: 'ns',
|
||||
name: 'n',
|
||||
},
|
||||
{ defaultKind: 'X' },
|
||||
),
|
||||
).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, {
|
||||
kind: 'X',
|
||||
namespace: 'default',
|
||||
name: 'n',
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithoutNamespace,
|
||||
{
|
||||
namespace: 'default',
|
||||
name: 'n',
|
||||
},
|
||||
{ defaultKind: 'X' },
|
||||
),
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, {
|
||||
kind: 'K',
|
||||
namespace: 'xx',
|
||||
name: 'n',
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithNamespace,
|
||||
{
|
||||
kind: 'K',
|
||||
name: 'n',
|
||||
},
|
||||
{ defaultNamespace: 'xx' },
|
||||
),
|
||||
).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, {
|
||||
kind: 'K',
|
||||
namespace: 'xx',
|
||||
name: 'n',
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithoutNamespace,
|
||||
{
|
||||
kind: 'K',
|
||||
name: 'n',
|
||||
},
|
||||
{ defaultNamespace: 'xx' },
|
||||
),
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
compareEntityToRef(entityWithNamespace, {
|
||||
kind: 'K',
|
||||
namespace: 'ns',
|
||||
name: 'x',
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(entityWithoutNamespace, {
|
||||
kind: 'K',
|
||||
namespace: 'default',
|
||||
name: 'x',
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
compareEntityToRef(
|
||||
entityWithoutNamespace,
|
||||
{
|
||||
kind: 'K',
|
||||
name: 'x',
|
||||
},
|
||||
{ defaultNamespace: 'default' },
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,6 +18,27 @@ import { EntityName, EntityRef } from '../types';
|
||||
import { ENTITY_DEFAULT_NAMESPACE } from './constants';
|
||||
import { Entity } from './Entity';
|
||||
|
||||
function parseRefString(
|
||||
ref: string,
|
||||
): {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name: string;
|
||||
} {
|
||||
const match = /^([^:/]+:)?([^:/]+\/)?([^:/]+)$/.exec(ref.trim());
|
||||
if (!match) {
|
||||
throw new TypeError(
|
||||
`Entity reference "${ref}" was not on the form [<kind>:][<namespace>/]<name>`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
kind: match[1]?.slice(0, -1),
|
||||
namespace: match[2]?.slice(0, -1),
|
||||
name: match[3],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the kind, namespace and name that form the name triplet of the
|
||||
* given entity.
|
||||
@@ -121,17 +142,11 @@ export function parseEntityRef(
|
||||
}
|
||||
|
||||
if (typeof ref === 'string') {
|
||||
const match = /^([^:/]+:)?([^:/]+\/)?([^:/]+)$/.exec(ref.trim());
|
||||
if (!match) {
|
||||
throw new Error(
|
||||
`Entity reference "${ref}" was not on the form [<kind>:][<namespace>/]<name>`,
|
||||
);
|
||||
}
|
||||
|
||||
const parsed = parseRefString(ref);
|
||||
return {
|
||||
kind: match[1]?.slice(0, -1) ?? context.defaultKind,
|
||||
namespace: match[2]?.slice(0, -1) ?? context.defaultNamespace,
|
||||
name: match[3],
|
||||
kind: parsed.kind ?? context.defaultKind,
|
||||
namespace: parsed.namespace ?? context.defaultNamespace,
|
||||
name: parsed.name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -196,3 +211,53 @@ export function serializeEntityRef(
|
||||
|
||||
return `${kind ? `${kind}:` : ''}${namespace ? `${namespace}/` : ''}${name}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares an entity to either a string reference or a compound reference.
|
||||
*
|
||||
* The comparison is case insensitive, and all of kind, namespace, and name
|
||||
* must match (after applying the optional context to the ref).
|
||||
*
|
||||
* @param entity The entity to match
|
||||
* @param ref A string or compound entity ref
|
||||
* @param context An optional context of default kind and namespace, that apply
|
||||
* to the ref if given
|
||||
* @returns True if matching, false otherwise
|
||||
*/
|
||||
export function compareEntityToRef(
|
||||
entity: Entity,
|
||||
ref: EntityRef | EntityName,
|
||||
context?: EntityRefContext,
|
||||
): boolean {
|
||||
const entityKind = entity.kind;
|
||||
const entityNamespace = entity.metadata.namespace || ENTITY_DEFAULT_NAMESPACE;
|
||||
const entityName = entity.metadata.name;
|
||||
|
||||
let refKind: string | undefined;
|
||||
let refNamespace: string | undefined;
|
||||
let refName: string;
|
||||
if (typeof ref === 'string') {
|
||||
const parsed = parseRefString(ref);
|
||||
refKind = parsed.kind || context?.defaultKind;
|
||||
refNamespace =
|
||||
parsed.namespace || context?.defaultNamespace || ENTITY_DEFAULT_NAMESPACE;
|
||||
refName = parsed.name;
|
||||
} else {
|
||||
refKind = ref.kind || context?.defaultKind;
|
||||
refNamespace =
|
||||
ref.namespace || context?.defaultNamespace || ENTITY_DEFAULT_NAMESPACE;
|
||||
refName = ref.name;
|
||||
}
|
||||
|
||||
if (!refKind || !refNamespace) {
|
||||
throw new Error(
|
||||
`Entity reference or context did not contain kind and namespace`,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
entityKind.toLowerCase() === refKind.toLowerCase() &&
|
||||
entityNamespace.toLowerCase() === refNamespace.toLowerCase() &&
|
||||
entityName.toLowerCase() === refName.toLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,48 @@
|
||||
# @backstage/cli
|
||||
|
||||
## 0.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 19fe61c27: We have updated the default `eslint` rules in the `@backstage/cli` package.
|
||||
|
||||
```diff
|
||||
-'@typescript-eslint/no-shadow': 'off',
|
||||
-'@typescript-eslint/no-redeclare': 'off',
|
||||
+'no-shadow': 'off',
|
||||
+'no-redeclare': 'off',
|
||||
+'@typescript-eslint/no-shadow': 'error',
|
||||
+'@typescript-eslint/no-redeclare': 'error',
|
||||
```
|
||||
|
||||
The rules are documented [here](https://eslint.org/docs/rules/no-shadow) and [here](https://eslint.org/docs/rules/no-redeclare).
|
||||
|
||||
This involved a large number of small changes to the code base. When you compile your own code using the CLI, you may also be
|
||||
affected. We consider these rules important, and the primary recommendation is to try to update your code according to the
|
||||
documentation above. But those that prefer to not enable the rules, or need time to perform the updates, may update their
|
||||
local `.eslintrc.js` file(s) in the repo root and/or in individual plugins as they see fit:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
// ... other declarations
|
||||
rules: {
|
||||
'@typescript-eslint/no-shadow': 'off',
|
||||
'@typescript-eslint/no-redeclare': 'off',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Because of the nature of this change, we're unable to provide a grace period for the update :(
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 398e1f83e: Update `create-plugin` template to use the new composability API, by switching to exporting a single routable extension component.
|
||||
- e9aab60c7: Fixed module resolution of external libraries during backend development. Modules used to be resolved relative to the backend entrypoint, but are now resolved relative to each individual module.
|
||||
- a08c4b0b0: Add check for outdated/duplicate packages to yarn start
|
||||
- Updated dependencies [062df71db]
|
||||
- Updated dependencies [e9aab60c7]
|
||||
- @backstage/config-loader@0.5.1
|
||||
|
||||
## 0.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -38,8 +38,10 @@ module.exports = {
|
||||
},
|
||||
ignorePatterns: ['.eslintrc.js', '**/dist/**', '**/dist-types/**'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-shadow': 'off',
|
||||
'@typescript-eslint/no-redeclare': 'off',
|
||||
'no-shadow': 'off',
|
||||
'no-redeclare': 'off',
|
||||
'@typescript-eslint/no-shadow': 'error',
|
||||
'@typescript-eslint/no-redeclare': 'error',
|
||||
|
||||
'no-console': 0, // Permitted in console programs
|
||||
'new-cap': ['error', { capIsNew: false }], // Because Express constructs things e.g. like 'const r = express.Router()'
|
||||
|
||||
@@ -45,8 +45,10 @@ module.exports = {
|
||||
},
|
||||
ignorePatterns: ['.eslintrc.js', '**/dist/**', '**/dist-types/**'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-shadow': 'off',
|
||||
'@typescript-eslint/no-redeclare': 'off',
|
||||
'no-shadow': 'off',
|
||||
'no-redeclare': 'off',
|
||||
'@typescript-eslint/no-shadow': 'error',
|
||||
'@typescript-eslint/no-redeclare': 'error',
|
||||
'no-undef': 'off',
|
||||
'import/newline-after-import': 'error',
|
||||
'import/no-duplicates': 'warn',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/cli",
|
||||
"description": "CLI for developing Backstage plugins and apps",
|
||||
"version": "0.5.0",
|
||||
"version": "0.6.0",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -30,7 +30,7 @@
|
||||
"dependencies": {
|
||||
"@backstage/cli-common": "^0.1.1",
|
||||
"@backstage/config": "^0.1.2",
|
||||
"@backstage/config-loader": "^0.5.0",
|
||||
"@backstage/config-loader": "^0.5.1",
|
||||
"@hot-loader/react-dom": "^16.13.0",
|
||||
"@lerna/package-graph": "^3.18.5",
|
||||
"@lerna/project": "^3.18.0",
|
||||
@@ -113,12 +113,12 @@
|
||||
"yn": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/backend-common": "^0.5.1",
|
||||
"@backstage/backend-common": "^0.5.2",
|
||||
"@backstage/config": "^0.1.2",
|
||||
"@backstage/core": "^0.5.0",
|
||||
"@backstage/dev-utils": "^0.1.8",
|
||||
"@backstage/core": "^0.6.0",
|
||||
"@backstage/dev-utils": "^0.1.9",
|
||||
"@backstage/test-utils": "^0.1.6",
|
||||
"@backstage/theme": "^0.2.2",
|
||||
"@backstage/theme": "^0.2.3",
|
||||
"@types/diff": "^4.0.2",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/fs-extra": "^9.0.1",
|
||||
|
||||
@@ -63,8 +63,8 @@ function serializeConfigData(
|
||||
}
|
||||
|
||||
const sanitizedConfigs = schema.process(appConfigs, {
|
||||
valueTransform: (value, { visibility }) =>
|
||||
visibility === 'secret' ? '<secret>' : value,
|
||||
valueTransform: (value, context) =>
|
||||
context.visibility === 'secret' ? '<secret>' : value,
|
||||
});
|
||||
|
||||
return ConfigReader.fromConfigs(sanitizedConfigs).get();
|
||||
|
||||
@@ -108,7 +108,7 @@ describe('bump', () => {
|
||||
paths.targetDir = '/';
|
||||
jest
|
||||
.spyOn(paths, 'resolveTargetRoot')
|
||||
.mockImplementation((...paths) => resolvePath('/', ...paths));
|
||||
.mockImplementation((...path) => resolvePath('/', ...path));
|
||||
jest.spyOn(runObj, 'runPlain').mockImplementation(async (...[, , , name]) =>
|
||||
JSON.stringify({
|
||||
type: 'inspect',
|
||||
@@ -204,7 +204,7 @@ describe('bump', () => {
|
||||
paths.targetDir = '/';
|
||||
jest
|
||||
.spyOn(paths, 'resolveTargetRoot')
|
||||
.mockImplementation((...paths) => resolvePath('/', ...paths));
|
||||
.mockImplementation((...path) => resolvePath('/', ...path));
|
||||
jest.spyOn(runObj, 'runPlain').mockImplementation(async () => '');
|
||||
jest.spyOn(runObj, 'run').mockResolvedValue(undefined);
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ export class LinkedPackageResolvePlugin implements ResolvePlugin {
|
||||
callback: () => void,
|
||||
) => {
|
||||
const pkg = this.packages.find(
|
||||
pkg => data.path && isChildPath(pkg.location, data.path),
|
||||
pkge => data.path && isChildPath(pkge.location, data.path),
|
||||
);
|
||||
if (!pkg) {
|
||||
callback();
|
||||
|
||||
@@ -42,14 +42,14 @@ export type BundlingPathsOptions = {
|
||||
export function resolveBundlingPaths(options: BundlingPathsOptions) {
|
||||
const { entry } = options;
|
||||
|
||||
const resolveTargetModule = (path: string) => {
|
||||
const resolveTargetModule = (pathString: string) => {
|
||||
for (const ext of ['mjs', 'js', 'ts', 'tsx', 'jsx']) {
|
||||
const filePath = paths.resolveTarget(`${path}.${ext}`);
|
||||
const filePath = paths.resolveTarget(`${pathString}.${ext}`);
|
||||
if (fs.pathExistsSync(filePath)) {
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
return paths.resolveTarget(`${path}.js`);
|
||||
return paths.resolveTarget(`${pathString}.js`);
|
||||
};
|
||||
|
||||
let targetPublic = undefined;
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @backstage/config-loader
|
||||
|
||||
## 0.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 062df71db: Bump `config-loader` to `ajv` 7, to enable v7 feature use elsewhere
|
||||
- e9aab60c7: Each piece of the configuration schema is now validated upfront, in order to produce more informative errors.
|
||||
|
||||
## 0.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/config-loader",
|
||||
"description": "Config loading functionality used by Backstage backend, and CLI",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
|
||||
@@ -118,7 +118,9 @@ export async function collectConfigSchemas(
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
depNames.map(name => processItem({ name, parentPath: pkgPath })),
|
||||
depNames.map(depName =>
|
||||
processItem({ name: depName, parentPath: pkgPath }),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/config": "^0.1.2",
|
||||
"@backstage/theme": "^0.2.2",
|
||||
"@backstage/theme": "^0.2.3",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@types/react": "^16.9",
|
||||
@@ -42,7 +42,7 @@
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.5.0",
|
||||
"@backstage/cli": "^0.6.0",
|
||||
"@backstage/test-utils": "^0.1.6",
|
||||
"@backstage/test-utils-core": "^0.1.1",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
|
||||
@@ -13,12 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {
|
||||
AuthProvider,
|
||||
ProfileInfo,
|
||||
BackstageIdentity,
|
||||
DiscoveryApi,
|
||||
} from '../../apis/definitions';
|
||||
import { AuthProvider, DiscoveryApi } from '../../apis/definitions';
|
||||
import { showLoginPopup } from '../loginPopup';
|
||||
|
||||
type Options = {
|
||||
@@ -26,13 +21,6 @@ type Options = {
|
||||
environment?: string;
|
||||
provider: AuthProvider & { id: string };
|
||||
};
|
||||
|
||||
export type DirectAuthResponse = {
|
||||
userId: string;
|
||||
profile: ProfileInfo;
|
||||
backstageIdentity: BackstageIdentity;
|
||||
};
|
||||
|
||||
export class DirectAuthConnector<DirectAuthResponse> {
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
private readonly environment: string | undefined;
|
||||
|
||||
@@ -25,8 +25,8 @@ type RouteObject = {
|
||||
|
||||
// Similar to the same function from react-router, this collects routes from the
|
||||
// children, but only the first level of routes
|
||||
function createRoutesFromChildren(children: ReactNode): RouteObject[] {
|
||||
return Children.toArray(children)
|
||||
function createRoutesFromChildren(childrenNode: ReactNode): RouteObject[] {
|
||||
return Children.toArray(childrenNode)
|
||||
.flatMap(child => {
|
||||
if (!isValidElement(child)) {
|
||||
return [];
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
# @backstage/core
|
||||
|
||||
## 0.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 21e624ba9: Closes #3556
|
||||
The scroll bar of collapsed sidebar is now hidden without full screen.
|
||||
|
||||

|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 12ece98cd: Add className to the SidebarItem
|
||||
- d82246867: Update `WarningPanel` component to use accordion-style expansion
|
||||
- 5fa3bdb55: Add `href` in addition to `onClick` to `ItemCard`. Ensure that the height of a
|
||||
`ItemCard` with and without tags is equal.
|
||||
- da9f53c60: Add a `prop` union for `SignInPage` that allows it to be used for just a single provider, with inline errors, and optionally with automatic sign-in.
|
||||
- 32c95605f: Fix check that determines whether popup was closed or the messaging was misconfigured.
|
||||
- 54c7d02f7: Introduce `TabbedLayout` for creating tabs that are routed.
|
||||
|
||||
```typescript
|
||||
<TabbedLayout>
|
||||
<TabbedLayout.Route path="/example" title="Example tab">
|
||||
<div>This is rendered under /example/anything-here route</div>
|
||||
</TabbedLayout.Route>
|
||||
</TabbedLayout>
|
||||
```
|
||||
|
||||
- Updated dependencies [c810082ae]
|
||||
- @backstage/theme@0.2.3
|
||||
|
||||
## 0.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/core",
|
||||
"description": "Core API used by Backstage plugins and apps",
|
||||
"version": "0.5.0",
|
||||
"version": "0.6.0",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
@@ -31,7 +31,7 @@
|
||||
"dependencies": {
|
||||
"@backstage/config": "^0.1.2",
|
||||
"@backstage/core-api": "^0.2.8",
|
||||
"@backstage/theme": "^0.2.2",
|
||||
"@backstage/theme": "^0.2.3",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
@@ -66,7 +66,7 @@
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.5.0",
|
||||
"@backstage/cli": "^0.6.0",
|
||||
"@backstage/test-utils": "^0.1.6",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^10.4.1",
|
||||
|
||||
+9
-9
@@ -13,12 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { TabbedLayout } from './TabbedLayout';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { Routes, Route } from 'react-router';
|
||||
import { Route, Routes } from 'react-router';
|
||||
import { RoutedTabs } from './RoutedTabs';
|
||||
|
||||
const testRoute1 = {
|
||||
path: '',
|
||||
@@ -31,10 +31,10 @@ const testRoute2 = {
|
||||
children: <div>tabbed-test-content-2</div>,
|
||||
};
|
||||
|
||||
describe('TabbedLayout', () => {
|
||||
describe('RoutedTabs', () => {
|
||||
it('renders simplest case', async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<TabbedLayout routes={[testRoute1]} />,
|
||||
<RoutedTabs routes={[testRoute1]} />,
|
||||
);
|
||||
|
||||
expect(rendered.getByText('tabbed-test-title')).toBeInTheDocument();
|
||||
@@ -46,7 +46,7 @@ describe('TabbedLayout', () => {
|
||||
<Routes>
|
||||
<Route
|
||||
path="/*"
|
||||
element={<TabbedLayout routes={[testRoute1, testRoute2]} />}
|
||||
element={<RoutedTabs routes={[testRoute1, testRoute2]} />}
|
||||
/>
|
||||
</Routes>,
|
||||
);
|
||||
@@ -70,7 +70,7 @@ describe('TabbedLayout', () => {
|
||||
<Route
|
||||
path="/*"
|
||||
element={
|
||||
<TabbedLayout
|
||||
<RoutedTabs
|
||||
routes={[
|
||||
testRoute1,
|
||||
{
|
||||
@@ -122,7 +122,7 @@ describe('TabbedLayout', () => {
|
||||
|
||||
it('shows only one tab contents at a time', async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<TabbedLayout routes={[testRoute1, testRoute2]} />,
|
||||
<RoutedTabs routes={[testRoute1, testRoute2]} />,
|
||||
{ routeEntries: ['/some-other-path'] },
|
||||
);
|
||||
|
||||
@@ -135,7 +135,7 @@ describe('TabbedLayout', () => {
|
||||
|
||||
it('redirects to the top level when no route is matching the url', async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<TabbedLayout routes={[testRoute1, testRoute2]} />,
|
||||
<RoutedTabs routes={[testRoute1, testRoute2]} />,
|
||||
{ routeEntries: ['/non-existing-path'] },
|
||||
);
|
||||
|
||||
+7
-7
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React, { useMemo } from 'react';
|
||||
import { useParams, useNavigate, matchRoutes, useRoutes } from 'react-router';
|
||||
import { HeaderTabs, Content as LayoutContent } from '@backstage/core';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { matchRoutes, useNavigate, useParams, useRoutes } from 'react-router';
|
||||
import { Content, HeaderTabs } from '../../layout';
|
||||
import { SubRoute } from './types';
|
||||
|
||||
export function useSelectedSubRoute(
|
||||
@@ -44,7 +44,7 @@ export function useSelectedSubRoute(
|
||||
};
|
||||
}
|
||||
|
||||
export const TabbedLayout = ({ routes }: { routes: SubRoute[] }) => {
|
||||
export const RoutedTabs = ({ routes }: { routes: SubRoute[] }) => {
|
||||
const navigate = useNavigate();
|
||||
const { index, route, element } = useSelectedSubRoute(routes);
|
||||
const headerTabs = useMemo(
|
||||
@@ -52,12 +52,12 @@ export const TabbedLayout = ({ routes }: { routes: SubRoute[] }) => {
|
||||
[routes],
|
||||
);
|
||||
|
||||
const onTabChange = (index: number) =>
|
||||
const onTabChange = (tabIndex: number) =>
|
||||
// Remove trailing /*
|
||||
// And remove leading / for relative navigation
|
||||
// Note! route resolves relative to the position in the React tree,
|
||||
// not relative to current location
|
||||
navigate(routes[index].path.replace(/\/\*$/, '').replace(/^\//, ''));
|
||||
navigate(routes[tabIndex].path.replace(/\/\*$/, '').replace(/^\//, ''));
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -66,10 +66,10 @@ export const TabbedLayout = ({ routes }: { routes: SubRoute[] }) => {
|
||||
selectedIndex={index}
|
||||
onChange={onTabChange}
|
||||
/>
|
||||
<LayoutContent>
|
||||
<Content>
|
||||
<Helmet title={route.title} />
|
||||
{element}
|
||||
</LayoutContent>
|
||||
</Content>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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, { PropsWithChildren } from 'react';
|
||||
import { MemoryRouter, Route, Routes } from 'react-router';
|
||||
import { TabbedLayout } from './TabbedLayout';
|
||||
|
||||
export default {
|
||||
title: 'Navigation/TabbedLayout',
|
||||
component: TabbedLayout,
|
||||
};
|
||||
|
||||
const Wrapper = ({ children }: PropsWithChildren<{}>) => (
|
||||
<MemoryRouter>
|
||||
<Routes>
|
||||
<Route path="/*" element={<>{children}</>} />
|
||||
</Routes>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
export const Default = () => (
|
||||
<Wrapper>
|
||||
<TabbedLayout>
|
||||
<TabbedLayout.Route path="/" title="tabbed-test-title">
|
||||
<div>tabbed-test-content</div>
|
||||
</TabbedLayout.Route>
|
||||
<TabbedLayout.Route path="/some-other-path" title="tabbed-test-title-2">
|
||||
<div>tabbed-test-content-2</div>
|
||||
</TabbedLayout.Route>
|
||||
</TabbedLayout>
|
||||
</Wrapper>
|
||||
);
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 { renderInTestApp, withLogCollector } from '@backstage/test-utils';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { Route, Routes } from 'react-router';
|
||||
import { TabbedLayout } from './TabbedLayout';
|
||||
|
||||
describe('TabbedLayout', () => {
|
||||
it('renders simplest case', async () => {
|
||||
const { getByText } = await renderInTestApp(
|
||||
<TabbedLayout>
|
||||
<TabbedLayout.Route path="/" title="tabbed-test-title">
|
||||
<div>tabbed-test-content</div>
|
||||
</TabbedLayout.Route>
|
||||
</TabbedLayout>,
|
||||
);
|
||||
|
||||
expect(getByText('tabbed-test-title')).toBeInTheDocument();
|
||||
expect(getByText('tabbed-test-content')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('throws if any other component is a child of TabbedLayout', async () => {
|
||||
const { error } = await withLogCollector(async () => {
|
||||
await expect(
|
||||
renderInTestApp(
|
||||
<TabbedLayout>
|
||||
<TabbedLayout.Route path="/" title="tabbed-test-title">
|
||||
<div>tabbed-test-content</div>
|
||||
</TabbedLayout.Route>
|
||||
<div>This will cause app to throw</div>
|
||||
</TabbedLayout>,
|
||||
),
|
||||
).rejects.toThrow(/Child of TabbedLayout must be an TabbedLayout.Route/);
|
||||
});
|
||||
|
||||
expect(error).toEqual([
|
||||
expect.stringMatching(
|
||||
/Child of TabbedLayout must be an TabbedLayout.Route/,
|
||||
),
|
||||
expect.stringMatching(
|
||||
/The above error occurred in the <TabbedLayout> component/,
|
||||
),
|
||||
]);
|
||||
});
|
||||
|
||||
it('navigates when user clicks different tab', async () => {
|
||||
const { getByText, queryByText, queryAllByRole } = await renderInTestApp(
|
||||
<Routes>
|
||||
<Route
|
||||
path="/*"
|
||||
element={
|
||||
<TabbedLayout>
|
||||
<TabbedLayout.Route path="/" title="tabbed-test-title">
|
||||
<div>tabbed-test-content</div>
|
||||
</TabbedLayout.Route>
|
||||
<TabbedLayout.Route
|
||||
path="/some-other-path"
|
||||
title="tabbed-test-title-2"
|
||||
>
|
||||
<div>tabbed-test-content-2</div>
|
||||
</TabbedLayout.Route>
|
||||
</TabbedLayout>
|
||||
}
|
||||
/>
|
||||
</Routes>,
|
||||
);
|
||||
|
||||
const secondTab = queryAllByRole('tab')[1];
|
||||
act(() => {
|
||||
fireEvent.click(secondTab);
|
||||
});
|
||||
|
||||
expect(getByText('tabbed-test-title')).toBeInTheDocument();
|
||||
expect(queryByText('tabbed-test-content')).not.toBeInTheDocument();
|
||||
|
||||
expect(getByText('tabbed-test-title-2')).toBeInTheDocument();
|
||||
expect(queryByText('tabbed-test-content-2')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -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 { attachComponentData } from '@backstage/core-api';
|
||||
import React, {
|
||||
Children,
|
||||
Fragment,
|
||||
isValidElement,
|
||||
PropsWithChildren,
|
||||
ReactNode,
|
||||
} from 'react';
|
||||
import { RoutedTabs } from './RoutedTabs';
|
||||
|
||||
type SubRoute = {
|
||||
path: string;
|
||||
title: string;
|
||||
children: JSX.Element;
|
||||
};
|
||||
|
||||
const Route: (props: SubRoute) => null = () => null;
|
||||
|
||||
// This causes all mount points that are discovered within this route to use the path of the route itself
|
||||
attachComponentData(Route, 'core.gatherMountPoints', true);
|
||||
|
||||
export function createSubRoutesFromChildren(
|
||||
childrenProps: ReactNode,
|
||||
): SubRoute[] {
|
||||
// Directly comparing child.type with Route will not work with in
|
||||
// combination with react-hot-loader in storybook
|
||||
// https://github.com/gaearon/react-hot-loader/issues/304
|
||||
const routeType = (
|
||||
<Route path="" title="">
|
||||
<div />
|
||||
</Route>
|
||||
).type;
|
||||
|
||||
return Children.toArray(childrenProps).flatMap(child => {
|
||||
if (!isValidElement(child)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (child.type === Fragment) {
|
||||
return createSubRoutesFromChildren(child.props.children);
|
||||
}
|
||||
|
||||
if (child.type !== routeType) {
|
||||
throw new Error('Child of TabbedLayout must be an TabbedLayout.Route');
|
||||
}
|
||||
|
||||
const { path, title, children } = child.props;
|
||||
return [{ path, title, children }];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* TabbedLayout is a compound component, which allows you to define a layout for
|
||||
* pages using a sub-navigation mechanism.
|
||||
*
|
||||
* Consists of two parts: TabbedLayout and TabbedLayout.Route
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* <TabbedLayout>
|
||||
* <TabbedLayout.Route path="/example" title="Example tab">
|
||||
* <div>This is rendered under /example/anything-here route</div>
|
||||
* </TabbedLayout.Route>
|
||||
* </TabbedLayout>
|
||||
* ```
|
||||
*/
|
||||
export const TabbedLayout = ({ children }: PropsWithChildren<{}>) => {
|
||||
const routes = createSubRoutesFromChildren(children);
|
||||
|
||||
return <RoutedTabs routes={routes} />;
|
||||
};
|
||||
|
||||
TabbedLayout.Route = Route;
|
||||
@@ -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 { TabbedLayout } from './TabbedLayout';
|
||||
@@ -21,10 +21,13 @@ export * from './CodeSnippet';
|
||||
export * from './CopyTextButton';
|
||||
export * from './DependencyGraph';
|
||||
export * from './DismissableBanner';
|
||||
export * from './EmptyState';
|
||||
export * from './FeatureDiscovery';
|
||||
export * from './HeaderIconLinkRow';
|
||||
export * from './HorizontalScrollGrid';
|
||||
export * from './Lifecycle';
|
||||
export * from './Link';
|
||||
export * from './MarkdownContent';
|
||||
export * from './OAuthRequestDialog';
|
||||
export * from './Progress';
|
||||
export * from './ProgressBars';
|
||||
@@ -32,10 +35,8 @@ export * from './SimpleStepper';
|
||||
export * from './Status';
|
||||
export * from './StructuredMetadataTable';
|
||||
export * from './SupportButton';
|
||||
export * from './TabbedLayout';
|
||||
export * from './Table';
|
||||
export * from './Tabs';
|
||||
export * from './TrendLine';
|
||||
export * from './WarningPanel';
|
||||
export * from './EmptyState';
|
||||
export * from './MarkdownContent';
|
||||
export * from './HeaderIconLinkRow';
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// 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';
|
||||
import { makeStyles, Tabs, Tab as TabUI } from '@material-ui/core';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
tabsWrapper: {
|
||||
@@ -81,7 +81,7 @@ export const HeaderTabs = ({
|
||||
value={selectedTab}
|
||||
>
|
||||
{tabs.map((tab, index) => (
|
||||
<Tab
|
||||
<TabUI
|
||||
label={tab.label}
|
||||
key={tab.id}
|
||||
value={index}
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { ItemCard } from '.';
|
||||
import { Grid } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { ItemCard } from '.';
|
||||
|
||||
export default {
|
||||
title: 'Layout/Item Card',
|
||||
@@ -63,5 +64,35 @@ export const Tags = () => (
|
||||
label="Button"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={3}>
|
||||
<ItemCard
|
||||
title="Item Card"
|
||||
description="This is the description of an Item Card without Tags"
|
||||
label="Button"
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
export const Link = () => (
|
||||
<MemoryRouter>
|
||||
<Grid container spacing={4}>
|
||||
<Grid item xs={12} md={3}>
|
||||
<ItemCard
|
||||
title="Backstage"
|
||||
description="This is the description of an Item Card with link"
|
||||
label="Read More"
|
||||
href="https://backstage.io"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={3}>
|
||||
<ItemCard
|
||||
title="Backstage @ GitHub"
|
||||
description="This is the description of an Item Card with link"
|
||||
label="Read More"
|
||||
href="https://github.com/backstage/backstage"
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Button, Card, Chip, makeStyles, Typography } from '@material-ui/core';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import { Button, Card, Chip, Typography, makeStyles } from '@material-ui/core';
|
||||
import { Link } from '../../components';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
header: {
|
||||
@@ -30,6 +32,9 @@ const useStyles = makeStyles(theme => ({
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
withTags: {
|
||||
height: 'calc(175px - 32px - 8px)',
|
||||
},
|
||||
footer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row-reverse',
|
||||
@@ -43,7 +48,9 @@ type ItemCardProps = {
|
||||
type?: string;
|
||||
label: string;
|
||||
onClick?: () => void;
|
||||
href?: string;
|
||||
};
|
||||
|
||||
export const ItemCard = ({
|
||||
description,
|
||||
tags,
|
||||
@@ -51,6 +58,7 @@ export const ItemCard = ({
|
||||
type,
|
||||
label,
|
||||
onClick,
|
||||
href,
|
||||
}: ItemCardProps) => {
|
||||
const classes = useStyles();
|
||||
|
||||
@@ -64,13 +72,27 @@ export const ItemCard = ({
|
||||
{tags?.map((tag, i) => (
|
||||
<Chip label={tag} key={`tag-${i}`} />
|
||||
))}
|
||||
<Typography variant="body2" paragraph className={classes.description}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
paragraph
|
||||
className={clsx(
|
||||
classes.description,
|
||||
tags && tags.length > 0 && classes.withTags,
|
||||
)}
|
||||
>
|
||||
{description}
|
||||
</Typography>
|
||||
<div className={classes.footer}>
|
||||
<Button onClick={onClick} color="primary">
|
||||
{label}
|
||||
</Button>
|
||||
{!href && (
|
||||
<Button onClick={onClick} color="primary">
|
||||
{label}
|
||||
</Button>
|
||||
)}
|
||||
{href && (
|
||||
<Button component={Link} to={href} color="primary">
|
||||
{label}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -1,5 +1,78 @@
|
||||
# @backstage/create-app
|
||||
|
||||
## 0.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 019fe39a0: `@backstage/plugin-catalog` stopped exporting hooks and helpers for other
|
||||
plugins. They are migrated to `@backstage/plugin-catalog-react`.
|
||||
Change both your dependencies and imports to the new package.
|
||||
- 436ca3f62: Remove techdocs.requestUrl and techdocs.storageUrl from app-config.yaml
|
||||
- Updated dependencies [ceef4dd89]
|
||||
- Updated dependencies [720149854]
|
||||
- Updated dependencies [c777df180]
|
||||
- Updated dependencies [398e1f83e]
|
||||
- Updated dependencies [12ece98cd]
|
||||
- Updated dependencies [d82246867]
|
||||
- Updated dependencies [7fc89bae2]
|
||||
- Updated dependencies [c810082ae]
|
||||
- Updated dependencies [b712841d6]
|
||||
- Updated dependencies [a5628df40]
|
||||
- Updated dependencies [2430ee7c2]
|
||||
- Updated dependencies [3149bfe63]
|
||||
- Updated dependencies [5fa3bdb55]
|
||||
- Updated dependencies [bc5082a00]
|
||||
- Updated dependencies [6e612ce25]
|
||||
- Updated dependencies [e44925723]
|
||||
- Updated dependencies [b37501a3d]
|
||||
- Updated dependencies [a26668913]
|
||||
- Updated dependencies [025e122c3]
|
||||
- Updated dependencies [e9aab60c7]
|
||||
- Updated dependencies [21e624ba9]
|
||||
- Updated dependencies [19fe61c27]
|
||||
- Updated dependencies [e9aab60c7]
|
||||
- Updated dependencies [da9f53c60]
|
||||
- Updated dependencies [a08c4b0b0]
|
||||
- Updated dependencies [24e47ef1e]
|
||||
- Updated dependencies [bc5082a00]
|
||||
- Updated dependencies [b37501a3d]
|
||||
- Updated dependencies [90c8f20b9]
|
||||
- Updated dependencies [32c95605f]
|
||||
- Updated dependencies [7881f2117]
|
||||
- Updated dependencies [529d16d27]
|
||||
- Updated dependencies [54c7d02f7]
|
||||
- Updated dependencies [de98c32ed]
|
||||
- Updated dependencies [806929fe2]
|
||||
- Updated dependencies [019fe39a0]
|
||||
- Updated dependencies [cdea0baf1]
|
||||
- Updated dependencies [019fe39a0]
|
||||
- Updated dependencies [11cb5ef94]
|
||||
- @backstage/plugin-catalog-import@0.3.7
|
||||
- @backstage/plugin-scaffolder@0.4.2
|
||||
- @backstage/plugin-techdocs-backend@0.5.5
|
||||
- @backstage/cli@0.6.0
|
||||
- @backstage/core@0.6.0
|
||||
- @backstage/plugin-api-docs@0.4.4
|
||||
- @backstage/plugin-catalog@0.3.0
|
||||
- @backstage/theme@0.2.3
|
||||
- @backstage/plugin-lighthouse@0.2.9
|
||||
- @backstage/backend-common@0.5.2
|
||||
- @backstage/plugin-catalog-backend@0.6.0
|
||||
- @backstage/plugin-techdocs@0.5.5
|
||||
- @backstage/plugin-user-settings@0.2.5
|
||||
- @backstage/catalog-model@0.7.1
|
||||
- @backstage/plugin-scaffolder-backend@0.6.0
|
||||
- @backstage/plugin-app-backend@0.3.6
|
||||
- @backstage/plugin-tech-radar@0.3.4
|
||||
- @backstage/plugin-explore@0.2.4
|
||||
- @backstage/plugin-circleci@0.2.7
|
||||
- @backstage/plugin-github-actions@0.3.1
|
||||
- @backstage/plugin-search@0.2.7
|
||||
- @backstage/test-utils@0.1.6
|
||||
- @backstage/plugin-auth-backend@0.2.12
|
||||
- @backstage/plugin-proxy-backend@0.2.4
|
||||
- @backstage/plugin-rollbar-backend@0.1.7
|
||||
|
||||
## 0.3.7
|
||||
|
||||
### Patch Changes
|
||||
@@ -52,7 +125,7 @@
|
||||
- @backstage/plugin-catalog@0.2.13
|
||||
- @backstage/plugin-scaffolder-backend@0.5.1
|
||||
|
||||
## 1.0.0
|
||||
## 0.3.6
|
||||
|
||||
### Minor Changes
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/create-app",
|
||||
"description": "Create app package for Backstage",
|
||||
"version": "0.3.7",
|
||||
"version": "0.3.8",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -44,32 +44,32 @@
|
||||
"ts-node": "^8.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@backstage/backend-common": "^0.5.1",
|
||||
"@backstage/catalog-model": "^0.7.0",
|
||||
"@backstage/cli": "^0.5.0",
|
||||
"@backstage/backend-common": "^0.5.2",
|
||||
"@backstage/catalog-model": "^0.7.1",
|
||||
"@backstage/cli": "^0.6.0",
|
||||
"@backstage/config": "^0.1.2",
|
||||
"@backstage/core": "^0.5.0",
|
||||
"@backstage/plugin-api-docs": "^0.4.3",
|
||||
"@backstage/plugin-app-backend": "^0.3.5",
|
||||
"@backstage/core": "^0.6.0",
|
||||
"@backstage/plugin-api-docs": "^0.4.4",
|
||||
"@backstage/plugin-app-backend": "^0.3.6",
|
||||
"@backstage/plugin-auth-backend": "^0.2.12",
|
||||
"@backstage/plugin-catalog": "^0.2.14",
|
||||
"@backstage/plugin-catalog-backend": "^0.5.5",
|
||||
"@backstage/plugin-catalog-import": "^0.3.6",
|
||||
"@backstage/plugin-circleci": "^0.2.6",
|
||||
"@backstage/plugin-explore": "^0.2.3",
|
||||
"@backstage/plugin-github-actions": "^0.3.0",
|
||||
"@backstage/plugin-lighthouse": "^0.2.8",
|
||||
"@backstage/plugin-catalog": "^0.3.0",
|
||||
"@backstage/plugin-catalog-backend": "^0.6.0",
|
||||
"@backstage/plugin-catalog-import": "^0.3.7",
|
||||
"@backstage/plugin-circleci": "^0.2.7",
|
||||
"@backstage/plugin-explore": "^0.2.4",
|
||||
"@backstage/plugin-github-actions": "^0.3.1",
|
||||
"@backstage/plugin-lighthouse": "^0.2.9",
|
||||
"@backstage/plugin-proxy-backend": "^0.2.4",
|
||||
"@backstage/plugin-rollbar-backend": "^0.1.7",
|
||||
"@backstage/plugin-scaffolder": "^0.4.1",
|
||||
"@backstage/plugin-search": "^0.2.6",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.5.2",
|
||||
"@backstage/plugin-tech-radar": "^0.3.3",
|
||||
"@backstage/plugin-techdocs": "^0.5.4",
|
||||
"@backstage/plugin-techdocs-backend": "^0.5.4",
|
||||
"@backstage/plugin-user-settings": "^0.2.4",
|
||||
"@backstage/plugin-scaffolder": "^0.4.2",
|
||||
"@backstage/plugin-search": "^0.2.7",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.6.0",
|
||||
"@backstage/plugin-tech-radar": "^0.3.4",
|
||||
"@backstage/plugin-techdocs": "^0.5.5",
|
||||
"@backstage/plugin-techdocs-backend": "^0.5.5",
|
||||
"@backstage/plugin-user-settings": "^0.2.5",
|
||||
"@backstage/test-utils": "^0.1.6",
|
||||
"@backstage/theme": "^0.2.2"
|
||||
"@backstage/theme": "^0.2.3"
|
||||
},
|
||||
"nodemonConfig": {
|
||||
"watch": "./src",
|
||||
|
||||
@@ -56,14 +56,13 @@ proxy:
|
||||
target: 'https://example.com'
|
||||
changeOrigin: true
|
||||
|
||||
# Reference documentation http://backstage.io/docs/features/techdocs/configuration
|
||||
techdocs:
|
||||
requestUrl: http://localhost:7000/api/techdocs
|
||||
storageUrl: http://localhost:7000/api/techdocs/static/docs
|
||||
builder: 'local'
|
||||
builder: 'local' # Alternatives - 'external'
|
||||
generators:
|
||||
techdocs: 'docker'
|
||||
techdocs: 'docker' # Alternatives - 'local'
|
||||
publisher:
|
||||
type: 'local'
|
||||
type: 'local' # Alternatives - 'googleGcs' or 'awsS3'. Read documentation for using alternatives.
|
||||
|
||||
auth:
|
||||
# see https://backstage.io/docs/tutorials/quickstart-app-auth to know more about enabling auth providers
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# @backstage/dev-utils
|
||||
|
||||
## 0.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 720149854: Added `path` option to `addPage` that can be used to set a specific path for the page rather than a generated one. Also omit sidebar item altogether if `title` option is not set.
|
||||
- 019fe39a0: Switch dependency from `@backstage/plugin-catalog` to `@backstage/plugin-catalog-react`.
|
||||
- Updated dependencies [12ece98cd]
|
||||
- Updated dependencies [d82246867]
|
||||
- Updated dependencies [7fc89bae2]
|
||||
- Updated dependencies [c810082ae]
|
||||
- Updated dependencies [5fa3bdb55]
|
||||
- Updated dependencies [6e612ce25]
|
||||
- Updated dependencies [025e122c3]
|
||||
- Updated dependencies [21e624ba9]
|
||||
- Updated dependencies [da9f53c60]
|
||||
- Updated dependencies [32c95605f]
|
||||
- Updated dependencies [7881f2117]
|
||||
- Updated dependencies [54c7d02f7]
|
||||
- Updated dependencies [11cb5ef94]
|
||||
- @backstage/core@0.6.0
|
||||
- @backstage/plugin-catalog-react@0.0.2
|
||||
- @backstage/theme@0.2.3
|
||||
- @backstage/catalog-model@0.7.1
|
||||
|
||||
## 0.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user