Merge branch 'master' into rugvip/ports

This commit is contained in:
Patrik Oldsberg
2021-02-04 19:44:05 +01:00
committed by GitHub
305 changed files with 4107 additions and 1759 deletions
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-import': patch
---
Export _api_ (Client, API, ref) from the catalog import plugin.
-5
View File
@@ -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`.
-6
View File
@@ -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
-5
View File
@@ -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.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-graphiql': patch
---
Finalized composability API migration, now exporting the plugin as `graphiqlPlugin`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core': patch
---
Add className to the SidebarItem
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core': patch
---
Update `WarningPanel` component to use accordion-style expansion
-13
View File
@@ -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.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/theme': patch
---
Updates warning text color to align to updated `WarningPanel` styling
-5
View File
@@ -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`.
-5
View File
@@ -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`.
-24
View File
@@ -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
});
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-user-settings': patch
---
Migrate to new composability API, exporting the plugin as `userSettingsPlugin` and the page as `UserSettingsPage`.
-5
View File
@@ -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.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog': patch
---
Add `children` option to `addPage`, which will be rendered as the children of the `Route`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Attempt to fix windows test errors in master
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/catalog-model': patch
---
Replace `yup` with `ajv`, for validation of catalog entities.
-5
View File
@@ -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.
-8
View File
@@ -1,8 +0,0 @@
---
'@backstage/core': minor
---
Closes #3556
The scroll bar of collapsed sidebar is now hidden without full screen.
![image](https://user-images.githubusercontent.com/46953622/105390193-0bfd0080-5c19-11eb-8e86-2161bbe6e8d9.png)
-5
View File
@@ -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`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/config-loader': patch
---
Bump `config-loader` to `ajv` 7, to enable v7 feature use elsewhere
-5
View File
@@ -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.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/integration': patch
---
Properly forward errors that occur when looking up GitLab project IDs.
-5
View File
@@ -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.
-5
View File
@@ -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.
-5
View File
@@ -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.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Add check for outdated/duplicate packages to yarn start
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-gcp-projects': patch
---
Migrate to new composability API, exporting the plugin as `gcpProjectsPlugin` and page as `GcpProjectsPage`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-backend': patch
---
Throw `NotAllowedError` when registering locations with entities of disallowed kinds
-8
View File
@@ -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 />`.
-5
View File
@@ -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`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog': patch
---
Finalize migration to new composability API, with the plugin instance now exported `catalogPlugin`.
-6
View File
@@ -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
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core': patch
---
Fix check that determines whether popup was closed or the messaging was misconfigured.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-sonarqube': patch
---
Migrate to new composability API, exporting the plugin as `sonarQubePlugin` and card as `EntitySonarQubeCard`.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/catalog-model': patch
---
Introduce json schema variants of the `yup` validation schemas
-23
View File
@@ -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')
```
-5
View File
@@ -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.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-user-settings': patch
---
Keep the Pin Sidebar setting visible on small screens.
-20
View File
@@ -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`.
-61
View File
@@ -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;
};
```
-8
View File
@@ -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.
+1
View File
@@ -3,6 +3,7 @@ name: E2E Test Linux
on:
pull_request:
paths-ignore:
- '.changeset/**'
- 'contrib/**'
- 'docs/**'
- 'microsite/**'
-2
View File
@@ -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'
+11 -9
View File
@@ -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
```
+3 -18
View File
@@ -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
```
+1 -1
View File
@@ -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
View File
@@ -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",
+76
View File
@@ -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
View File
@@ -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
View File
@@ -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/*"
+1 -1
View File
@@ -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';
+34
View File
@@ -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
+4 -4
View File
@@ -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();
}
+26
View File
@@ -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
+9 -9
View File
@@ -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"
+2 -2
View File
@@ -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"
},
+9
View File
@@ -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
+2 -2
View File
@@ -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,
+322 -1
View File
@@ -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);
});
});
});
+75 -10
View File
@@ -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()
);
}
+43
View File
@@ -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
+4 -2
View File
@@ -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()'
+4 -2
View File
@@ -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',
+6 -6
View File
@@ -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",
+2 -2
View File
@@ -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();
+3 -3
View File
@@ -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;
+7
View File
@@ -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 -1
View File
@@ -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 }),
),
);
}
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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 [];
+30
View File
@@ -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.
![image](https://user-images.githubusercontent.com/46953622/105390193-0bfd0080-5c19-11eb-8e86-2161bbe6e8d9.png)
### 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
+3 -3
View File
@@ -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",
@@ -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'] },
);
@@ -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';
+4 -3
View File
@@ -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>
);
+27 -5
View File
@@ -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>
+74 -1
View File
@@ -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
+22 -22
View File
@@ -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
+24
View File
@@ -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