Merge branch 'master' into statuses-for-github-deployments-plugin
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
A `<CatalogResultListItem />` component is now available for use in custom Search Experiences.
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
'@backstage/core-api': patch
|
||||
---
|
||||
|
||||
Updated the `Observable` type to provide interoperability with `Symbol.observable`, making it compatible with at least `zen-observable` and `RxJS 7`.
|
||||
|
||||
In cases where this change breaks tests that mocked the `Observable` type, the following addition to the mock should fix the breakage:
|
||||
|
||||
```ts
|
||||
[Symbol.observable]() {
|
||||
return this;
|
||||
},
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-cost-insights': patch
|
||||
---
|
||||
|
||||
Move `canvas` package to `devDependencies`.
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Updated the `@gitbeaker/node` dependency past the broken one without a `dist` folder.
|
||||
|
||||
See [this issue](https://github.com/jdalrymple/gitbeaker/issues/1861) for more details.
|
||||
|
||||
If you get build errors that look like the following in your Backstage instance, you may want to also bump all of your `@gitbeaker/*` dependencies to at least `^30.2.0`.
|
||||
|
||||
```
|
||||
node:internal/modules/cjs/loader:356
|
||||
throw err;
|
||||
^
|
||||
|
||||
Error: Cannot find module '/path/to/project/node_modules/@gitbeaker/node/dist/index.js'. Please verify that the package.json has a valid "main" entry
|
||||
at tryPackage (node:internal/modules/cjs/loader:348:19)
|
||||
at Function.Module._findPath (node:internal/modules/cjs/loader:561:18)
|
||||
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:926:27)
|
||||
at Function.Module._load (node:internal/modules/cjs/loader:773:27)
|
||||
at Module.require (node:internal/modules/cjs/loader:1012:19)
|
||||
at require (node:internal/modules/cjs/helpers:93:18)
|
||||
at Object.<anonymous> (/path/to/project/test.js:4:18)
|
||||
at Module._compile (node:internal/modules/cjs/loader:1108:14)
|
||||
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
|
||||
at Module.load (node:internal/modules/cjs/loader:988:32) {
|
||||
code: 'MODULE_NOT_FOUND',
|
||||
path: '/path/to/project/node_modules/@gitbeaker/node/package.json',
|
||||
requestPath: '@gitbeaker/node'
|
||||
}
|
||||
```
|
||||
|
||||
you could also consider pinning the version to an older one in your `package.json`, before the breakage occurred.
|
||||
|
||||
```json
|
||||
"resolutions": {
|
||||
"@gitbeaker/node": "29.2.4",
|
||||
"@gitbeaker/core": "29.2.4",
|
||||
"@gitbeaker/requester-utils": "29.2.4"
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Restructure the next catalog types and files a bit
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-github-actions': patch
|
||||
---
|
||||
|
||||
Add missing token on job list call to GitHub API
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Omits the `upgrade-insecure-requests` Content-Security-Policy directive by default, to prevent automatic HTTPS request upgrading for HTTP-deployed Backstage sites.
|
||||
|
||||
If you previously disabled this using `false` in your `app-config.yaml`, this line is no longer necessary:
|
||||
|
||||
```diff
|
||||
backend:
|
||||
csp:
|
||||
- upgrade-insecure-requests: false
|
||||
```
|
||||
|
||||
To keep the existing behavior of `upgrade-insecure-requests` Content-Security-Policy being _enabled_, add the key with an empty array as the value in your `app-config.yaml`:
|
||||
|
||||
```diff
|
||||
backend:
|
||||
+ csp:
|
||||
+ upgrade-insecure-requests: []
|
||||
```
|
||||
|
||||
Read more on [upgrade-insecure-requests here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/upgrade-insecure-requests).
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-badges-backend': patch
|
||||
---
|
||||
|
||||
Fix generated badge links
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/catalog-model': patch
|
||||
---
|
||||
|
||||
Add the `status` field to the Entity envelope
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Updated dependencies
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Migrating old `backstage.io/v1alpha1` templates to `backstage.io/v1beta2`
|
||||
|
||||
Deprecating the `create-react-app` Template. We're planning on removing the `create-react-app` templater, as it's been a little tricky to support and takes 15mins to run in a container. We've currently cached a copy of the output for `create-react-app` and ship that under our sample templates folder. If you want to continue using it, we suggest copying the template out of there and putting it in your own repository as it will be removed in upcoming releases.
|
||||
|
||||
We also recommend removing this entry from your `app-config.yaml` if it exists:
|
||||
|
||||
```diff
|
||||
- - type: url
|
||||
- target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml
|
||||
- rules:
|
||||
- - allow: [Template]
|
||||
```
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/config-loader': patch
|
||||
---
|
||||
|
||||
Updated dependencies
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/catalog-client': patch
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
---
|
||||
|
||||
Display preview result final step.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
'@backstage/search-common': patch
|
||||
'@backstage/plugin-search-backend-node': patch
|
||||
'@backstage/plugin-search': patch
|
||||
---
|
||||
|
||||
The `<Search...Next /> set of components exported by the Search Plugin are now updated to use the Search Backend API. These will be made available as the default non-"next" versions in a follow-up release.
|
||||
|
||||
The interfaces for decorators and collators in the Search Backend have also seen minor, breaking revisions ahead of a general release. If you happen to be building on top of these interfaces, check and update your implementations accordingly. The APIs will be considered more stable in a follow-up release.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-git-release-manager': patch
|
||||
'@backstage/plugin-ilert': patch
|
||||
---
|
||||
|
||||
[ImgBot] Optimize images
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Skip adding entries to the `entities_search` table if their `key` exceeds a length limit.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/dev-utils': patch
|
||||
---
|
||||
|
||||
Fix a bug where an instance of the SCM integrations API wasn't being provided properly to the dev app.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
Bug fix on sidebar position when Tab-Bar is enabled
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/test-utils': patch
|
||||
---
|
||||
|
||||
Updated `MockErrorApi` to work with new `Observable` type in `@backstage/core`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-github-deployments': patch
|
||||
---
|
||||
|
||||
Support GHE by properly parsing enterprise instance hosts
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
Handle URLs with a `#hash` correctly when rewriting link URLs.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Update gitbeaker past the broken version without a dist folder
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Exported AboutCard contents and utility functions
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-proxy-backend': patch
|
||||
---
|
||||
|
||||
Fixed proxy requests to the base URL of routes without a trailing slash redirecting to the `target` with the full path appended.
|
||||
@@ -1,4 +1,32 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var path = require('path');
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['@spotify/eslint-config-oss'],
|
||||
plugins: ['notice'],
|
||||
rules: {
|
||||
'notice/notice': [
|
||||
'error',
|
||||
{
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
templateFile: path.resolve(__dirname, './scripts/copyright-header.txt'),
|
||||
onNonMatchingHeader: 'replace',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@ exemptLabels:
|
||||
- plugin
|
||||
- help wanted
|
||||
- good first issue
|
||||
- rfc
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
|
||||
@@ -1,126 +1,58 @@
|
||||
Apdex
|
||||
Api
|
||||
Autoscaling
|
||||
Avro
|
||||
Bigtable
|
||||
Billett
|
||||
Bitrise
|
||||
Blackbox
|
||||
Chai
|
||||
Changesets
|
||||
Chanwit
|
||||
Cloudformation
|
||||
Cobertura
|
||||
Codecov
|
||||
Codehilite
|
||||
Config
|
||||
Datadog
|
||||
Debounce
|
||||
Discoverability
|
||||
Dockerfile
|
||||
dockerfiles
|
||||
Dockerize
|
||||
Docusaurus
|
||||
Env
|
||||
Expedia
|
||||
Fargate
|
||||
Figma
|
||||
Firekube
|
||||
Fiverr
|
||||
GitHub
|
||||
GitLab
|
||||
Grafana
|
||||
GraphQL
|
||||
Hackathons
|
||||
Heroku
|
||||
Hostname
|
||||
Iain
|
||||
JaCoCo
|
||||
JavaScript
|
||||
Kaewkasi
|
||||
Knex
|
||||
Leasot
|
||||
Lerna
|
||||
LocalStack
|
||||
Luxon
|
||||
Minikube
|
||||
Minio
|
||||
Mkdocs
|
||||
Monorepo
|
||||
Namespaces
|
||||
OAuth
|
||||
Okta
|
||||
Onboarding
|
||||
Platformize
|
||||
Podman
|
||||
Preprarer
|
||||
Protobuf
|
||||
Proxying
|
||||
Readme
|
||||
readonly
|
||||
rebase
|
||||
Recharts
|
||||
Redash
|
||||
Repo
|
||||
Rollbar
|
||||
Rollup
|
||||
Routable
|
||||
Scaffolder
|
||||
Serverless
|
||||
Sinon
|
||||
Snyk
|
||||
Splunk
|
||||
Spotifiers
|
||||
Spotify
|
||||
Superfences
|
||||
Talkdesk
|
||||
Telenor
|
||||
Templater
|
||||
Templaters
|
||||
todo
|
||||
Tolerations
|
||||
WWW
|
||||
Weaveworks
|
||||
Webpack
|
||||
XML
|
||||
Zalando
|
||||
Zhou
|
||||
abc
|
||||
accessors
|
||||
Apdex
|
||||
api
|
||||
Api
|
||||
apis
|
||||
args
|
||||
asciidoc
|
||||
async
|
||||
automations
|
||||
autoscaling
|
||||
Autoscaling
|
||||
Avro
|
||||
backrub
|
||||
Bigtable
|
||||
Billett
|
||||
Bitrise
|
||||
Blackbox
|
||||
bool
|
||||
boolean
|
||||
builtins
|
||||
Chai
|
||||
changeset
|
||||
changesets
|
||||
Changesets
|
||||
chanwit
|
||||
Chanwit
|
||||
ci
|
||||
cisphobia
|
||||
cissexist
|
||||
classname
|
||||
cli
|
||||
cloudbuild
|
||||
Cloudformation
|
||||
cncf
|
||||
Cobertura
|
||||
codeblocks
|
||||
Codecov
|
||||
codehilite
|
||||
Codehilite
|
||||
codeowners
|
||||
composability
|
||||
composable
|
||||
config
|
||||
Config
|
||||
configmaps
|
||||
configs
|
||||
const
|
||||
cookiecutter
|
||||
css
|
||||
Datadog
|
||||
dataflow
|
||||
deadnaming
|
||||
debounce
|
||||
Debounce
|
||||
declaratively
|
||||
deps
|
||||
destructured
|
||||
@@ -128,60 +60,99 @@ dev
|
||||
devops
|
||||
devs
|
||||
discoverability
|
||||
Discoverability
|
||||
dls
|
||||
docgen
|
||||
Dockerfile
|
||||
dockerfiles
|
||||
Dockerize
|
||||
dockerode
|
||||
Docusaurus
|
||||
env
|
||||
Env
|
||||
esbuild
|
||||
eslint
|
||||
etag
|
||||
Expedia
|
||||
facto
|
||||
failover
|
||||
Fargate
|
||||
Figma
|
||||
Firekube
|
||||
Fiverr
|
||||
gitbeaker
|
||||
GitHub
|
||||
GitLab
|
||||
Grafana
|
||||
graphql
|
||||
GraphQL
|
||||
graphviz
|
||||
Hackathons
|
||||
haproxy
|
||||
Helidon
|
||||
Heroku
|
||||
hoc
|
||||
horizontalpodautoscalers
|
||||
Hostname
|
||||
hotspots
|
||||
html
|
||||
http
|
||||
https
|
||||
Iain
|
||||
img
|
||||
incentivised
|
||||
inlined
|
||||
inlinehilite
|
||||
interop
|
||||
JaCoCo
|
||||
JavaScript
|
||||
Jira
|
||||
jq
|
||||
js
|
||||
json
|
||||
jsonnet
|
||||
jsx
|
||||
Kaewkasi
|
||||
Keyv
|
||||
Knex
|
||||
kubectl
|
||||
kubernetes
|
||||
kubernetes
|
||||
learnings
|
||||
Leasot
|
||||
lerna
|
||||
Lerna
|
||||
LocalStack
|
||||
lockfile
|
||||
lunr
|
||||
Luxon
|
||||
magiclink
|
||||
mailto
|
||||
maintainership
|
||||
makefile
|
||||
md
|
||||
memcache
|
||||
microservice
|
||||
microservices
|
||||
microsite
|
||||
middleware
|
||||
minikube
|
||||
Minikube
|
||||
Minio
|
||||
misconfiguration
|
||||
misconfigured
|
||||
misgendering
|
||||
mkdocs
|
||||
Mkdocs
|
||||
monorepo
|
||||
Monorepo
|
||||
monorepos
|
||||
msw
|
||||
mysql
|
||||
namespace
|
||||
namespaced
|
||||
namespaces
|
||||
Namespaces
|
||||
namespacing
|
||||
neuro
|
||||
newrelic
|
||||
@@ -193,43 +164,68 @@ noop
|
||||
npm
|
||||
nvarchar
|
||||
nvm
|
||||
OAuth
|
||||
octokit
|
||||
oidc
|
||||
Okta
|
||||
onboarding
|
||||
Onboarding
|
||||
pagerduty
|
||||
pageview
|
||||
parallelization
|
||||
plantuml
|
||||
Platformize
|
||||
Podman
|
||||
postgres
|
||||
postpack
|
||||
pre
|
||||
prebaked
|
||||
preconfigured
|
||||
prepack
|
||||
Preprarer
|
||||
productional
|
||||
Protobuf
|
||||
proxying
|
||||
Proxying
|
||||
pygments
|
||||
pymdownx
|
||||
rankdir
|
||||
readme
|
||||
Readme
|
||||
readonly
|
||||
rebase
|
||||
Recharts
|
||||
Redash
|
||||
replicasets
|
||||
repo
|
||||
Repo
|
||||
repos
|
||||
rerender
|
||||
rollbar
|
||||
Rollbar
|
||||
Rollup
|
||||
routable
|
||||
Routable
|
||||
rst
|
||||
rsync
|
||||
ruleset
|
||||
sam
|
||||
sanitization
|
||||
scaffolded
|
||||
scaffolder
|
||||
Scaffolder
|
||||
seb
|
||||
semlas
|
||||
semver
|
||||
Serverless
|
||||
Sinon
|
||||
Snyk
|
||||
sourcemaps
|
||||
sparklines
|
||||
Splunk
|
||||
Spotifiers
|
||||
spotify
|
||||
Spotify
|
||||
sqlite
|
||||
squidfunk
|
||||
src
|
||||
@@ -240,17 +236,25 @@ subkey
|
||||
subroutes
|
||||
subtree
|
||||
superfences
|
||||
Superfences
|
||||
superset
|
||||
supertype
|
||||
talkdesk
|
||||
Talkdesk
|
||||
tasklist
|
||||
techdocs
|
||||
Telenor
|
||||
templated
|
||||
templater
|
||||
Templater
|
||||
templaters
|
||||
Templaters
|
||||
theia
|
||||
thumbsup
|
||||
toc
|
||||
todo
|
||||
tolerations
|
||||
Tolerations
|
||||
toolchain
|
||||
toolsets
|
||||
tooltip
|
||||
@@ -266,11 +270,18 @@ untracked
|
||||
upvote
|
||||
url
|
||||
utils
|
||||
validator
|
||||
validators
|
||||
varchar
|
||||
Weaveworks
|
||||
Webpack
|
||||
winston
|
||||
www
|
||||
WWW
|
||||
XML
|
||||
xyz
|
||||
yaml
|
||||
Zalando
|
||||
Zhou
|
||||
zoomable
|
||||
zsh
|
||||
|
||||
@@ -20,3 +20,4 @@ jobs:
|
||||
version: yarn release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
|
||||
HUSKY: '0'
|
||||
|
||||
@@ -76,6 +76,9 @@ jobs:
|
||||
- name: prettier
|
||||
run: yarn prettier:check
|
||||
|
||||
- name: lock
|
||||
run: yarn lock:check
|
||||
|
||||
- name: validate config
|
||||
run: yarn backstage-cli config:check --lax
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ jobs:
|
||||
|
||||
- name: test
|
||||
run: yarn lerna -- run test
|
||||
env:
|
||||
BACKSTAGE_TEST_DISABLE_DOCKER: 1
|
||||
|
||||
# credit: https://github.com/appleboy/discord-action/issues/3#issuecomment-731426861
|
||||
- name: Discord notification
|
||||
|
||||
@@ -16,6 +16,41 @@ jobs:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x]
|
||||
|
||||
services:
|
||||
postgres13:
|
||||
image: postgres:13
|
||||
env:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432/tcp
|
||||
postgres9:
|
||||
image: postgres:9
|
||||
env:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432/tcp
|
||||
mysql8:
|
||||
image: mysql:8
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping -h localhost"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 3306/tcp
|
||||
|
||||
env:
|
||||
CI: true
|
||||
NODE_OPTIONS: --max-old-space-size=4096
|
||||
@@ -86,6 +121,10 @@ jobs:
|
||||
# Upload code coverage for some specific flags. Also see .codecov.yml
|
||||
bash <(curl -s https://codecov.io/bash) -f packages/core/coverage/* -F core
|
||||
bash <(curl -s https://codecov.io/bash) -f packages/core-api/coverage/* -F core-api
|
||||
env:
|
||||
BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres13.ports[5432] }}
|
||||
BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres9.ports[5432] }}
|
||||
BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING: mysql://root:root@localhost:${{ job.services.mysql8.ports[3306] }}/ignored
|
||||
|
||||
- name: Discord notification
|
||||
if: ${{ failure() }}
|
||||
|
||||
@@ -40,6 +40,10 @@ jobs:
|
||||
run: yarn prettier:check
|
||||
working-directory: microsite
|
||||
|
||||
- name: lock
|
||||
run: yarn lock:check
|
||||
working-directory: microsite
|
||||
|
||||
- name: build microsite
|
||||
run: yarn build
|
||||
working-directory: microsite
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
| Organization | Contact | Description of Use |
|
||||
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. |
|
||||
| [bol.com](https://www.bol.com) | [@RoyJacobs](https://github.com/RoyJacobs) | Initial work being done to unify platform tooling. |
|
||||
| [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. |
|
||||
| [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up |
|
||||
| [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. |
|
||||
| [SDA SE](https://sda.se) | [@Fox32](https://github.com/Fox32) | Central place for developing and sharing services in our insurance ecosystem. |
|
||||
| [H-E-B](https://www.heb.com) | [@german-j-rodriguez](https://github.com/german-j-rodriguez) | Initial work on Engineering Portal service platform. |
|
||||
| [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications |
|
||||
| [Kiwi.com](https://kiwi.com) | [@aexvir](https://github.com/aexvir) | Replacing the frontend of [The Zoo](https://github.com/kiwicom/the-zoo), their service registry. |
|
||||
| [Voi](https://www.voiscooters.com/) | [@K-Phoen](https://github.com/K-Phoen) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. |
|
||||
| [Talkdesk](https://www.talkdesk.com) | [@jaime-talkdesk](https://github.com/jaime-talkdesk) | Initial work for Engineering Portal and Self Provisioning to R&D |
|
||||
| [Wealthsimple](https://www.wealthsimple.com) | [@andrewthauer](https://github.com/andrewthauer) | Developer portal, service catalog, documentation and tooling |
|
||||
| [Grab](https://www.grab.com) | [@althafh](https://github.com/althafh) | Initial work as a unified interface for all of Grab's internal tooling |
|
||||
| [Telenor Sweden](https://www.telenor.se) | [@O5ten](https://github.com/O5ten) | Building a developer portal for scaffolding projects towards our unified build environment and microservice stacks |
|
||||
| [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. |
|
||||
| [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. |
|
||||
| [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. |
|
||||
| [Expedia Group](https://www.expediagroup.com) | [Mike Turner](mailto:miturner@expediagroup.com), [Sneha Kumar](mailto:snkumar@expediagroup.com), [@guillermomanzo](https://github.com/guillermomanzo), [Erik Lindgren](https://github.com/lindgren) | EG Common Developer Toolkit |
|
||||
| [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go |
|
||||
| [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling |
|
||||
| [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. |
|
||||
| [Trendyol](https://trendyol.com) | [Erdogan Oksuz](https://github.com/erdoganoksuz) | The Developer Portal has been called `Pandora`. Provides an overview of Trendyol tech ecosystem. TechDocs, Catalog, Custom Plugins and Theme. |
|
||||
| [Peloton](https://www.onepeloton.com/) | [Jim Haughwout](https://github.com/JimHaughwout) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. |
|
||||
| [TELUS](https://telus.com) | [Seb Barre](https://github.com/sbarre) | The Go-to place to find answers about development and delivery at TELUS. |
|
||||
| [Brex](https://www.brex.com/) | [Vamsi Chitters](https://github.com/vamsikc) | A centralized UI to understand how a service fits in the whole Brex architecture and manage a team’s engineering dependencies. |
|
||||
| [Oriflame](https://www.oriflame.com/) | [Oriflame](https://github.com/oriflame) | Internal developer portal for services, single page apps and packages overview, API documentation, technical guides, tech-radar and more. |
|
||||
| Organization | Contact | Description of Use |
|
||||
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. |
|
||||
| [bol.com](https://www.bol.com) | [@RoyJacobs](https://github.com/RoyJacobs) | Initial work being done to unify platform tooling. |
|
||||
| [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. |
|
||||
| [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up |
|
||||
| [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. |
|
||||
| [SDA SE](https://sda.se) | [@Fox32](https://github.com/Fox32) | Central place for developing and sharing services in our insurance ecosystem. |
|
||||
| [H-E-B](https://www.heb.com) | [@german-j-rodriguez](https://github.com/german-j-rodriguez) | Initial work on Engineering Portal service platform. |
|
||||
| [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications |
|
||||
| [Kiwi.com](https://kiwi.com) | [@aexvir](https://github.com/aexvir) | Replacing the frontend of [The Zoo](https://github.com/kiwicom/the-zoo), their service registry. |
|
||||
| [Voi](https://www.voiscooters.com/) | [@K-Phoen](https://github.com/K-Phoen) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. |
|
||||
| [Talkdesk](https://www.talkdesk.com) | [@jaime-talkdesk](https://github.com/jaime-talkdesk) | Initial work for Engineering Portal and Self Provisioning to R&D |
|
||||
| [Wealthsimple](https://www.wealthsimple.com) | [@andrewthauer](https://github.com/andrewthauer) | Developer portal, service catalog, documentation and tooling |
|
||||
| [Grab](https://www.grab.com) | [@althafh](https://github.com/althafh) | Initial work as a unified interface for all of Grab's internal tooling |
|
||||
| [Telenor Sweden](https://www.telenor.se) | [@O5ten](https://github.com/O5ten) | Building a developer portal for scaffolding projects towards our unified build environment and microservice stacks |
|
||||
| [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. |
|
||||
| [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. |
|
||||
| [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. |
|
||||
| [Expedia Group](https://www.expediagroup.com) | [Mike Turner](mailto:miturner@expediagroup.com), [Sneha Kumar](mailto:snkumar@expediagroup.com), [@guillermomanzo](https://github.com/guillermomanzo), [Erik Lindgren](https://github.com/lindgren) | EG Common Developer Toolkit |
|
||||
| [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go |
|
||||
| [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling |
|
||||
| [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. |
|
||||
| [Trendyol](https://trendyol.com) | [Erdogan Oksuz](https://github.com/erdoganoksuz) | The Developer Portal has been called `Pandora`. Provides an overview of Trendyol tech ecosystem. TechDocs, Catalog, Custom Plugins and Theme. |
|
||||
| [Peloton](https://www.onepeloton.com/) | [Jim Haughwout](https://github.com/JimHaughwout) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. |
|
||||
| [TELUS](https://telus.com) | [Seb Barre](https://github.com/sbarre) | The Go-to place to find answers about development and delivery at TELUS. |
|
||||
| [Brex](https://www.brex.com/) | [Vamsi Chitters](https://github.com/vamsikc) | A centralized UI to understand how a service fits in the whole Brex architecture and manage a team’s engineering dependencies. |
|
||||
| [Oriflame](https://www.oriflame.com/) | [Oriflame](https://github.com/oriflame) | Internal developer portal for services, single page apps and packages overview, API documentation, technical guides, tech-radar and more. |
|
||||
| [Booz Allen Hamilton](https://www.boozallen.com/) | [Jason Miller](https://github.com/JasonMiller-BAH) | Developer portal for a full-stack software development ecosystem that accelerates consistent and repeatable Modern Software Development practices for internal innovation and investments. |
|
||||
| [Netflix](https://www.netflix.com/) | [bleathem](https://github.com/bleathem) | Our Backstage implementation will be the front door to a unified experience connecting our internal platform products across important workflows with integrated knowledge and support. |
|
||||
| [b.well](https://www.icanbwell.com/) | [Jacob Rosales](https://github.com/jrosales) | Foundation for our engineering portal and cloud insights. |
|
||||
| [PagerDuty](https://www.pagerduty.com/) | [Mark Shaw](https://github.com/markshawtoronto) | Developer portal, initially focused on software templates and tech-docs. |
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
# Backstage Changelog
|
||||
|
||||
This changelog is no longer being updated and will be removed in the future, as each package now has its own changelog instead. It was a best-effort changelog where we manually collected breaking changes during the `v0.1.1-alpha.<n>` releases.
|
||||
|
||||
If you encounter issues while upgrading to a newer version, don't hesitate to reach out on [Discord](https://discord.gg/EBHEGzX) or [open an issue](https://github.com/backstage/backstage/issues/new/choose)!
|
||||
|
||||
## v0.1.1-alpha.26
|
||||
|
||||
### @backstage/cli
|
||||
|
||||
- Configuration files are no longer selected through `APP_ENV` or `NODE_ENV`. The default configuration files are `app-config.yaml` and, fix it exists, `app-config.local.yaml` in the repo root. To load a different set of files, use `--config <path>` arguments.
|
||||
|
||||
### @backstage/backend-common
|
||||
|
||||
- Configuration files are no longer selected through `APP_ENV` or `NODE_ENV`. The default configuration files are `app-config.yaml` and, fix it exists, `app-config.local.yaml` in the repo root. To load a different set of files, use `--config <path>` arguments.
|
||||
|
||||
## v0.1.1-alpha.25
|
||||
|
||||
### @backstage/cli
|
||||
|
||||
- The recommended way to set the configuration environment is now to use `APP_ENV` instead of `NODE_ENV`.
|
||||
|
||||
### Backend (example-backend, or backends created with @backstage/create-app)
|
||||
|
||||
- A plugin database manager has been created, and plugins can now accept that interface as an argument during initialisation. Notably, the `auth` plugin has a [`createRouter` signature change](./plugins/auth-backend/src/service/router.ts). See [packages/backend/src/index.ts](./packages/backend/src/index.ts) on how to set it up. [#2697](https://github.com/backstage/backstage/pull/2697)
|
||||
|
||||
## v0.1.1-alpha.24
|
||||
|
||||
### Backend (example-backend, or backends created with @backstage/create-app)
|
||||
|
||||
- The default mount point for backend plugins have been changed to `/api`. These changes are done in the backend package itself, so it is recommended that you sync up existing backend packages with this new pattern. [#2562](https://github.com/backstage/backstage/pull/2562)
|
||||
- A service discovery mechanism for backend plugins has been added, and is now a requirement for several backend plugins. See [packages/backend/src/index.ts](./packages/backend/src/index.ts) for how to set it up using `SingleHostDiscovery` from `@backstage/backend-common`. Note that the default base path for plugins is set to `/api` to that change, but it can be set to use the old behavior via the `basePath` option. [#2600](https://github.com/backstage/backstage/pull/2600)
|
||||
|
||||
### @backstage/auth-backend
|
||||
|
||||
- The default mount path of backend plugins was changed to `/api/:pluginId`, and as part of that it was needed to enable configuration of the base path of the auth backend, so that it can construct redirect URLs correctly. Note that you will also need to reconfigure any allowed redirect URLs to include `/api` if you switch to the new recommended pattern. [#2562](https://github.com/backstage/backstage/pull/2562)
|
||||
- The auth backend now requires an implementation of `PluginEndpointDiscovery` from `@backstage/backend-common` to be passed in as `discovery`. See the changes to `@backstage/backend`.
|
||||
|
||||
### @backstage/proxy-backend
|
||||
|
||||
- The proxy backend now requires an implementation of `PluginEndpointDiscovery` from `@backstage/backend-common` to be passed in as `discovery`. See the changes to `@backstage/backend`.
|
||||
|
||||
### @backstage/techdocs-backend
|
||||
|
||||
- The TechDocs backend now requires an implementation of `PluginEndpointDiscovery` from `@backstage/backend-common` to be passed in as `discovery`. See the changes to `@backstage/backend`.
|
||||
|
||||
### @backstage/plugin-identity-backend
|
||||
|
||||
- This plugin was removed, remove it from your backend if it's there. [#2616](https://github.com/backstage/backstage/pull/2616)
|
||||
|
||||
## v0.1.1-alpha.23
|
||||
|
||||
### @backstage/core
|
||||
|
||||
- Renamed `SessionStateApi` to `SessionApi` and `logout` to `signOut`. Custom implementations of the `SingInPage` app-component will need to rename their `logout` function. The different auth provider items for the `UserSettingsMenu` have been consolidated into a single `ProviderSettingsItem`, meaning you need to replace existing usages of `OAuthProviderSettings` and `OIDCProviderSettings`. [#2555](https://github.com/backstage/backstage/pull/2555).
|
||||
|
||||
## v0.1.1-alpha.22
|
||||
|
||||
### @backstage/core
|
||||
|
||||
- Introduced initial version of an inverted app/plugin relationship, where plugins export components for apps to use, instead registering themselves directly into the app. This enables more fine-grained control of plugin features, and also composition of plugins such as catalog pages with additional cards and tabs. This breaks the use of `RouteRef`s, and there will be more changes related to this in the future, but this change lays the initial foundation. See `packages/app` and followup PRs for how to update plugins for this change. [#2076](https://github.com/backstage/backstage/pull/2076)
|
||||
- Switch to an automatic dependency injection mechanism for all Utility APIs, allowing plugins to ship default implementations of their APIs. See [https://backstage.io/docs/api/utility-apis](https://backstage.io/docs/api/utility-apis). [#2285](https://github.com/backstage/backstage/pull/2285)
|
||||
|
||||
### @backstage/cli
|
||||
|
||||
- Change `backstage-cli backend:build-image` to forward all args to `docker image build`, instead of just tag. Also add `--build` flag for building all dependent packages before packaging the workspace for the docker build. [#2299](https://github.com/backstage/backstage/pull/2299)
|
||||
|
||||
### @backstage/create-app
|
||||
|
||||
- Change root `tsc` output dir to `dist-types`, in order to allow for standalone plugin repos. [#2278](https://github.com/backstage/backstage/pull/2278)
|
||||
|
||||
### @backstage/catalog-backend
|
||||
|
||||
- We have simplified the way that GitHub ingestion works. The `catalog.processors.githubApi` key is deprecated, in favor of `catalog.processors.github`. At the same time, the location type `github/api` is likewise deprecated, in favor of `github`. This location type now serves both raw HTTP reads and APIv3 reads, depending on how you configure it. It also supports having several providers at once - for example, both public GitHub and an internal GitHub Enterprise, with different keys. If you still use the `catalog.processors.githubApi` config key, things will work but you will get a deprecation warning at startup. In a later release, support for the old key will go away entirely. See the [configuration section in the docs](https://backstage.io/docs/features/software-catalog/configuration) for more details.
|
||||
|
||||
## v0.1.1-alpha.21
|
||||
|
||||
- Added many more frontend plugins to the template along with the sidebar. [#1942](https://github.com/backstage/backstage/pull/1942), [#2084](https://github.com/backstage/backstage/pull/2084)
|
||||
|
||||
### @backstage/core
|
||||
|
||||
- Material-UI: Bumped to 4.11.0, which is the version that create-app will
|
||||
resolve to, because we wanted to get the renaming of ExpansionPanel to
|
||||
Accordion into place. This gets rid of a lot of console deprecation warnings
|
||||
in newly scaffolded apps.
|
||||
|
||||
### @backstage/cli
|
||||
|
||||
- Set `NODE_ENV` to `test` when running test. [#2214](https://github.com/backstage/backstage/pull/2214)
|
||||
|
||||
- Fix for backend plugins names requiring to be prefixed with `@backstage` to build. [#2224](https://github.com/backstage/backstage/pull/2224)
|
||||
|
||||
### @backstage/backend-common
|
||||
|
||||
- The backend plugin
|
||||
[service builder](https://github.com/backstage/backstage/blob/master/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts)
|
||||
no longer adds `express.json()` automatically to all routes. While convenient
|
||||
in a lot of cases, it also led to problems where for example the proxy
|
||||
middleware could hang because the body had already been altered and could not
|
||||
be streamed. Also, plugins that rather wanted to handle e.g. form encoded data
|
||||
still had to cater to that manually. We therefore decided to let plugins add
|
||||
`express.json()` themselves if they happen to deal with JSON data.
|
||||
|
||||
### @backstage/catalog-backend
|
||||
|
||||
- Add rules configuration for catalog location and entity kinds. The default rules should cover most use-cases, but you may need to allow specific entity kinds when using things like Template or Group entities. [#2118](https://github.com/backstage/backstage/pull/2118)
|
||||
|
||||
## v0.1.1-alpha.20
|
||||
|
||||
### @backstage/cli
|
||||
|
||||
- Use config files according to `NODE_ENV` when serving and building frontend packages. [#2077](https://github.com/backstage/backstage/pull/2077)
|
||||
|
||||
- Pin `rollup-plugin-dts` to avoid a later broken version. [#2097](https://github.com/backstage/backstage/pull/2097)
|
||||
|
||||
## v0.1.1-alpha.19
|
||||
|
||||
### @backstage/backend-common
|
||||
|
||||
- Allow listen host and port to be configured separately, in order to support PORT environment variables. [#1950](https://github.com/backstage/backstage/pull/1950)
|
||||
|
||||
### @backstage/core
|
||||
|
||||
- Added new `DiscoveryApi` for discovering backend endpoint in the frontend, and use in most plugins. See [packages/app/src/apis.ts](https://github.com/backstage/backstage/blob/master/packages/app/src/apis.ts) for how to register in your app. [#2074](https://github.com/backstage/backstage/pull/2074)
|
||||
|
||||
### @backstage/create-app
|
||||
|
||||
- Added catalog and scaffolder frontend plugins to the template along with the sidebar. [#1942](https://github.com/backstage/backstage/pull/1942), [#2084](https://github.com/backstage/backstage/pull/2084)
|
||||
- Many plugins have been added to the catalog and will for now be required to be added to separate apps as well. This will be solved as [#1536](https://github.com/backstage/backstage/issues/1536) gets sorted out, but for now you may need to install some plugins just to get pages to work.
|
||||
|
||||
### @backstage/catalog-backend
|
||||
|
||||
- Added the possibility to add static locations via `app-config.yaml`. This changed the signature of `new LocationReaders(logger)` inside `packages/backend/src/plugins/catalog.ts` to `new LocationReaders({config, logger})`. [#1890](https://github.com/backstage/backstage/pull/1890)
|
||||
|
||||
### @backstage/theme
|
||||
|
||||
- Changed the type signature of the palette, removing `sidebar: string` and adding `navigation: { background: string; indicator: string}`. [#1880](https://github.com/backstage/backstage/pull/1880)
|
||||
|
||||
## v0.1.1-alpha.18
|
||||
|
||||
### @backstage/catalog-backend
|
||||
|
||||
- Fixed an issue with duplicated location logs. Applying the database migrations from this fix will clear the existing migration logs. [#1836](https://github.com/backstage/backstage/pull/1836)
|
||||
|
||||
### @backstage/auth-backend
|
||||
|
||||
This version fixes a breakage in CSP policies set by the auth backend. If you're facing trouble with auth in alpha.17, upgrade to alpha.18.
|
||||
|
||||
- OAuth redirect URLs no longer receive the `env` parameter, as it is now passed through state instead. This will likely require a reconfiguration of the OAuth app, where a redirect URL like `http://localhost:7000/auth/google/handler/frame?env=development` should now be configured as `http://localhost:7000/auth/google/handler/frame`. [#1812](https://github.com/backstage/backstage/pull/1812)
|
||||
|
||||
### @backstage/core
|
||||
|
||||
- `SignInPage` props have been changed to receive a list of provider objects instead of simple string identifiers for all but the `'guest'` and `'custom'` providers. This opens up for configuration of custom providers, but may break existing configurations. See [packages/app/src/App.tsx](https://github.com/backstage/backstage/blob/032ba401af36a760efdac41668d7000ccf09bc57/packages/app/src/App.tsx#L36) and [packages/app/src/identityProviders.ts](https://github.com/backstage/backstage/blob/032ba401af36a760efdac41668d7000ccf09bc57/packages/app/src/identityProviders.ts#L24) for how to bring back the existing providers. [#1816](https://github.com/backstage/backstage/pull/1816)
|
||||
|
||||
## v0.1.1-alpha.17
|
||||
|
||||
### @backstage/techdocs-backend
|
||||
|
||||
- The techdocs backend now requires more configuration to be supplied when creating the router. See [packages/backend/src/plugins/techdocs.ts](https://github.com/backstage/backstage/blob/0201fd9b4a52429519dd59e9184106ba69456deb/packages/backend/src/plugins/techdocs.ts#L42) for an example. [#1736](https://github.com/backstage/backstage/pull/1736)
|
||||
|
||||
### @backstage/cli
|
||||
|
||||
- The `create-app` command was moved out from the CLI to a standalone package. It's now invoked with `npx @backstage/create-app` instead. [#1745](https://github.com/backstage/backstage/pull/1745)
|
||||
@@ -29,12 +29,16 @@ backend:
|
||||
database:
|
||||
client: sqlite3
|
||||
connection: ':memory:'
|
||||
cache:
|
||||
store: memory
|
||||
cors:
|
||||
origin: http://localhost:3000
|
||||
methods: [GET, POST, PUT, DELETE]
|
||||
credentials: true
|
||||
csp:
|
||||
connect-src: ["'self'", 'http:', 'https:']
|
||||
# Content-Security-Policy directives follow the Helmet format: https://helmetjs.github.io/#reference
|
||||
# Default Helmet Content-Security-Policy values can be removed by setting the key to false
|
||||
reading:
|
||||
allow:
|
||||
- host: example.com
|
||||
|
||||
@@ -167,4 +167,4 @@ Once it's deployed, after going through the AAD authentication flow, Backstage s
|
||||
|
||||
<!-- links -->
|
||||
|
||||
[monorepo-app-setup-with-auth-ms]: https://backstage.io/docs/tutorials/quickstart-app-auth#the-auth-configuration
|
||||
[monorepo-app-setup-with-auth-ms]: https://backstage.io/docs/auth/microsoft/provider
|
||||
|
||||
@@ -80,6 +80,4 @@ backend:
|
||||
origin: https://your-public-url.com:3000
|
||||
```
|
||||
|
||||
If the protocol is `http`, you will need to set `backend.csp.upgrade-insecure-requests` to `false` as well.
|
||||
|
||||
The app port must proxy web socket connections in order to make hot reloading work.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"cypress": "^6.4.0",
|
||||
"cypress": "^7.3.0",
|
||||
"typescript": "^4.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,12 @@
|
||||
dependencies:
|
||||
any-observable "^0.3.0"
|
||||
|
||||
"@types/sinonjs__fake-timers@^6.0.1":
|
||||
"@types/node@^14.14.31":
|
||||
version "14.17.0"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-14.17.0.tgz#3ba770047723b3eeb8dc9fca02cce8a7fb6378da"
|
||||
integrity sha512-w8VZUN/f7SSbvVReb9SWp6cJFevxb4/nkG65yLAya//98WgocKm5PLDAtSs5CtJJJM+kHmJjO/6mmYW4MHShZA==
|
||||
|
||||
"@types/sinonjs__fake-timers@^6.0.2":
|
||||
version "6.0.2"
|
||||
resolved "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz#3a84cf5ec3249439015e14049bd3161419bf9eae"
|
||||
integrity sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==
|
||||
@@ -117,7 +122,7 @@ any-observable@^0.3.0:
|
||||
resolved "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b"
|
||||
integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==
|
||||
|
||||
arch@^2.1.2:
|
||||
arch@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
|
||||
integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==
|
||||
@@ -171,7 +176,7 @@ bcrypt-pbkdf@^1.0.0:
|
||||
dependencies:
|
||||
tweetnacl "^0.14.3"
|
||||
|
||||
blob-util@2.0.2:
|
||||
blob-util@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb"
|
||||
integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==
|
||||
@@ -242,10 +247,10 @@ check-more-types@^2.24.0:
|
||||
resolved "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600"
|
||||
integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=
|
||||
|
||||
ci-info@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
|
||||
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
|
||||
ci-info@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.1.1.tgz#9a32fcefdf7bcdb6f0a7e1c0f8098ec57897b80a"
|
||||
integrity sha512-kdRWLBIJwdsYJWYJFtAFFYxybguqeF91qpZaggjG5Nf8QKdizFG2hjqvaTXbxFIcYbSaD74KpAXv6BSm17DHEQ==
|
||||
|
||||
cli-cursor@^1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -359,18 +364,19 @@ cross-spawn@^7.0.0:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
cypress@^6.4.0:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.npmjs.org/cypress/-/cypress-6.4.0.tgz#432c516bf4f1a0f042a6aa1f2c3a4278fa35a8b2"
|
||||
integrity sha512-SrsPsZ4IBterudkoFYBvkQmXOVxclh1/+ytbzpV8AH/D2FA+s2Qy5ISsaRzOFsbQa4KZWoi3AKwREmF1HucYkg==
|
||||
cypress@^7.3.0:
|
||||
version "7.3.0"
|
||||
resolved "https://registry.npmjs.org/cypress/-/cypress-7.3.0.tgz#17345b8d18681c120f033e7d8fd0f0271e9d0d51"
|
||||
integrity sha512-aseRCH1tRVCrM6oEfja6fR/bo5l6e4SkHRRSATh27UeN4f/ANC8U7tGIulmrISJVy9xuOkOdbYKbUb2MNM+nrw==
|
||||
dependencies:
|
||||
"@cypress/listr-verbose-renderer" "^0.4.1"
|
||||
"@cypress/request" "^2.88.5"
|
||||
"@cypress/xvfb" "^1.2.4"
|
||||
"@types/sinonjs__fake-timers" "^6.0.1"
|
||||
"@types/node" "^14.14.31"
|
||||
"@types/sinonjs__fake-timers" "^6.0.2"
|
||||
"@types/sizzle" "^2.3.2"
|
||||
arch "^2.1.2"
|
||||
blob-util "2.0.2"
|
||||
arch "^2.2.0"
|
||||
blob-util "^2.0.2"
|
||||
bluebird "^3.7.2"
|
||||
cachedir "^2.3.0"
|
||||
chalk "^4.1.0"
|
||||
@@ -378,27 +384,26 @@ cypress@^6.4.0:
|
||||
cli-table3 "~0.6.0"
|
||||
commander "^5.1.0"
|
||||
common-tags "^1.8.0"
|
||||
dayjs "^1.9.3"
|
||||
debug "^4.1.1"
|
||||
eventemitter2 "^6.4.2"
|
||||
execa "^4.0.2"
|
||||
dayjs "^1.10.4"
|
||||
debug "4.3.2"
|
||||
eventemitter2 "^6.4.3"
|
||||
execa "4.1.0"
|
||||
executable "^4.1.1"
|
||||
extract-zip "^1.7.0"
|
||||
fs-extra "^9.0.1"
|
||||
fs-extra "^9.1.0"
|
||||
getos "^3.2.1"
|
||||
is-ci "^2.0.0"
|
||||
is-installed-globally "^0.3.2"
|
||||
is-ci "^3.0.0"
|
||||
is-installed-globally "~0.4.0"
|
||||
lazy-ass "^1.6.0"
|
||||
listr "^0.14.3"
|
||||
lodash "^4.17.19"
|
||||
lodash "^4.17.21"
|
||||
log-symbols "^4.0.0"
|
||||
minimist "^1.2.5"
|
||||
moment "^2.29.1"
|
||||
ospath "^1.2.2"
|
||||
pretty-bytes "^5.4.1"
|
||||
ramda "~0.26.1"
|
||||
pretty-bytes "^5.6.0"
|
||||
ramda "~0.27.1"
|
||||
request-progress "^3.0.0"
|
||||
supports-color "^7.2.0"
|
||||
supports-color "^8.1.1"
|
||||
tmp "~0.2.1"
|
||||
untildify "^4.0.0"
|
||||
url "^0.11.0"
|
||||
@@ -416,11 +421,18 @@ date-fns@^1.27.2:
|
||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
|
||||
integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
|
||||
|
||||
dayjs@^1.9.3:
|
||||
dayjs@^1.10.4:
|
||||
version "1.10.4"
|
||||
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2"
|
||||
integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw==
|
||||
|
||||
debug@4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
||||
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
@@ -435,13 +447,6 @@ debug@^3.1.0:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.1.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
|
||||
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
@@ -477,12 +482,12 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
|
||||
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
eventemitter2@^6.4.2:
|
||||
version "6.4.3"
|
||||
resolved "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.3.tgz#35c563619b13f3681e7eb05cbdaf50f56ba58820"
|
||||
integrity sha512-t0A2msp6BzOf+QAcI6z9XMktLj52OjGQg+8SJH6v5+3uxNpWYRR3wQmfA+6xtMU9kOC59qk9licus5dYcrYkMQ==
|
||||
eventemitter2@^6.4.3:
|
||||
version "6.4.4"
|
||||
resolved "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.4.tgz#aa96e8275c4dbeb017a5d0e03780c65612a1202b"
|
||||
integrity sha512-HLU3NDY6wARrLCEwyGKRBvuWYyvW6mHYv72SJJAH3iJN3a6eVUvkjFkcxah1bcTgGVBBrFdIopBJPhCQFMLyXw==
|
||||
|
||||
execa@^4.0.2:
|
||||
execa@4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
|
||||
integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
|
||||
@@ -580,7 +585,7 @@ form-data@~2.3.2:
|
||||
combined-stream "^1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fs-extra@^9.0.1:
|
||||
fs-extra@^9.1.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
|
||||
integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
|
||||
@@ -628,12 +633,12 @@ glob@^7.1.3:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
global-dirs@^2.0.1:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d"
|
||||
integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==
|
||||
global-dirs@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686"
|
||||
integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==
|
||||
dependencies:
|
||||
ini "1.3.7"
|
||||
ini "2.0.0"
|
||||
|
||||
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
version "4.2.5"
|
||||
@@ -702,17 +707,17 @@ inherits@2, inherits@^2.0.3, inherits@~2.0.3:
|
||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
ini@1.3.7:
|
||||
version "1.3.7"
|
||||
resolved "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
|
||||
integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==
|
||||
|
||||
is-ci@^2.0.0:
|
||||
ini@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
|
||||
integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
|
||||
resolved "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
|
||||
integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
|
||||
|
||||
is-ci@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz#c7e7be3c9d8eef7d0fa144390bd1e4b88dc4c994"
|
||||
integrity sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ==
|
||||
dependencies:
|
||||
ci-info "^2.0.0"
|
||||
ci-info "^3.1.1"
|
||||
|
||||
is-fullwidth-code-point@^1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -731,13 +736,13 @@ is-fullwidth-code-point@^3.0.0:
|
||||
resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
is-installed-globally@^0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141"
|
||||
integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==
|
||||
is-installed-globally@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520"
|
||||
integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==
|
||||
dependencies:
|
||||
global-dirs "^2.0.1"
|
||||
is-path-inside "^3.0.1"
|
||||
global-dirs "^3.0.0"
|
||||
is-path-inside "^3.0.2"
|
||||
|
||||
is-observable@^1.1.0:
|
||||
version "1.1.0"
|
||||
@@ -746,10 +751,10 @@ is-observable@^1.1.0:
|
||||
dependencies:
|
||||
symbol-observable "^1.1.0"
|
||||
|
||||
is-path-inside@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017"
|
||||
integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==
|
||||
is-path-inside@^3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
||||
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
||||
|
||||
is-promise@^2.1.0:
|
||||
version "2.2.2"
|
||||
@@ -879,10 +884,10 @@ lodash.once@^4.1.1:
|
||||
resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
|
||||
|
||||
lodash@^4.17.19:
|
||||
version "4.17.20"
|
||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||
lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
log-symbols@^1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -953,11 +958,6 @@ mkdirp@^0.5.4:
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
moment@^2.29.1:
|
||||
version "2.29.1"
|
||||
resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
@@ -1056,10 +1056,10 @@ pify@^2.2.0:
|
||||
resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
|
||||
|
||||
pretty-bytes@^5.4.1:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.5.0.tgz#0cecda50a74a941589498011cf23275aa82b339e"
|
||||
integrity sha512-p+T744ZyjjiaFlMUZZv6YPC5JrkNj8maRmPaQCWFJFplUAzpIUTRaTcS+7wmZtUoFXHtESJb23ISliaWyz3SHA==
|
||||
pretty-bytes@^5.6.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
|
||||
integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
@@ -1099,10 +1099,10 @@ querystring@0.2.0:
|
||||
resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
||||
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
|
||||
|
||||
ramda@~0.26.1:
|
||||
version "0.26.1"
|
||||
resolved "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06"
|
||||
integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==
|
||||
ramda@~0.27.1:
|
||||
version "0.27.1"
|
||||
resolved "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9"
|
||||
integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==
|
||||
|
||||
readable-stream@^2.2.2:
|
||||
version "2.3.7"
|
||||
@@ -1277,13 +1277,20 @@ supports-color@^5.3.0:
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
supports-color@^7.1.0, supports-color@^7.2.0:
|
||||
supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
supports-color@^8.1.1:
|
||||
version "8.1.1"
|
||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
|
||||
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
symbol-observable@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
|
||||
|
||||
@@ -125,8 +125,8 @@ entity, and for machines and other components to reference the entity (e.g. in
|
||||
URLs or from other entity specification files).
|
||||
|
||||
Names must be unique per kind, within a given namespace (if specified), at any
|
||||
point in time. Names may be reused at a later time, after an entity is deleted
|
||||
from the registry.
|
||||
point in time. This uniqueness constraint is also case insensitive. Names may be
|
||||
reused at a later time, after an entity is deleted from the registry.
|
||||
|
||||
Names are required to follow a certain format. Entities that do not follow those
|
||||
rules will not be accepted for registration in the catalog. The ruleset is
|
||||
@@ -139,18 +139,6 @@ follows.
|
||||
|
||||
Example: `visits-tracking-service`, `CircleciBuildsDs_avro_gcs`
|
||||
|
||||
In addition to this, names are passed through a normalization function and then
|
||||
compared to the same normalized form of other entity names and made sure to not
|
||||
collide. This rule of uniqueness exists to avoid situations where e.g. both
|
||||
`my-component` and `MyComponent` are registered side by side, which leads to
|
||||
confusion and risk. The normalization function is also configurable, but the
|
||||
default behavior is as follows.
|
||||
|
||||
- Strip out all characters outside of the set `[a-zA-Z0-9]`
|
||||
- Convert to lowercase
|
||||
|
||||
Example: `CircleciBuildsDs_avro_gcs` -> `circlecibuildsdsavrogcs`
|
||||
|
||||
### `namespace`
|
||||
|
||||
The `name` of a namespace that the entity belongs to. This field is optional,
|
||||
|
||||
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 19 KiB |
@@ -31,8 +31,8 @@ auth:
|
||||
providers:
|
||||
gitlab:
|
||||
development:
|
||||
clientId: ${AUTH_GITLAB_APPLICATION_ID}
|
||||
clientSecret: ${AUTH_GITLAB_SECRET}
|
||||
clientId: ${AUTH_GITLAB_CLIENT_ID}
|
||||
clientSecret: ${AUTH_GITLAB_CLIENT_SECRET}
|
||||
## uncomment if using self-hosted GitLab
|
||||
# audience: https://gitlab.company.com
|
||||
```
|
||||
|
||||
@@ -77,7 +77,6 @@ built-in providers:
|
||||
+
|
||||
const app = createApp({
|
||||
apis,
|
||||
plugins: Object.values(plugins),
|
||||
+ components: {
|
||||
+ SignInPage: props => (
|
||||
+ <SignInPage
|
||||
@@ -96,7 +95,6 @@ To also allow unauthenticated guest access, use the `providers` prop for
|
||||
```diff
|
||||
const app = createApp({
|
||||
apis,
|
||||
plugins: Object.values(plugins),
|
||||
+ components: {
|
||||
+ SignInPage: props => (
|
||||
+ <SignInPage
|
||||
|
||||
@@ -6,8 +6,9 @@ description: Documentation on Writing Backstage Configuration Files
|
||||
|
||||
## File Format
|
||||
|
||||
Configuration is stored in YAML format in `app-config.yaml` files, looking
|
||||
something like this:
|
||||
Configuration is stored in YAML format in `app-config.yaml` files. This
|
||||
configuration is shared between the frontend and backend and it looks something
|
||||
like this:
|
||||
|
||||
```yaml
|
||||
app:
|
||||
@@ -32,6 +33,15 @@ proxy:
|
||||
Configuration files are typically checked in and stored in the repo that houses
|
||||
the rest of the Backstage application.
|
||||
|
||||
The particular configuration that is available to each Backstage app depends on
|
||||
what plugins and packages are installed. To view the configuration reference for
|
||||
your own project, including what configuration keys available and whether they
|
||||
are needed by the frontend, use the following command:
|
||||
|
||||
```sh
|
||||
yarn backstage-cli config:docs
|
||||
```
|
||||
|
||||
## Environment Variable Overrides
|
||||
|
||||
Individual configuration values can be overridden using environment variables
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
---
|
||||
id: catalog-customization
|
||||
title: Catalog Customization
|
||||
# prettier-ignore
|
||||
description: How to add custom filters or interface elements to the Backstage software catalog
|
||||
---
|
||||
|
||||
The Backstage software catalog comes with a default `CatalogIndexPage` to filter
|
||||
and find catalog entities. This is already set up by default by
|
||||
`@backstage/create-app`.
|
||||
|
||||
If you want to change the default index page - such as to add a custom filter to
|
||||
the catalog - you can replace the routing in `App.tsx` to point to your own
|
||||
`CatalogIndexPage`.
|
||||
|
||||
> Note: The catalog index page is designed to have a minimal code footprint to
|
||||
> support easy customization, but creating a copy does introduce a possibility
|
||||
> of drifting out of date over time. Be sure to check the catalog
|
||||
> [CHANGELOG](https://github.com/backstage/backstage/blob/master/plugins/catalog/CHANGELOG.md)
|
||||
> periodically.
|
||||
|
||||
For example, suppose that I want to allow filtering by a custom annotation added
|
||||
to entities, `company.com/security-tier`. To start, I'll copy the code for the
|
||||
default catalog page and create a component in a
|
||||
[new plugin](../../plugins/create-a-plugin.md):
|
||||
|
||||
```tsx
|
||||
// imports, etc omitted for brevity. for full source see:
|
||||
// https://github.com/backstage/backstage/blob/master/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx
|
||||
export const CustomCatalogPage = () => {
|
||||
return (
|
||||
<CatalogLayout>
|
||||
<Content>
|
||||
<ContentHeader title="Components">
|
||||
<CreateComponentButton />
|
||||
<SupportButton>All your software catalog entities</SupportButton>
|
||||
</ContentHeader>
|
||||
<div className={styles.contentWrapper}>
|
||||
<EntityListProvider>
|
||||
<div>
|
||||
<EntityKindPicker initialFilter="component" hidden />
|
||||
<EntityTypePicker />
|
||||
<UserListPicker />
|
||||
<EntityTagPicker />
|
||||
</div>
|
||||
<CatalogTable />
|
||||
</EntityListProvider>
|
||||
</div>
|
||||
</Content>
|
||||
</CatalogLayout>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
The `EntityListProvider` shown here provides a list of entities from the
|
||||
`catalog-backend`, and a way to hook in filters.
|
||||
|
||||
Now we're ready to create a new filter that implements the `EntityFilter`
|
||||
interface:
|
||||
|
||||
```ts
|
||||
import { EntityFilter } from '@backstage/plugin-catalog-react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
class EntitySecurityTierFilter implements EntityFilter {
|
||||
constructor(readonly values: string[]) {}
|
||||
filterEntity(entity: Entity): boolean {
|
||||
const tier = entity.metadata.annotations?.['company.com/security-tier'];
|
||||
return tier !== undefined && this.values.includes(tier);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `EntityFilter` interface permits backend filters, which are passed along to
|
||||
the `catalog-backend` - or frontend filters, which are applied after entities
|
||||
are loaded from the backend.
|
||||
|
||||
We'll use this filter to extend the default filters in a type-safe way. Let's
|
||||
create the custom filter shape extending the default somewhere alongside this
|
||||
filter:
|
||||
|
||||
```ts
|
||||
export type CustomFilters = DefaultEntityFilters & {
|
||||
securityTiers?: EntitySecurityTierFilter;
|
||||
};
|
||||
```
|
||||
|
||||
To control this filter, we can create a React component that shows checkboxes
|
||||
for the security tiers. This component will make use of the
|
||||
`useEntityListProvider` hook, which accepts this extended filter type as a
|
||||
[generic](https://www.typescriptlang.org/docs/handbook/2/generics.html)
|
||||
parameter:
|
||||
|
||||
```tsx
|
||||
export const EntitySecurityTierPicker = () => {
|
||||
// The securityTiers key is recognized due to the CustomFilter generic
|
||||
const {
|
||||
filters: { securityTiers },
|
||||
updateFilters,
|
||||
} = useEntityListProvider<CustomFilters>();
|
||||
|
||||
// Toggles the value, depending on whether it's already selected
|
||||
function onChange(value: string) {
|
||||
const newTiers = securityTiers?.values.includes(value)
|
||||
? securityTiers.values.filter(tier => tier !== value)
|
||||
: [...(securityTiers?.values ?? []), value];
|
||||
updateFilters({
|
||||
securityTiers: newTiers.length
|
||||
? new EntitySecurityTierFilter(newTiers)
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
const tierOptions = ['1', '2', '3'];
|
||||
return (
|
||||
<FormControl component="fieldset">
|
||||
<Typography variant="button">Security Tier</Typography>
|
||||
<FormGroup>
|
||||
{tierOptions.map(tier => (
|
||||
<FormControlLabel
|
||||
key={tier}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={securityTiers?.values.includes(tier)}
|
||||
onChange={() => onChange(tier)}
|
||||
/>
|
||||
}
|
||||
label={`Tier ${tier}`}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
</FormControl>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
Now we can add the component to `CustomCatalogPage`:
|
||||
|
||||
```diff
|
||||
export const CustomCatalogPage = () => {
|
||||
return (
|
||||
...
|
||||
<EntityListProvider>
|
||||
<div>
|
||||
<EntityKindPicker initialFilter="component" hidden />
|
||||
<EntityTypePicker />
|
||||
<UserListPicker />
|
||||
+ <EntitySecurityTierPicker />
|
||||
<EntityTagPicker />
|
||||
</div>
|
||||
<CatalogTable />
|
||||
</EntityListProvider>
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
This page itself can be exported as a routable extension in the plugin:
|
||||
|
||||
```ts
|
||||
export const CustomCatalogIndexPage = myPlugin.provide(
|
||||
createRoutableExtension({
|
||||
component: () =>
|
||||
import('./components/CustomCatalogPage').then(m => m.CustomCatalogPage),
|
||||
mountPoint: catalogRouteRef,
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
Finally, we can replace the catalog route in the Backstage application with our
|
||||
new `CustomCatalogIndexPage`.
|
||||
|
||||
```diff
|
||||
# packages/app/src/App.tsx
|
||||
const routes = (
|
||||
<FlatRoutes>
|
||||
<Navigate key="/" to="/catalog" />
|
||||
- <Route path="/catalog" element={<CatalogIndexPage />} />
|
||||
+ <Route path="/catalog" element={<CustomCatalogIndexPage />} />
|
||||
```
|
||||
|
||||
The same method can be used to customize the _default_ filters with a different
|
||||
interface - for such usage, the generic argument isn't needed since the filter
|
||||
shape remains the same as the default.
|
||||
@@ -399,16 +399,17 @@ well-known / common relations and their semantics.
|
||||
|
||||
## Common to All Kinds: Status
|
||||
|
||||
The `status` root field is a read-only set of statuses, pertaining to the
|
||||
The `status` root object is a read-only set of statuses, pertaining to the
|
||||
current state or health of the entity, described in the
|
||||
[well-known statuses section](well-known-statuses.md). Each status field
|
||||
contains a specific blob of data that describes some aspect of the state of the
|
||||
entity, as seen from the point of view of some specific system. Different
|
||||
systems may contribute to this status object, under their own respective keys.
|
||||
[well-known statuses section](well-known-statuses.md).
|
||||
|
||||
Currently, the only defined field is the `items` array. Each of its items
|
||||
contains a specific data structure that describes some aspect of the state of
|
||||
the entity, as seen from the point of view of some specific system. Different
|
||||
systems may contribute to this array, under their own respective `type` keys.
|
||||
|
||||
The current main use case for this field is for the ingestion processes of the
|
||||
catalog itself to convey information about failures and warnings back to the
|
||||
user.
|
||||
catalog itself to convey information about errors and warnings back to the user.
|
||||
|
||||
A status field as part of a single entity that's read out of the API may look as
|
||||
follows.
|
||||
@@ -417,9 +418,18 @@ follows.
|
||||
{
|
||||
// ...
|
||||
"status": {
|
||||
"backstage.io/catalog-processing": {
|
||||
"errors": []
|
||||
}
|
||||
"items": [
|
||||
{
|
||||
"type": "backstage.io/catalog-processing",
|
||||
"level": "error",
|
||||
"message": "NotFoundError: File not found",
|
||||
"error": {
|
||||
"name": "NotFoundError",
|
||||
"message": "File not found",
|
||||
"stack": "..."
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"spec": {
|
||||
// ...
|
||||
@@ -427,23 +437,27 @@ follows.
|
||||
}
|
||||
```
|
||||
|
||||
The keys of the `status` object are arbitrary strings. We recommend that any
|
||||
statuses that are not strictly private within the organization be namespaced to
|
||||
avoid collisions. Statuses emitted by Backstage core processes will for example
|
||||
be prefixed with `backstage.io/` as in the example above.
|
||||
The fields of a status item are:
|
||||
|
||||
The values of the `status` object are currently left unrestricted, except that
|
||||
they must be objects. We reserve the right to extend this model in the future,
|
||||
such that some fields of those value objects gain standardized meaning. We may
|
||||
for example want to add a standard concept of "severity" or "level" to these.
|
||||
| Field | Type | Description |
|
||||
| --------- | ------ | ------------------------------------------------------------------------------------------------ |
|
||||
| `type` | String | The type of status as a unique key per source. Each type may appear more than once in the array. |
|
||||
| `level` | String | The level / severity of the status item: 'info', 'warning, or 'error'. |
|
||||
| `message` | String | A brief message describing the status, intended for human consumption. |
|
||||
| `error` | Object | An optional serialized error object related to the status. |
|
||||
|
||||
Entity descriptor YAML files are not supposed to contain this field. Instead,
|
||||
catalog processors analyze the entity descriptor data and its surroundings, and
|
||||
deduce status entries that are then attached onto the entity as read from the
|
||||
catalog.
|
||||
The `type` is an arbitrary string, but we recommend that types that are not
|
||||
strictly private within the organization be namespaced to avoid collisions.
|
||||
Types emitted by Backstage core processes will for example be prefixed with
|
||||
`backstage.io/` as in the example above.
|
||||
|
||||
Entity descriptor YAML files are not supposed to contain a `status` root key.
|
||||
Instead, catalog processors analyze the entity descriptor data and its
|
||||
surroundings, and deduce status entries that are then attached onto the entity
|
||||
as read from the catalog.
|
||||
|
||||
See the [well-known statuses section](well-known-statuses.md) for a list of
|
||||
well-known / common relations and their semantics.
|
||||
well-known / common status types.
|
||||
|
||||
## Kind: Component
|
||||
|
||||
@@ -706,6 +720,25 @@ You can find out more about the `parameters` key
|
||||
You can find out more about the `steps` key
|
||||
[here](../software-templates/writing-templates.md)
|
||||
|
||||
### `spec.owner` [optional]
|
||||
|
||||
An [entity reference](#string-references) to the owner of the component, e.g.
|
||||
`artist-relations-team`. This field is required.
|
||||
|
||||
In Backstage, the owner of a Template is the singular entity (commonly a team)
|
||||
that bears ultimate responsibility for the Template, and has the authority and
|
||||
capability to develop and maintain it. They will be the point of contact if
|
||||
something goes wrong, or if features are to be requested. The main purpose of
|
||||
this field is for display purposes in Backstage, so that people looking at
|
||||
catalog items can get an understanding of to whom this Template belongs. It is
|
||||
not to be used by automated processes to for example assign authorization in
|
||||
runtime systems. There may be others that also develop or otherwise touch the
|
||||
Template, but there will always be one ultimate owner.
|
||||
|
||||
| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type |
|
||||
| ------------------------------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------------- |
|
||||
| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownerOf`, and reverse `ownedBy`](well-known-relations.md#ownedby-and-ownerof) |
|
||||
|
||||
## Kind: API
|
||||
|
||||
Describes the following entity kind:
|
||||
|
||||
@@ -353,18 +353,43 @@ relation could be considered for addition to the core.
|
||||
|
||||
## Adding a New Status field
|
||||
|
||||
Example intents:
|
||||
Example intent:
|
||||
|
||||
> "We would like to convey entity statuses through the catalog in a generic way,
|
||||
> as an integration layer. Our monitoring and alerting system has a plugin with
|
||||
> Backstage, and it would be useful if the entity's status field contained the
|
||||
> current alert state close to the actual entity data for anyone to consume.
|
||||
> current alert state close to the actual entity data for anyone to consume. We
|
||||
> find the `status.items` semantics a poor fit, so we would prefer to make our
|
||||
> own custom field under `status` for these purposes."
|
||||
|
||||
While we are considering a mechanism for contributing generic statuses to
|
||||
entities, no such mechanism has yet been built. If you are interested in that
|
||||
topic, [this issue](https://github.com/backstage/backstage/issues/2292) contains
|
||||
We have not yet ventured to define any generic semantics for the `status`
|
||||
object. We recommend sticking with the `status.items` mechanism where possible
|
||||
(see below), since third party consumers will not be able to consume your status
|
||||
information otherwise. Please reach out to the maintainers on Discord or by
|
||||
making a GitHub issue describing your use case if you are interested in this
|
||||
topic.
|
||||
|
||||
## Adding a New Status Item Type
|
||||
|
||||
Example intent:
|
||||
|
||||
> "The semantics of the entity `status.items` field are fine for our needs, but
|
||||
> we want to contribute our own type of status into that array instead of the
|
||||
> catalog specific one."
|
||||
|
||||
This is a simple, low risk way of adding your own status information to
|
||||
entities. Consumers will be able to easily track and display the status together
|
||||
with other types / sources.
|
||||
|
||||
We recommend that any status type that are not strictly private within the
|
||||
organization be namespaced to avoid collisions. Statuses emitted by Backstage
|
||||
core processes will for example be prefixed with `backstage.io/`, your
|
||||
organization may prefix with `my-org.net/`, and `pagerduty.com/active-alerts`
|
||||
could be a sensible complete status item type for that particular external
|
||||
system.
|
||||
|
||||
The mechanics for how to emit custom statuses is not in place yet, so if this is
|
||||
of interest to you, you might consider contacting the maintainers on Discord or
|
||||
my making a GitHub issue describing your use case.
|
||||
[This issue](https://github.com/backstage/backstage/issues/2292) also contains
|
||||
more context.
|
||||
|
||||
But in general, errors emitted (and exceptions thrown) by any processor
|
||||
including custom ones, end up in the [well known key](well-known-statuses.md)
|
||||
for ingestion status.
|
||||
|
||||
@@ -6,35 +6,37 @@ sidebar_label: Well-known Statuses
|
||||
description: Lists a number of well known entity statuses, that have defined semantics. They can be attached to catalog entities and consumed by plugins as needed.
|
||||
---
|
||||
|
||||
This section lists a number of well known
|
||||
[entity status fields](descriptor-format.md#common-to-all-kinds-status), that
|
||||
have defined semantics. They can be attached to catalog entities and consumed by
|
||||
This section lists well known
|
||||
[entity statuses](descriptor-format.md#common-to-all-kinds-status), that have
|
||||
defined semantics. They can be attached to catalog entities and consumed by
|
||||
plugins as needed.
|
||||
|
||||
If you are looking to extend the set of statuses, see
|
||||
If you are looking to extend the statuses, see
|
||||
[Extending the model](extending-the-model.md).
|
||||
|
||||
## Common Fields
|
||||
|
||||
The values of statuses are currently left unrestricted, except that they must be
|
||||
objects. They therefore currently formally have no common fields.
|
||||
The `status` object of an entity is currently left unrestricted, except for the
|
||||
`items` field. Its structure is defined in the
|
||||
[descriptor format](descriptor-format.md#common-to-all-kinds-status) section.
|
||||
|
||||
We reserve the right to extend this model in the future, such that some fields
|
||||
of those value objects gain standardized meaning. We may for example want to add
|
||||
a standard concept of "severity" or "level" to these.
|
||||
We reserve the right to extend this model in the future. This status is in
|
||||
active development and its format will change unexpectedly. Do not consume it in
|
||||
your own code until such a time that this documentation has been updated.
|
||||
|
||||
## Statuses
|
||||
## Status Item Types
|
||||
|
||||
This is a (non-exhaustive) list of statuses that are known to be in active use.
|
||||
This is a (non-exhaustive) list of `status.items.[].type` values that are known
|
||||
to be in active use.
|
||||
|
||||
### `backstage.io/catalog-processing`
|
||||
|
||||
Contains the current status of the catalog's ingestion of this entity. Errors
|
||||
that may appear here include inability to read from the remote SCM provider,
|
||||
syntax errors in the YAML file, and similar.
|
||||
Expresses an aspect of the current status of the catalog's ingestion of this
|
||||
entity. Errors that may appear here include inability to read from the remote
|
||||
SCM provider, syntax errors in the YAML file, and similar.
|
||||
|
||||
Note that the entity data itself may be of an older version, when errors are
|
||||
present. The ingestion system keeps the old, valid entity data untouched when
|
||||
present. The ingestion system keeps the old valid entity data untouched when
|
||||
possible, so the errors described in this state may not seem to align with the
|
||||
rest of the entity, because they pertain to a remote that could not be
|
||||
successfully ingested. This is normal.
|
||||
@@ -42,10 +44,12 @@ successfully ingested. This is normal.
|
||||
```yaml
|
||||
# Example:
|
||||
status:
|
||||
backstage.io/catalog-processing:
|
||||
errors: []
|
||||
items:
|
||||
- type: backstage.io/catalog-processing
|
||||
level: error
|
||||
message: 'NotFoundError: File not found'
|
||||
error:
|
||||
name: NotFoundError
|
||||
message: File not found
|
||||
stack: ...
|
||||
```
|
||||
|
||||
This status is in active development and its format will change unexpectedly. Do
|
||||
not consume it in your own code until such a time that this documentation has
|
||||
been updated.
|
||||
|
||||
@@ -0,0 +1,334 @@
|
||||
---
|
||||
id: migrating-from-v1alpha1-to-v1beta2
|
||||
title: Migrating to v1beta2 templates
|
||||
# prettier-ignore
|
||||
description:
|
||||
How to move your old templates from v1alpha1 to the more declarative v1beta2
|
||||
---
|
||||
|
||||
# What's new?
|
||||
|
||||
Previously, the scaffolder was very restricted in what you could do when
|
||||
creating new software components from templates. There were three scaffolding
|
||||
steps which was pretty hard to extend and add new functionality to, difficult to
|
||||
re-use logic between templates. There used to be a fixed pipeline of
|
||||
`preparers`, `templaters`, and `publishers`, which were defined by the backend
|
||||
and needed to be run for each template. This is now changed, to give the
|
||||
template total control over what should be executed as part of the templating
|
||||
run. This makes templates a little more declarative as you can now register
|
||||
different `actions` or `functions` with the `scaffolder-backend` which you then
|
||||
can decide how, and in what order, to run using the template definition YAML
|
||||
file.
|
||||
|
||||
We've also made some improvements, and added some helpers to work with
|
||||
cookiecutter. The skeleton for a template can now be stored in a different place
|
||||
to where your entity definition is: previously you needed to have your
|
||||
`template.yaml` next to the skeleton source (`{{cookiecutter.component_id}}`
|
||||
directory), but now that's not the case. Part of the changes with the `v1beta2`
|
||||
syntax is that you can grab your template source from any repository, and re-use
|
||||
them between templates.
|
||||
|
||||
We've also renamed the `schema` property to `parameters` as this makes more
|
||||
sense when using them as parameters to the actions or steps that you've setup
|
||||
for your templates. There's the added benefit that you can now assign an array
|
||||
to the `parameters` property, which will then give you multiple steps in the UI,
|
||||
so you can split apart your input parameters and group them as needed rather
|
||||
than having one long list of input fields.
|
||||
|
||||
## The `parameters` property
|
||||
|
||||
The `schema` key has now been renamed to `parameters` with a few more features.
|
||||
You can pass an array now to break apart the input form into different steps in
|
||||
the UI. You can also specify `ui:schema` fields that are passed along to
|
||||
[`react-jsonschema-form`](https://rjsf-team.github.io/react-jsonschema-form/)
|
||||
inline with the JSON schema.
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
parameters:
|
||||
- title: Fill in some steps
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
title: Name
|
||||
type: string
|
||||
description: Unique name of the component
|
||||
ui:autofocus: true
|
||||
ui:options:
|
||||
rows: 5
|
||||
```
|
||||
|
||||
## The `steps` property
|
||||
|
||||
`v1beta2` template syntax introduces the new `steps` property, which is an array
|
||||
of `actions` that the scaffolder will run in combination with the user input
|
||||
that is declared in the `schema`. Actions look like the following:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
steps:
|
||||
- id: publish # a unique id for the step, can be anything you like
|
||||
name: Publish # a user friendly name for the step, this is what is shown in the frontend
|
||||
action: publish:github # the action ID that has been registered with the scaffolder-backend
|
||||
input: # parameters that are passed as input to the action handler function
|
||||
allowedHosts: ['github.com']
|
||||
description: 'This is {{ parameters.name }}' # handlebars templating is supported with the values from the parameters section in the same file.
|
||||
repoUrl: '{{ parameters.repoUrl }}'
|
||||
```
|
||||
|
||||
# Migrating a `v1alpha1` template
|
||||
|
||||
## The template definition (.yaml)
|
||||
|
||||
### `parameters`
|
||||
|
||||
Because of the changes to invert the control to the `template.yaml` definition
|
||||
for running the workflow, we need to adjust the `schema` property and we also
|
||||
now need to define what the template is actually going to do as part of the
|
||||
template run.
|
||||
|
||||
A simple migration would move the following yaml:
|
||||
|
||||
```yaml
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: Template
|
||||
metadata:
|
||||
name: react-ssr-template
|
||||
title: React SSR Template
|
||||
description: Create a website powered with Next.js
|
||||
tags:
|
||||
- recommended
|
||||
- react
|
||||
spec:
|
||||
owner: web@example.com
|
||||
templater: cookiecutter
|
||||
type: website
|
||||
path: '.'
|
||||
schema:
|
||||
required:
|
||||
- component_id
|
||||
- description
|
||||
properties:
|
||||
component_id:
|
||||
title: Name
|
||||
type: string
|
||||
description: Unique name of the component
|
||||
description:
|
||||
title: Description
|
||||
type: string
|
||||
description: Help others understand what this website is for.
|
||||
```
|
||||
|
||||
To something that looks like the following:
|
||||
|
||||
```yaml
|
||||
apiVersion: backstage.io/v1beta2
|
||||
kind: Template
|
||||
metadata:
|
||||
name: react-ssr-template
|
||||
title: React SSR Template
|
||||
description: Create a website powered with Next.js
|
||||
tags:
|
||||
- recommended
|
||||
- react
|
||||
spec:
|
||||
owner: web@example.com
|
||||
type: website
|
||||
parameters:
|
||||
- title: Add some input
|
||||
required:
|
||||
- component_id
|
||||
- description
|
||||
properties:
|
||||
component_id:
|
||||
title: Name
|
||||
type: string
|
||||
description: Unique name of the component
|
||||
description:
|
||||
title: Description
|
||||
type: string
|
||||
description: Help others understand what this website is for.
|
||||
- title: Some more additional info that was previously provided automatically
|
||||
required:
|
||||
- owner
|
||||
- repoUrl
|
||||
properties:
|
||||
owner:
|
||||
title: Owner
|
||||
type: string
|
||||
description: Owner of the component
|
||||
ui:field: OwnerPicker
|
||||
ui:options:
|
||||
allowedKinds:
|
||||
- Group
|
||||
- title: Choose a location
|
||||
repoUrl:
|
||||
title: Repository Location
|
||||
type: string
|
||||
ui:field: RepoUrlPicker
|
||||
ui:options:
|
||||
allowedHosts:
|
||||
- github.com
|
||||
```
|
||||
|
||||
There are a few things to note here. On the `alpha` version, the second step of
|
||||
the template flow in the frontend was provided by Backstage for free, so we used
|
||||
to collect the user input for the `owner` field and the `repositoryUrl` that you
|
||||
were going to publish to. Now because `actions` can have any workflow they like,
|
||||
it doesn't make sense to still provide these fields for every scaffolding
|
||||
workflow, as you might not need these anymore. That's why we now manually add
|
||||
those fields back into the template parameters that are shown to the user:
|
||||
|
||||
```yaml
|
||||
- title: Some more additional info that was previously provided automatically
|
||||
required:
|
||||
- owner
|
||||
- repoUrl
|
||||
properties:
|
||||
owner:
|
||||
title: Owner
|
||||
type: string
|
||||
description: Owner of the component
|
||||
ui:field: OwnerPicker
|
||||
ui:options:
|
||||
allowedKinds:
|
||||
- Group
|
||||
- title: Choose a location
|
||||
repoUrl:
|
||||
title: Repository Location
|
||||
type: string
|
||||
ui:field: RepoUrlPicker
|
||||
ui:options:
|
||||
allowedHosts:
|
||||
- github.com
|
||||
```
|
||||
|
||||
Maybe you also don't need to publish to `github.com`, you should replace this
|
||||
with your VCS provider URL that is listed in your `integrations` config instead.
|
||||
|
||||
### `steps`
|
||||
|
||||
So now we should have all the required information that we need from the user in
|
||||
a much more extensible way. We now need to tell the scaffolder what to do with
|
||||
these parameters and what to do with the user input.
|
||||
|
||||
We've made templating using `cookiecutter` a little simpler. You don't need to
|
||||
store the `cookiecutter` skeleton in the same directory as the `template.yaml`
|
||||
definition, it can live wherever you like - maybe a shared repository somewhere
|
||||
so you can re-use the skeletons but apply different actions for different
|
||||
templates depending on your use case.
|
||||
|
||||
We also no longer need to have a directory called
|
||||
`{{cookiecutter.component_id}}`. This is because now we can't ensure that
|
||||
`component_id` will be a parameter that is provided from the frontend, this
|
||||
could break `cookiecutter`. If your directory structure used to look like this:
|
||||
|
||||
```
|
||||
my-awesome-template
|
||||
-> {{cookiecutter.component_id}}
|
||||
-> file.txt
|
||||
-> some_more_files.ts
|
||||
-> hooks
|
||||
-> post_gen_project.sh
|
||||
-> template.yaml
|
||||
```
|
||||
|
||||
We now recommend that you move to the following structure:
|
||||
|
||||
```
|
||||
my-awesome-template
|
||||
-> skeleton
|
||||
-> file.txt
|
||||
-> some_more_files.ts
|
||||
-> template.yaml
|
||||
```
|
||||
|
||||
This migration renames the skeleton folder to something more semantic, and also
|
||||
drops support for `cookiecutter` hooks. We've dropped support for `cookiecutter`
|
||||
hooks for now, as hopefully everything that is stored in these hooks can be
|
||||
moved to `actions` instead, and for security reasons, it's more secure to run
|
||||
trusted code that you ship with Backstage as an action rather than some script
|
||||
that can be pulled in from anywhere which doesn't get vetted first. It's a
|
||||
pretty big security risk that those scripts will be run on Backstage instances
|
||||
inside your infrastructure, especially `.sh` files.
|
||||
|
||||
If you really need hooks and can't find a suitable solution by using actions
|
||||
please reach out to us through a ticket and we'll see what we can do to assist
|
||||
:)
|
||||
|
||||
You'll notice that we removed the `templater` property from the `spec`
|
||||
definition in the template `yaml`, so there's no way to define that this is a
|
||||
`cookiecutter` `templater`.
|
||||
|
||||
We've created a built-in action that you can use which will when run, go grab a
|
||||
directory from anywhere and run `cookiecutter` on top of it, and then extract
|
||||
the contents into the working directory for the scaffolder.
|
||||
|
||||
Adding the `steps` for a simple template should look something like the
|
||||
following:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
steps:
|
||||
# this action will go use cookiecutter to template some files into the working directory
|
||||
- id: template # an ID for the templating step
|
||||
name: Create skeleton # A user friendly name for the action
|
||||
action: fetch:cookiecutter
|
||||
input:
|
||||
url: ./skeleton # this is the directory for your skeleton files.
|
||||
# If it's located next to the `template.yaml` then you can use a relative path,
|
||||
# otherwise you can use absolute URLs that point at the VCS: https://github.com/backstage/backstage/tree/master/some_folder_somewhere
|
||||
values:
|
||||
# for each value that you need to pass to cookiecutter, they should be listed here and set in this values object.
|
||||
# You can use the handlebars templating syntax to pull them from the input parameters listed in the same file
|
||||
name: '{{ parameters.name }}'
|
||||
owner: '{{ parameters.owner }}'
|
||||
destination: '{{ parseRepoUrl parameters.repoUrl }}'
|
||||
|
||||
# this action is for publishing the working directory to the VCS
|
||||
- id: publish
|
||||
name: Publish
|
||||
action: publish:github
|
||||
input:
|
||||
allowedHosts: ['github.com']
|
||||
description: 'This is {{ parameters.name }}'
|
||||
repoUrl: '{{ parameters.repoUrl }}'
|
||||
|
||||
# this action will then register the created component in Backstage
|
||||
- id: register
|
||||
name: Register
|
||||
action: catalog:register
|
||||
input:
|
||||
repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}'
|
||||
catalogInfoPath: '/catalog-info.yaml'
|
||||
```
|
||||
|
||||
### `output`
|
||||
|
||||
Steps can output values, and so can the template itself. This is good for
|
||||
returning values to the frontend, so we can make the buttons like
|
||||
`Go to catalog` and `Go to repo` work correctly. You can add the following to
|
||||
your `template.yaml` to make sure you return the right values from the steps:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
output:
|
||||
remoteUrl: '{{ steps.publish.output.remoteUrl }}'
|
||||
entityRef: '{{ steps.register.output.entityRef }}'
|
||||
```
|
||||
|
||||
Or you can return a `links` array with text and a URL explicitly:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
output:
|
||||
links:
|
||||
- url: '{{steps.publish.output.remoteUrl}}'
|
||||
text: 'Go to Repo'
|
||||
```
|
||||
|
||||
## Questions?
|
||||
|
||||
If you have any questions or feedback, please reach out to us on GitHub or
|
||||
Discord and we will do our best to help!
|
||||
@@ -142,6 +142,12 @@ this:
|
||||
"type": "string",
|
||||
"title": "Last name"
|
||||
},
|
||||
"nicknames":{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"telephone": {
|
||||
"type": "string",
|
||||
"title": "Telephone",
|
||||
@@ -161,6 +167,11 @@ this:
|
||||
"ui:emptyValue": "",
|
||||
"ui:autocomplete": "given-name"
|
||||
},
|
||||
"nicknames": {
|
||||
"ui:options":{
|
||||
"orderable": false
|
||||
}
|
||||
},
|
||||
"telephone": {
|
||||
"ui:options": {
|
||||
"inputType": "tel"
|
||||
@@ -202,6 +213,12 @@ spec:
|
||||
title: Last name
|
||||
ui:emptyValue: ''
|
||||
ui:autocomplete: given-name
|
||||
nicknames:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
ui:options:
|
||||
orderable: false
|
||||
telephone:
|
||||
type: string
|
||||
title: Telephone
|
||||
@@ -222,17 +239,17 @@ You can see it in the above full example which is a separate step and it looks a
|
||||
little like this:
|
||||
|
||||
```yaml
|
||||
- title: Choose a location
|
||||
required:
|
||||
- repoUrl
|
||||
properties:
|
||||
repoUrl:
|
||||
title: Repository Location
|
||||
type: string
|
||||
ui:field: RepoUrlPicker
|
||||
ui:options:
|
||||
allowedHosts:
|
||||
- github.com
|
||||
- title: Choose a location
|
||||
required:
|
||||
- repoUrl
|
||||
properties:
|
||||
repoUrl:
|
||||
title: Repository Location
|
||||
type: string
|
||||
ui:field: RepoUrlPicker
|
||||
ui:options:
|
||||
allowedHosts:
|
||||
- github.com
|
||||
```
|
||||
|
||||
The `allowedHosts` part should be set to where you wish to enable this template
|
||||
@@ -304,7 +321,10 @@ You might have noticed in the examples that there are `{{ }}`, and these are a
|
||||
`yaml` together. All the form inputs from the `parameters` section, when passed
|
||||
to the steps will be available by using the template syntax
|
||||
`{{ parameters.something }}`. This is great for passing the values from the form
|
||||
into different steps and reusing these input variables.
|
||||
into different steps and reusing these input variables. To pass arrays or
|
||||
objects use the syntax `{{ json paramaters.something }}` where
|
||||
`paramaters.something` is of type `object` or `array` in the `jsonSchema`, such
|
||||
as the `nicknames` parameter in the previous example.
|
||||
|
||||
As you can see above in the `Outputs` section, `actions` and `steps` can also
|
||||
output things. So you can grab that output by using
|
||||
|
||||
@@ -23,7 +23,8 @@ Backstage provides a utility for creating new apps. It guides you through the
|
||||
initial setup of selecting the name of the app and a database for the backend.
|
||||
The database options are either SQLite or PostgreSQL, where the latter requires
|
||||
you to set up a separate database instance. If in doubt, choose SQLite, but
|
||||
don't worry about the choice, it's easy to change later!
|
||||
don't worry about the choice, it's easy to change later! Here is a
|
||||
[tutorial](../tutorials/switching-sqlite-postgres.md) for it.
|
||||
|
||||
The easiest way to run the create app package is with `npx`:
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ entities that mirror your org setup.
|
||||
The processor that performs the import, `GithubOrgReaderProcessor`, comes
|
||||
installed with the default setup of Backstage.
|
||||
|
||||
If you replace the set of processors in your installation using that facility of
|
||||
the catalog builder class, you can import and add it as follows.
|
||||
If you have _replaced_ the set of processors in your installation using
|
||||
`replaceProcessors`, you can import and add it as follows:
|
||||
|
||||
```ts
|
||||
// Typically in packages/backend/src/plugins/catalog.ts
|
||||
@@ -45,30 +45,23 @@ catalog:
|
||||
locations:
|
||||
- type: github-org
|
||||
target: https://github.com/my-org-name
|
||||
processors:
|
||||
githubOrg:
|
||||
providers:
|
||||
- target: https://github.com
|
||||
apiBaseUrl: https://api.github.com
|
||||
token: ${GITHUB_TOKEN}
|
||||
```
|
||||
|
||||
If Backstage is configured to use GitHub Apps authentication you must grant
|
||||
`Read-Only` access for `Members` under `Organization` in order to ingest users
|
||||
correctly. You can modify the app's permissions under the organization settings,
|
||||
`https://github.com/organizations/{ORG}/settings/apps/{APP_NAME}/permissions`.
|
||||

|
||||
|
||||
**Please note that when you change permissions, the app owner will get an email
|
||||
that must be approved first before the changes are applied.**
|
||||

|
||||
|
||||
Locations point out the specific org(s) you want to import. The `type` of these
|
||||
locations must be `github-org`, and the `target` must point to the exact URL of
|
||||
some organization. You can have several such location entries if you want, but
|
||||
typically you will have just one.
|
||||
some organization. You can have several such location entries if needed.
|
||||
|
||||
The processor itself is configured in the other block, under
|
||||
`catalog.processors.githubOrg`. There may be many providers, each targeting a
|
||||
specific `target` which is supposed to be the address of the home page of GitHub
|
||||
or your GitHub Enterprise installation.
|
||||
|
||||
The example above assumes that the backend is started with an environment
|
||||
variable called `GITHUB_TOKEN` that contains a Personal Access Token. The token
|
||||
needs to have at least the scopes `read:org`, `read:user`, and `user:email` in
|
||||
the given `target`.
|
||||
|
||||
If you want to address your own GitHub Enterprise instance, replace occurrences
|
||||
of `https://github.com` in the configuration above with the address of your
|
||||
GitHub Enterprise home page, and the `apiBaseUrl` to where your API endpoint
|
||||
lives - commonly on the form `https://<host>/api/v3`.
|
||||
The authorization for loading org information comes from a configured
|
||||
[GitHub integration](locations.md#configuration). When using a personal access
|
||||
token, the token needs to have at least the scopes `read:org`, `read:user`, and
|
||||
`user:email` in the given `target`.
|
||||
|
||||
@@ -43,13 +43,13 @@ this.
|
||||
|
||||
The UI is a thin, client-side wrapper around a set of plugins. It provides some
|
||||
core UI components and libraries for shared activities such as config
|
||||
management. [[live demo](https://backstage-demo.roadie.io/)]
|
||||
management. [[live demo](https://demo.backstage.io/catalog)]
|
||||
|
||||

|
||||
|
||||
Each plugin typically makes itself available in the UI on a dedicated URL. For
|
||||
example, the Lighthouse plugin is registered with the UI on `/lighthouse`.
|
||||
[[live demo](https://backstage-demo.roadie.io/lighthouse)]
|
||||
[[learn more](https://backstage.io/blog/2020/04/06/lighthouse-plugin)]
|
||||
|
||||

|
||||
|
||||
@@ -116,9 +116,9 @@ Architecturally, plugins can take three forms:
|
||||
#### Standalone plugins
|
||||
|
||||
Standalone plugins run entirely in the browser.
|
||||
[The Tech Radar plugin](https://backstage-demo.roadie.io/tech-radar), for
|
||||
example, simply renders hard-coded information. It doesn't make any API requests
|
||||
to other services.
|
||||
[The Tech Radar plugin](https://demo.backstage.io/tech-radar), for example,
|
||||
simply renders hard-coded information. It doesn't make any API requests to other
|
||||
services.
|
||||
|
||||

|
||||
|
||||
@@ -182,6 +182,21 @@ work but
|
||||
[aren't tested as fully](https://github.com/backstage/backstage/issues/2460)
|
||||
yet.
|
||||
|
||||
## Cache
|
||||
|
||||
The Backstage backend and its builtin plugins are also able to leverage cache
|
||||
stores as a means of improving performance or reliability. Similar to how
|
||||
databases are supported, plugins receive logically separated cache connections,
|
||||
which are powered by [Keyv](https://github.com/lukechilds/keyv) under the hood.
|
||||
|
||||
At this time of writing, Backstage can be configured to use one of two cache
|
||||
stores: memory, which is mainly used for local testing, and memcache, which is a
|
||||
cache store better suited for production deployment. The right cache store for
|
||||
your Backstage instance will depend on your own run-time constraints and those
|
||||
required of the plugins you're running.
|
||||
|
||||
Contributions supporting other cache stores are welcome!
|
||||
|
||||
## Containerization
|
||||
|
||||
The example Backstage architecture shown above would Dockerize into three
|
||||
|
||||
@@ -108,50 +108,33 @@ Stability: `1`. Mainly intended for internal use.
|
||||
|
||||
### `core` [GitHub](https://github.com/backstage/backstage/tree/master/packages/core/)
|
||||
|
||||
#### Section: React Components
|
||||
The `@backstage/core` and `@backstage/core-api` packages are being phased out
|
||||
and replaced by other `@backstage/core-*` packages. They are still in use but
|
||||
will not receive any breaking changes.
|
||||
|
||||
All of the React components exported from `src/components/` and `src/layout/`
|
||||
### `core-api` [GitHub](https://github.com/backstage/backstage/tree/master/packages/core-api/)
|
||||
|
||||
Stability: See `@backstage/core` above
|
||||
|
||||
### `core-app-api` [GitHub](https://github.com/backstage/backstage/tree/master/packages/core-app-api/)
|
||||
|
||||
The APIs used exclusively in the app, such as `createApp` and the system icons.
|
||||
|
||||
Stability: `2`.
|
||||
|
||||
### `core-components` [GitHub](https://github.com/backstage/backstage/tree/master/packages/core-components/)
|
||||
|
||||
A collection of React components for use in Backstage plugins and apps.
|
||||
Previously exported by `@backstage/core`.
|
||||
|
||||
Stability: `1`. These components have not received a proper review of the API,
|
||||
but we also want to ensure stability.
|
||||
|
||||
#### Section: Plugin API
|
||||
### `core-plugin-api` [GitHub](https://github.com/backstage/backstage/tree/master/packages/core-plugin-api/)
|
||||
|
||||
The parts of the core API that are used by plugins, and the way plugins expose
|
||||
functionality to apps and other plugins. Includes for example `createPlugin`,
|
||||
`createRouteRef`, `createApiRef`.
|
||||
The core API used to build Backstage plugins and apps.
|
||||
|
||||
Stability: `2`. There are planned breaking changes around the way that plugins
|
||||
expose features and do routing. We still commit to keeping a short deprecation
|
||||
period so that plugins outside of the main repo have time to migrate.
|
||||
|
||||
#### Section: App API
|
||||
|
||||
The APIs used exclusively in the app, such as `createApp` and the system icons.
|
||||
|
||||
Stability: `2`
|
||||
|
||||
#### Section: Utility API Definitions
|
||||
|
||||
The type declarations of the core Utility APIs.
|
||||
|
||||
Stability: `2`. Changes to the Utility API type declarations need time to
|
||||
propagate.
|
||||
|
||||
#### Section: Utility API Implementations
|
||||
|
||||
The interfaces and default implementations for various Utility APIs, such as
|
||||
ErrorApi, IdentityApi, the auth APIs, etc.
|
||||
|
||||
Stability: `1`. Most changes to the core utility APIs will not lead to
|
||||
widespread breaking changes since most apps rely on the default implementations.
|
||||
|
||||
### `core-api` [GitHub](https://github.com/backstage/backstage/tree/master/packages/core-api/)
|
||||
|
||||
The non-visual parts of @backstage/core. Everything in this packages is
|
||||
re-exported from @backstage/core, and this package should not be used directly.
|
||||
|
||||
Stability: See @backstage/core
|
||||
Stability: `2`.
|
||||
|
||||
### `cost-insights` [GitHub](https://github.com/backstage/backstage/tree/master/plugins/cost-insights)
|
||||
|
||||
|
||||
@@ -1,7 +1,113 @@
|
||||
---
|
||||
id: backend-plugin
|
||||
title: Backend plugin
|
||||
description: Documentation on Backend plugin
|
||||
title: Backend plugins
|
||||
description: Creating and Developing Backend plugins
|
||||
---
|
||||
|
||||
## TODO
|
||||
This page describes the process of creating and managing backend plugins in your
|
||||
Backstage repository.
|
||||
|
||||
## Creating a Backend Plugin
|
||||
|
||||
A new, bare-bones backend plugin package can be created by issuing the following
|
||||
command in your Backstage repository root:
|
||||
|
||||
```sh
|
||||
yarn create-plugin --backend
|
||||
```
|
||||
|
||||
Please also see the `--help` flag for the `create-plugin` command for some
|
||||
further options that are available, notably the `--scope` and `--no-private`
|
||||
flags that control naming and publishing of the newly created package. Your repo
|
||||
root `package.json` will probably also have some default values already set up
|
||||
for these.
|
||||
|
||||
You will be asked to supply a name for the plugin. This is an identifier that
|
||||
will be part of the NPM package name, so make it short and containing only
|
||||
lowercase characters separated by dashes, for example `carmen`, if it's a
|
||||
package that adds an integration with a system named Carmen, for example. The
|
||||
full NPM package name would then be something like
|
||||
`@internal/plugin-carmen-backend`, depending on the other flags passed to the
|
||||
`create-plugin` command, and your settings for the `create-plugin` command in
|
||||
your root `package.json`.
|
||||
|
||||
Creating the plugin will take a little while, so be patient. It will helpfully
|
||||
run the initial installation and build commands, so that your package is ready
|
||||
to be hacked on! It will be located in a new folder in your `plugins` directory,
|
||||
in this example `plugins/carmen-backend`.
|
||||
|
||||
For simple development purposes, a backend plugin can actually be started in a
|
||||
standalone mode. You can do a first-light test of your service:
|
||||
|
||||
```sh
|
||||
cd plugins/carmen-backend
|
||||
yarn start
|
||||
```
|
||||
|
||||
This will think for a bit, and then say `Listening on :7000`. In a different
|
||||
terminal window, now run
|
||||
|
||||
```sh
|
||||
curl localhost:7000/carmen/health
|
||||
```
|
||||
|
||||
This should return `{"status":"ok"}`. Success! Press `Ctrl + c` to kill it
|
||||
again.
|
||||
|
||||
## Developing your Backend Plugin
|
||||
|
||||
A freshly created backend plugin does basically nothing, in terms of the overall
|
||||
app. It has a small set of basic dependencies and exposes an Express router in
|
||||
`src/service/router.ts`. This is where you will start adding routes and
|
||||
connecting those to actual underlying functionality. But nothing in your
|
||||
Backstage application / backend exposes it.
|
||||
|
||||
To actually attach and run the plugin router, you will make some modifications
|
||||
to your backend.
|
||||
|
||||
```sh
|
||||
# From the Backstage root directory
|
||||
cd packages/backend
|
||||
yarn add @internal/plugin-carmen-backend@^0.1.1 # Change this to match the plugin's package.json
|
||||
```
|
||||
|
||||
Create a new file named `packages/backend/src/plugins/carmen.ts`, and add the
|
||||
following to it
|
||||
|
||||
```ts
|
||||
import { createRouter } from '@internal/plugin-carmen-backend';
|
||||
import { PluginEnvironment } from '../types';
|
||||
|
||||
export default async function createPlugin(env: PluginEnvironment) {
|
||||
// Here is where you will add all of the required initialization code that
|
||||
// your backend plugin needs to be able to start!
|
||||
|
||||
// The env contains a lot of goodies, but our router currently only
|
||||
// needs a logger
|
||||
return await createRouter({
|
||||
logger: env.logger,
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
And finally, wire this into the overall backend router. Edit
|
||||
`packages/backend/src/index.ts`:
|
||||
|
||||
```ts
|
||||
import carmen from './plugins/carmen';
|
||||
// ...
|
||||
async function main() {
|
||||
// ...
|
||||
const carmenEnv = useHotMemoize(module, () => createEnv('carmen'));
|
||||
apiRouter.use('/carmen', await carmen(badgesEnv));
|
||||
```
|
||||
|
||||
After you start the backend (e.g. using `yarn start-backend` from the repo
|
||||
root), you should be able to fetch data from it.
|
||||
|
||||
```sh
|
||||
# Note the extra /api here
|
||||
curl localhost:7000/api/carmen/health
|
||||
```
|
||||
|
||||
This should return `{"status":"ok"}` like before. Success!
|
||||
|
||||
@@ -1,371 +0,0 @@
|
||||
---
|
||||
id: quickstart-app-auth
|
||||
title: Monorepo App Setup With Authentication
|
||||
---
|
||||
|
||||
###### January 8th 2021 - @backstage/create-app - v0.4.5
|
||||
|
||||
<br />
|
||||
|
||||
> This document takes you through setting up a Backstage app that runs in your
|
||||
> own environment. It starts with a skeleton install and verifying of the
|
||||
> monorepo's functionality. Next, authentication is added and tested.
|
||||
>
|
||||
> This document assumes you have Node.js 12 or 14 active along with Yarn and
|
||||
> Python. Please note, that at the time of this writing, the current version is
|
||||
> v0.4.5. This guide can still be used with future versions, just, verify as you
|
||||
> go.
|
||||
|
||||
# The Skeleton Application
|
||||
|
||||
From the terminal:
|
||||
|
||||
1. Create a (monorepo) application: `npx @backstage/create-app`
|
||||
1. Enter an `id` for your new app like `mybiz-backstage` I went with
|
||||
`simple-backstage-app`
|
||||
1. Choose `SQLite` as your database. This is the quickest way to get started as
|
||||
PostgreSQL requires additional setup not covered here.
|
||||
1. Start your backend: `yarn --cwd packages/backend start`
|
||||
|
||||
```zsh
|
||||
# You should see positive verbiage in your terminal output
|
||||
2020-09-11T22:20:26.712Z backstage info Listening on :7000
|
||||
```
|
||||
|
||||
5. Finally, start the frontend. Open a new terminal window and from the root of
|
||||
your project, run: `yarn start`
|
||||
|
||||
```zsh
|
||||
# You should see positive verbiage in your terminal output
|
||||
ℹ 「wds」: Project is running at http://localhost:3000/
|
||||
```
|
||||
|
||||
Once the app compiles, a browser window should have popped with your stand-alone
|
||||
application loaded at `localhost:3000`. This could take a couple minutes.
|
||||
|
||||
```zsh
|
||||
# You should see positive verbiage in your terminal output
|
||||
ℹℹ 「wdm」: Compiled successfully.
|
||||
```
|
||||
|
||||
Since there is no auth currently configured, you are automatically entered as a
|
||||
guest. Let's fix that now and add auth.
|
||||
|
||||
# The Auth Configuration
|
||||
|
||||
A default Backstage installation includes multiple authentication providers out
|
||||
of the box. The steps to enable new authentication providers in Backstage are
|
||||
very similar to each other, the biggest difference is usually configuring the
|
||||
external authentication provider. Please see a subset of possible providers and
|
||||
instructions to integrate them below. Steps 1 & 2 are described separately for
|
||||
each provider and steps beyond that are common for all.
|
||||
|
||||
<details><summary>GitHub</summary>
|
||||
<p>
|
||||
|
||||
### 1. Open `app-config.yaml` and change it as follows
|
||||
|
||||
_from:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers: {}
|
||||
```
|
||||
|
||||
_to:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers:
|
||||
github:
|
||||
development:
|
||||
clientId: ${AUTH_GITHUB_CLIENT_ID}
|
||||
clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
|
||||
## uncomment the following line if using enterprise
|
||||
# enterpriseInstanceUrl: ${AUTH_GITHUB_ENTERPRISE_INSTANCE_URL}
|
||||
```
|
||||
|
||||
### 2. Generate a GitHub client ID and secret
|
||||
|
||||
- Log into http://github.com
|
||||
- Navigate to (Settings > Developer Settings > OAuth Apps > New OAuth
|
||||
App)[https://github.com/settings/applications/new]
|
||||
- Set Homepage URL = `http://localhost:3000`
|
||||
- Set Callback URL = `http://localhost:7000/api/auth/github`
|
||||
- Click [Register application]
|
||||
- On the next page, copy and paste your new Client ID and Client Secret to
|
||||
environment variables defined in the `app-config.yaml` file,
|
||||
`AUTH_GITHUB_CLIENT_ID` & `AUTH_GITHUB_CLIENT_SECRET`
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details><summary>GitLab</summary>
|
||||
<p>
|
||||
|
||||
### 1. Open `app-config.yaml` and change it as follows
|
||||
|
||||
_from:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers: {}
|
||||
```
|
||||
|
||||
_to:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers:
|
||||
gitlab:
|
||||
development:
|
||||
clientId: ${AUTH_GITLAB_CLIENT_ID}
|
||||
clientSecret: ${AUTH_GITLAB_CLIENT_SECRET}
|
||||
audience: https://gitlab.com # Or your self-hosted GitLab instance URL
|
||||
```
|
||||
|
||||
### 2. Generate a GitLab Application client ID and secret
|
||||
|
||||
- Log into GitLab
|
||||
- Navigate to (Profile > Settings >
|
||||
Applications)[https://gitlab.com/-/profile/applications]
|
||||
- Name your application
|
||||
- Set Callback URL = `http://localhost:7000/api/auth/gitlab/handler/frame`
|
||||
- Select the following values:
|
||||
- `read_user` (Read the authenticated user's personal information)
|
||||
- `read_repository` (Allows read-only access to the repository)
|
||||
- `write_repository` (Allows read-write access to the repository)
|
||||
- `openid` (Authenticate using OpenID Connect)
|
||||
- `profile` (Allows read-only access to the user's personal information using
|
||||
OpenID Connect)
|
||||
- `email` (Allows read-only access to the user's primary email address using
|
||||
OpenID Connect)
|
||||
- Click [Save application]
|
||||
- On the next page, copy and paste your new Application ID and Secret to
|
||||
environment variables defined in the `app-config.yaml` file,
|
||||
`AUTH_GITLAB_CLIENT_ID` & `AUTH_GITLAB_CLIENT_SECRET`
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details><summary>Google</summary>
|
||||
<p>
|
||||
|
||||
### 1. Open `app-config.yaml` and change it as follows
|
||||
|
||||
_from:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers: {}
|
||||
```
|
||||
|
||||
_to:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers:
|
||||
google:
|
||||
development:
|
||||
clientId: ${AUTH_GOOGLE_CLIENT_ID}
|
||||
clientSecret: ${AUTH_GOOGLE_CLIENT_SECRET}
|
||||
```
|
||||
|
||||
### 2. Generate Google Credentials in Google Cloud console
|
||||
|
||||
- Log into https://console.cloud.google.com
|
||||
- Select or create a new project from the dropdown on the top bar
|
||||
- Navigate to (APIs & Services >
|
||||
Credentials)[https://console.cloud.google.com/apis/credentials]
|
||||
- Click Create Credentials and select [OAuth client ID]
|
||||
- Select Web Application as the application type
|
||||
- Add new Authorised JavaScript origin = `http://localhost:3000`
|
||||
- Add new Authorised redirect URI =
|
||||
`http://localhost:7000/api/auth/google/handler/frame`
|
||||
- Click [Save application]
|
||||
- Google should display a modal with your Client ID and Secret. Copy and paste
|
||||
those to environment variables defined in the `app-config.yaml` file,
|
||||
`AUTH_GOOGLE_CLIENT_ID` & `AUTH_GOOGLE_CLIENT_SECRET`
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details><summary>Microsoft</summary>
|
||||
<p>
|
||||
|
||||
### 1. Open `app-config.yaml` and change it as follows
|
||||
|
||||
_from:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers: {}
|
||||
```
|
||||
|
||||
_to:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers:
|
||||
microsoft:
|
||||
development:
|
||||
clientId: ${AUTH_MICROSOFT_CLIENT_ID}
|
||||
clientSecret: ${AUTH_MICROSOFT_CLIENT_SECRET}
|
||||
tenantId: ${AUTH_MICROSOFT_TENANT_ID}
|
||||
```
|
||||
|
||||
### 2. Create a Microsoft App Registration in Microsoft Portal
|
||||
|
||||
- Log into https://portal.azure.com
|
||||
- Navigate to (Azure Active Directory > App
|
||||
Registrations)[https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps]
|
||||
- Create a New Registration
|
||||
- Add new Redirect URI = `http://localhost:3000`
|
||||
- Add new Authorised redirect URI =
|
||||
`http://localhost:7000/api/auth/microsoft/handler/frame`
|
||||
- Click [Save application]
|
||||
- Set environment variable `AUTH_MICROSOFT_CLIENT_ID` from
|
||||
`Application (client) Id` displayed on the directory page
|
||||
- Set environment variable `AUTH_MICROSOFT_TENANT_ID` from
|
||||
`Directory (tenant) ID` displayed on the directory page
|
||||
- Navigate to Certificates & Secrets section and click [Create a new secret]
|
||||
- Set environment variable `AUTH_MICROSOFT_CLIENT_SECRET` from the `value` field
|
||||
created.
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details><summary>Auth0</summary>
|
||||
<p>
|
||||
|
||||
### 1. Open `app-config.yaml` and change it as follows
|
||||
|
||||
_from:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers: {}
|
||||
```
|
||||
|
||||
_to:_
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
providers:
|
||||
auth0:
|
||||
development:
|
||||
clientId: ${AUTH_AUTH0_CLIENT_ID}
|
||||
clientSecret: ${AUTH_AUTH0_CLIENT_SECRET}
|
||||
domain: ${AUTH_AUTH0_DOMAIN_ID}
|
||||
```
|
||||
|
||||
### 2. Create an Auth0 application in the Auth0 management console
|
||||
|
||||
- Log into https://manage.auth0.com/dashboard/
|
||||
- Navigate to Applications
|
||||
- Create a New Application
|
||||
- Select Single Page Web Application
|
||||
- Go to Settings tab
|
||||
- Add new line to Allowed Callback URLs =
|
||||
`http://localhost:7000/api/auth/auth0/handler/frame`
|
||||
- Click [Save Changes]
|
||||
- Set environment variables displayed on the Basic Information page
|
||||
- `AUTH_AUTH0_CLIENT_ID` from `Client ID` displayed on Auth0 application page
|
||||
- `AUTH_AUTH0_CLIENT_SECRET` from `Client Secret` displayed on Auth0
|
||||
application page
|
||||
- `AUTH_AUTH0_DOMAIN_ID` from `Domain` displayed on Auth0 application page
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
### 3. Set environment variables in whatever fashion is easiest for you. I chose to
|
||||
|
||||
add mine to my `.zshrc` profile.
|
||||
|
||||
```zsh
|
||||
# For macOS Catalina & Z Shell
|
||||
# ------ simple-backstage-app GitHub
|
||||
#
|
||||
# (Change the name of the environment variables based on your auth setup above)
|
||||
export AUTH_GITHUB_CLIENT_ID=xxx
|
||||
export AUTH_GITHUB_CLIENT_SECRET=xxx
|
||||
# export AUTH_GITHUB_ENTERPRISE_INSTANCE_URL=https://github.{MY_BIZ}.com
|
||||
```
|
||||
|
||||
### 4. And of course I need to source that file.
|
||||
|
||||
```zsh
|
||||
# Loading the new variables
|
||||
% source ~/.zshrc
|
||||
|
||||
# Any other currently opened terminals need to be restarted to pick up the new values
|
||||
# verify your setup by running env
|
||||
% env
|
||||
# should output something like
|
||||
> ...
|
||||
> AUTH_GITHUB_CLIENT_ID=xxx
|
||||
> AUTH_GITHUB_CLIENT_SECRET=xxx
|
||||
> ...
|
||||
```
|
||||
|
||||
### 5. Open and change _root > packages > app > src >_ `App.tsx` to use correct
|
||||
|
||||
authentication provider reference
|
||||
|
||||
```tsx
|
||||
import { githubAuthApiRef, SignInPage } from '@backstage/core';
|
||||
```
|
||||
|
||||
Modify the imported reference based on the authentication method you selected
|
||||
above:
|
||||
|
||||
| Auth Provider | Import Name |
|
||||
| ------------- | ------------------- |
|
||||
| GitHub | githubAuthApiRef |
|
||||
| GitLab | gitlabAuthApiRef |
|
||||
| Google | googleAuthApiRef |
|
||||
| Microsoft | microsoftAuthApiRef |
|
||||
| Auth0 | auth0AuthApiRef |
|
||||
|
||||
### 6. In the same file, modify createApp
|
||||
|
||||
Remember to modify the provider information based on the table above.
|
||||
|
||||
```tsx
|
||||
const app = createApp({
|
||||
apis,
|
||||
plugins: Object.values(plugins),
|
||||
components: {
|
||||
SignInPage: props => (
|
||||
<SignInPage
|
||||
{...props}
|
||||
auto
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Simple Backstage Application Login',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
After finishing setting up one (or multiple) authentication providers defined
|
||||
above you can start the backend and frontend as before
|
||||
|
||||
When the browser loads, you should be presented with a login page for GitHub.
|
||||
Login as usual with your GitHub account. If this is your first time, you will be
|
||||
asked to authorize and then are redirected to the catalog page if all is well.
|
||||
|
||||
For more information you can clone
|
||||
[the backstage-auth-example repository](https://github.com/RoadieHQ/backstage-auth-example).
|
||||
Each authentication setting is set up there on a branch named after the
|
||||
authentication provider.
|
||||
|
||||
# Where to go from here
|
||||
|
||||
> You're probably eager to write your first custom plugin. Follow this next
|
||||
> tutorial for an in-depth look at a custom GitHub repository browser plugin.
|
||||
> [Adding Custom Plugin to Existing Monorepo App](quickstart-app-plugin.md).
|
||||
@@ -35,8 +35,8 @@ title: Adding Custom Plugin to Existing Monorepo App
|
||||
1. When the process finishes, let's start the backend:
|
||||
`yarn --cwd packages/backend start`
|
||||
1. If you see errors starting, refer to
|
||||
[Auth Configuration](https://backstage.io/docs/tutorials/quickstart-app-auth#the-auth-configuration)
|
||||
for more information on environment variables.
|
||||
[Auth Configuration](https://backstage.io/docs/auth/) for more information on
|
||||
environment variables.
|
||||
1. And now the frontend, from a new terminal window and the root of your
|
||||
project: `yarn start`
|
||||
1. As usual, a browser window should popup loading the App.
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
registry=https://registry.npmjs.org/
|
||||
engine-strict=true
|
||||
@@ -0,0 +1,135 @@
|
||||
---
|
||||
title: Where do you start when adopting Backstage?
|
||||
author: Austin Lamon, Spotify
|
||||
authorURL: https://www.linkedin.com/in/austinlamon
|
||||
---
|
||||
|
||||

|
||||
|
||||
One of the greatest strengths of Backstage also presents a never-ending challenge: Backstage is highly customizable and allows you to easily build a unique developer portal suited to your organization’s needs. The downside of this flexibility is that it can be hard to know where to start. Backstage can do so many things — integrating every part of your tech infrastructure and developer experience — but if you set off building a developer portal without a plan, it’s easy to get overwhelmed by all the possibilities. To help you form your plan, this post will detail how Spotify came to design our internal portal and recommend potential models for you to use when designing and building your own.
|
||||
|
||||
<!--truncate-->
|
||||
|
||||
## Infrastructure as tech culture
|
||||
|
||||
Before providing recommendations on getting started with Backstage, it’s helpful to have a bit of context as to why Spotify made the design decisions we did. No two companies are identical — and thus, no two Backstage implementations are the same.
|
||||
|
||||
Rolling back the clock just a few years, [Spotify was challenged](https://engineering.atspotify.com/2021/05/18/a-product-story-the-lessons-of-backstage-and-spotifys-autonomous-culture/) to continue to scale our engineering team (and the number of features and components built) but retain the speed of product development. Some user research with Spotify developers highlighted a clear problem: there was simply too much non-documented institutional knowledge needed to get things done. No one could find anything and everyone was interrupting everyone else trying to figure things out.
|
||||
|
||||
Spotify’s developers were facing three big challenges on a daily basis:
|
||||
|
||||
- They not only needed to build software quickly, they also needed to pass along knowledge to new joiners about how best to create new components.
|
||||
- They needed to somehow maintain a mental model of the systems their squad owned. (Or, if they were lucky, they found a hopefully-up-to-date spreadsheet tracking this information.)
|
||||
- They needed to keep an eye on what squads around them might be building to ensure they could reuse systems when they needed to solve similar problems in the future.
|
||||
|
||||
In short, Spotify developers needed to continue building industry leading features at breakneck speed, while simultaneously maintaining a mental model for all the software at Spotify (oh, and help every new joiner develop that mental model as well!).
|
||||
<br>
|
||||
|
||||
## Three jobs: Create, manage, explore
|
||||
|
||||
Around the same time, the [jobs to be done](https://hbr.org/2016/09/know-your-customers-jobs-to-be-done) framework was becoming popular and luckily, a few Spotifiers helped guide the vision for a _sense-making tool for developers_ toward using it. After user research and many failed attempts, we landed on three jobs Spotify developers needed to do consistently:
|
||||
<br>
|
||||
|
||||
- **Create**: Spotify developers want to delight their customers with incredible features. They create new software to do that.
|
||||
- **Manage**: Spotify developers are proud of their work and treat their software and data like products. That requires maintaining all the software they own on an ongoing basis.
|
||||
- **Explore**: Spotify developers want to solve new, yet unsolved problems. They try to build on existing systems to help them do that.
|
||||
|
||||
So: make software, maintain the software you own throughout its lifecycle, and integrate with other people’s software.
|
||||
|
||||
Within today’s complex development environments, there are barriers both big and small that get in the way of those three jobs. Backstage provides the building blocks for removing those barriers, streamlining your development cycle, and letting developers do what they really want to do: build great features. Let’s take a closer look at each of these jobs.
|
||||
|
||||

|
||||
|
||||
### Create
|
||||
|
||||
**Job:** You’re an engineer, ready to start building a new microservice. Do you just pick whatever framework you want? How do you reserve capacity to run your service in production? What about managing CI/CD?
|
||||
|
||||
**Tool:** At Spotify, we use **Backstage Software Templates** to simplify all of this, reducing time–to–Hello World to just a few clicks. Instead of researching Spring Boot versus Helidon, opening a Jira ticket, rummaging through docs, and configuring CI automations, you just choose a template and your project is automatically set up in the repo for you, with the CI already running your first build.
|
||||
|
||||
**Result:** By making it easier to start new projects, your engineers get to the good part of coding features faster. And your organization’s best practices are built into the templates, encouraging standards and reducing complexity in your tech ecosystem.
|
||||
|
||||

|
||||
|
||||
### Manage
|
||||
|
||||
**Job:** You’re on a small team that owns a dozen services. Whenever you update and deploy those services, you’re switching between your CI, the AWS console, a security dashboard, and a CLI so you can try to figure out which Kubernetes cluster your service ended up on. In other words, you have a lot of open windows and tabs, and each step means switching to a new interface.
|
||||
|
||||
**Tool:** All of your team’s software components are organized together on one page in the **Backstage Service Catalog**. Go to any service’s page from there and its CI/CD status, [Kubernetes deployment status](https://backstage.io/blog/2021/01/12/new-backstage-feature-kubernetes-for-service-owners), documentation, security checks — and everything else related to that service — is grouped together in one seamless interface that shows you only the info you want.
|
||||
|
||||
**Result**: One page in Backstage has everything you need to manage the software you own. No more context-switching. No more digging through your cloud provider’s obscure admin features. Outside the repo and your IDE, everything you need to manage your service is right inside Backstage.
|
||||
|
||||

|
||||
|
||||
### Explore
|
||||
|
||||
**Job:** You're building a new mobile feature that needs to ensure a user is paying for the premium version of your product — but someone must’ve already built a library that handles that, right? A company-wide email and a few calls for help on Slack yield no response, so you resign yourself to building the capability yourself. Turns out someone did build the library you needed. They were just on vacation so they didn’t see your messages. How do you enable better discovery and collaboration across your org?
|
||||
|
||||
**Tools:** At Spotify, anyone can find everyone else’s software — because everything is centralized inside Backstage, organized by the **Backstage Service Catalog** and accessible by **search**. Go to any library or services page, and you’ll find the owners and documentation, even its API and how to extend it if need be.
|
||||
|
||||
**Result:** One place for everything, one place to search. Developers can more easily share components, build on top of each other’s work, and discover tools, libraries, frameworks, documentation, system designs, org charts, and more.
|
||||
|
||||
## Sounds great. Where do I start?
|
||||
|
||||
After talking with companies who have already adopted Backstage, we’ve seen a few common strategies for getting started. The different strategies are based on the size of your engineering org (which often also corresponds with how fast you’re growing).
|
||||
|
||||

|
||||
<br>
|
||||
|
||||
### My org has ~200 engineers (and is growing fast)
|
||||
|
||||
You’re big enough to start feeling the pain, and only getting bigger. Onboarding and discoverability are your biggest challenges.
|
||||
|
||||
**Pain points:**
|
||||
|
||||
- This size seems to be the tipping point — where complexity is taking hold, collaboration starts breaking down, and ad hoc solutions stop working.
|
||||
- Often this is also when you’re growing so fast (doubling in size every 6–12 months) that there are now more new engineers than old engineers.
|
||||
- New engineers can’t find anything, so they ask around, which pulls all your other engineers off-task with interruptions.
|
||||
- Logjams form. One company told us how it was taking 3–4 days for pull requests to get merged.
|
||||
|
||||
**Recommendation — Explore, then create:**
|
||||
|
||||
- New engineers need an easy way to find out how to do things, so you’re not just adding bodies, you’re adding happy, productive contributors.
|
||||
- To streamline onboarding, start with centralizing your documentation and making your tools and software components discoverable in Backstage.
|
||||
- At this size, you might not have a dedicated platform/infra team in place yet, but Backstage can provide the framework for centralizing and sharing knowledge — from managing compliance requirements to finding the right API documentation.
|
||||
- This allows both new and old engineers to collaborate more efficiently, easily discover best practices, and cuts down on duplicated work (e.g., a new team doesn’t end up rebuilding a database that already exists but nobody can find).
|
||||
|
||||

|
||||
|
||||
### My org has ~1,000 engineers
|
||||
|
||||
You’re officially big. Lots and lots of teams are managing lots and lots of software — and the frustration of switching between all the various tools to do that is growing exponentially.
|
||||
|
||||
**Pain points:**
|
||||
|
||||
- Fragmentation and entropy are real threats to productivity. From security requirements to cluster management to a thousand data endpoints, there’s too much to keep track of, leading to cognitive overload.
|
||||
- A death by a thousand cuts: constantly logging into new interfaces — from your cloud provider’s console to some brand new security tool then back to your CI/CD — is bogging your engineers down with too much context-switching and a lot of noise.
|
||||
- Every day, it’s getting more and more difficult for one team to manage their own microservices, data, and documentation, let alone share their knowledge with other teams.
|
||||
|
||||
**Recommendation — Manage, then explore, then create:**
|
||||
|
||||
- Backstage will allow your teams to get a handle on the software they own, since everything they need to manage it is in one place.
|
||||
- From CI/CD status to documentation to deciphering a monorepo, Backstage makes it easy to manage a service (or other software component) on a day-to-day basis.
|
||||
- The service catalog also helps your developers visualize your existing software ecosystem, beyond the software they own. And with Backstage Software Templates, every new software component is already added to the catalog.
|
||||
- Even at this scale, a small platform team should be all it takes to build and maintain your own version of Backstage. At Spotify, we have a 4-person team responsible for our internal version of Backstage, which is used by all of Spotify’s 1,600+ developers.
|
||||
|
||||

|
||||
|
||||
### My org has 1,000+ engineers
|
||||
|
||||
Integrating infrastructure of this size and complexity can seem overwhelming. It’s an even bigger challenge to bring this level of change to a well-established culture with ingrained processes.
|
||||
|
||||
**Pain points:**
|
||||
|
||||
- When you’re this large, you’ve incorporated a lot of technology and processes, as well as a lot of partners, each with their own technologies and processes.
|
||||
- You’re focussed on “replacing cruft” and bringing discoverability and order to your vast ecosystem of components and tools.
|
||||
- Getting your tools adopted by your engineers while modernizing your tech stack and coordinating with your infra teams to improve your engineering practices across the whole company… it’s a lot.
|
||||
|
||||
**Recommendation — Create, then manage, then explore:**
|
||||
|
||||
- The fastest way to bring change to your ecosystem is to start at the beginning of the chain with Backstage Software Templates.
|
||||
- With every new component created with your templates, you’re establishing best practices and rewarding your developers with a streamlined experience focused on their needs — all the while building up your new service catalog.
|
||||
- The more the templates ease the process of starting up a project, the more your engineers will adopt them, and the faster the other benefits of Backstage will build up, transforming productivity across your organization. ([That’s how we did it at Spotify](https://open.spotify.com/episode/7iuQ3ew1Wwpuiq6LbBKzCl).)
|
||||
|
||||
## More questions about adopting Backstage?
|
||||
|
||||
[Contact the Backstage team at Spotify.](https://calendly.com/spotify-backstage) We’ll share more about what we’ve learned from our experience here at Spotify — and from other companies who are already using Backstage to transform their developer experience.
|
||||
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 795 KiB |
|
After Width: | Height: | Size: 214 KiB |
|
After Width: | Height: | Size: 266 KiB |
|
After Width: | Height: | Size: 314 KiB |
@@ -85,7 +85,7 @@ class Footer extends React.Component {
|
||||
</div>
|
||||
</section>
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
<a href="https://spotify.github.io">Made with ❤️ at Spotify</a>
|
||||
<a href="https://spotify.github.io">Made with ❤️ at Spotify</a>
|
||||
</p>
|
||||
<p className="copyright">{this.props.config.copyright}</p>
|
||||
</footer>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Cortex Service Quality Scorecards
|
||||
author: Cortex
|
||||
authorUrl: https://www.getcortexapp.com
|
||||
category: Monitoring
|
||||
description: Grade the quality of your Backstage services using Scorecards. Automate production readiness, migrations, security audits, and more with CQL (Cortex Query Language).
|
||||
documentation: https://github.com/cortexapps/backstage-plugin
|
||||
iconUrl: img/cortex.png
|
||||
npmPackageName: '@cortexapps/backstage-plugin'
|
||||
tags:
|
||||
- web
|
||||
- monitoring
|
||||
- sre
|
||||
@@ -12,13 +12,15 @@
|
||||
"write-translations": "docusaurus-write-translations",
|
||||
"version": "docusaurus-version",
|
||||
"rename-version": "docusaurus-rename-version",
|
||||
"verify:sidebars": "node ./scripts/verify-sidebars"
|
||||
"verify:sidebars": "node ./scripts/verify-sidebars",
|
||||
"lock:check": "yarn-lock-check"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@spotify/prettier-config": "^10.0.0",
|
||||
"docusaurus": "^2.0.0-alpha.70",
|
||||
"js-yaml": "^4.1.0",
|
||||
"prettier": "^2.3.0"
|
||||
"prettier": "^2.3.1",
|
||||
"yarn-lock-check": "^1.0.4"
|
||||
},
|
||||
"prettier": "@spotify/prettier-config"
|
||||
}
|
||||
|
||||
@@ -18,12 +18,6 @@ const Background = props => {
|
||||
<Block.Container style={{ justifyContent: 'flex-start' }}>
|
||||
<Block.TextBox>
|
||||
<Block.Title>See us in action</Block.Title>
|
||||
<Block.Paragraph>
|
||||
To explore the UI and basic features of Backstage firsthand, go
|
||||
to: <a href="https://demo.backstage.io">demo.backstage.io</a>.
|
||||
(Tip: click “All” to view all the example components in the
|
||||
service catalog.)
|
||||
</Block.Paragraph>
|
||||
<Block.Paragraph>
|
||||
Watch the videos below to get an introduction to Backstage and to
|
||||
see how we use different plugins to customize{' '}
|
||||
@@ -32,13 +26,31 @@ const Background = props => {
|
||||
</a>
|
||||
.
|
||||
</Block.Paragraph>
|
||||
<Block.Paragraph>
|
||||
To see how other companies have already started using Backstage,
|
||||
watch these presentations from{' '}
|
||||
<a href="https://youtu.be/rRphwXeq33Q?t=1508">Expedia</a>,{' '}
|
||||
<a href="https://youtu.be/6sg5uMCLxTA?t=153">Zalando</a>, and{' '}
|
||||
<a href="https://youtu.be/UZTVjv-AvZA?t=188">TELUS</a>. For more,
|
||||
join our{' '}
|
||||
<a href="https://github.com/backstage/community">
|
||||
Community Sessions
|
||||
</a>
|
||||
.
|
||||
</Block.Paragraph>
|
||||
<Block.Paragraph>
|
||||
To explore the UI and basic features of Backstage firsthand, go
|
||||
to: <a href="https://demo.backstage.io">demo.backstage.io</a>.
|
||||
(Tip: click “All” to view all the example components in the
|
||||
service catalog.)
|
||||
</Block.Paragraph>
|
||||
</Block.TextBox>
|
||||
<Block.Graphics>
|
||||
<Block.Graphic
|
||||
x={-7}
|
||||
y={-12}
|
||||
width={120}
|
||||
src={`${baseUrl}img/demo-illustration.svg`}
|
||||
src={`${baseUrl}img/demo-screen.png`}
|
||||
/>
|
||||
</Block.Graphics>
|
||||
</Block.Container>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"features/software-catalog/well-known-statuses",
|
||||
"features/software-catalog/extending-the-model",
|
||||
"features/software-catalog/external-integrations",
|
||||
"features/software-catalog/catalog-customization",
|
||||
"features/software-catalog/software-catalog-api"
|
||||
]
|
||||
},
|
||||
@@ -66,7 +67,8 @@
|
||||
"features/software-templates/writing-templates",
|
||||
"features/software-templates/builtin-actions",
|
||||
"features/software-templates/writing-custom-actions",
|
||||
"features/software-templates/template-legacy"
|
||||
"features/software-templates/template-legacy",
|
||||
"features/software-templates/migrating-from-v1alpha1-to-v1beta2"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -238,7 +240,6 @@
|
||||
],
|
||||
"Tutorials": [
|
||||
"tutorials/journey",
|
||||
"tutorials/quickstart-app-auth",
|
||||
"tutorials/quickstart-app-plugin",
|
||||
"tutorials/switching-sqlite-postgres"
|
||||
],
|
||||
|
||||
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 386 KiB |
@@ -9,6 +9,13 @@
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.0.0"
|
||||
|
||||
"@babel/code-frame@^7.0.0":
|
||||
version "7.12.13"
|
||||
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658"
|
||||
integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.12.13"
|
||||
|
||||
"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11":
|
||||
version "7.12.11"
|
||||
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
|
||||
@@ -220,6 +227,11 @@
|
||||
resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
|
||||
integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.14.0":
|
||||
version "7.14.0"
|
||||
resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288"
|
||||
integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==
|
||||
|
||||
"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11":
|
||||
version "7.12.11"
|
||||
resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f"
|
||||
@@ -253,6 +265,15 @@
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/highlight@^7.12.13":
|
||||
version "7.14.0"
|
||||
resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf"
|
||||
integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.14.0"
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7":
|
||||
version "7.12.11"
|
||||
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79"
|
||||
@@ -911,7 +932,7 @@
|
||||
|
||||
"@spotify/prettier-config@^10.0.0":
|
||||
version "10.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@spotify/prettier-config/-/prettier-config-10.0.0.tgz#fa076d98d2e7e6c53dd3d86a696307a7010bd056"
|
||||
resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-10.0.0.tgz#fa076d98d2e7e6c53dd3d86a696307a7010bd056"
|
||||
integrity sha512-VYOdo8P7lIScAkl02nB9KpUAuOYMManryBIBuKJkAw5D3aVtLobfmdIKvdV6MqEmGMEQPbn7w/UpnjJYhUH+IA==
|
||||
|
||||
"@types/cheerio@^0.22.8":
|
||||
@@ -921,16 +942,39 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/glob@^7.1.3":
|
||||
version "7.1.3"
|
||||
resolved "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
|
||||
integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==
|
||||
dependencies:
|
||||
"@types/minimatch" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/minimatch@*":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21"
|
||||
integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==
|
||||
|
||||
"@types/node@*":
|
||||
version "14.14.20"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz#f7974863edd21d1f8a494a73e8e2b3658615c340"
|
||||
integrity sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==
|
||||
|
||||
"@types/node@^15.6.1":
|
||||
version "15.9.0"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-15.9.0.tgz#0b7f6c33ca5618fe329a9d832b478b4964d325a8"
|
||||
integrity sha512-AR1Vq1Ei1GaA5FjKL5PBqblTZsL5M+monvGSZwe6sSIdGiuu7Xr/pNwWJY+0ZQuN8AapD/XMB5IzBAyYRFbocA==
|
||||
|
||||
"@types/q@^1.5.1":
|
||||
version "1.5.4"
|
||||
resolved "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
|
||||
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
|
||||
|
||||
"@yarnpkg/lockfile@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"
|
||||
integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==
|
||||
|
||||
accepts@~1.3.7:
|
||||
version "1.3.7"
|
||||
resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
||||
@@ -1039,7 +1083,7 @@ argparse@^1.0.10, argparse@^1.0.7:
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
arr-diff@^4.0.0:
|
||||
@@ -1359,15 +1403,15 @@ browserslist@4.7.0:
|
||||
node-releases "^1.1.29"
|
||||
|
||||
browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.0:
|
||||
version "4.16.0"
|
||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.0.tgz#410277627500be3cb28a1bfe037586fbedf9488b"
|
||||
integrity sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==
|
||||
version "4.16.6"
|
||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2"
|
||||
integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001165"
|
||||
colorette "^1.2.1"
|
||||
electron-to-chromium "^1.3.621"
|
||||
caniuse-lite "^1.0.30001219"
|
||||
colorette "^1.2.2"
|
||||
electron-to-chromium "^1.3.723"
|
||||
escalade "^3.1.1"
|
||||
node-releases "^1.1.67"
|
||||
node-releases "^1.1.71"
|
||||
|
||||
buffer-alloc-unsafe@^1.1.0:
|
||||
version "1.1.0"
|
||||
@@ -1405,6 +1449,11 @@ buffer@^5.2.1:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
builtin-modules@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
|
||||
integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
|
||||
|
||||
bytes@1:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8"
|
||||
@@ -1498,10 +1547,10 @@ caniuse-api@^3.0.0:
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001165:
|
||||
version "1.0.30001173"
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001173.tgz#3c47bbe3cd6d7a9eda7f50ac016d158005569f56"
|
||||
integrity sha512-R3aqmjrICdGCTAnSXtNyvWYMK3YtV5jwudbq0T7nN9k4kmE4CBuwPqyJ+KBzepSTh0huivV2gLbSMEzTTmfeYw==
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001219:
|
||||
version "1.0.30001235"
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001235.tgz#ad5ca75bc5a1f7b12df79ad806d715a43a5ac4ed"
|
||||
integrity sha512-zWEwIVqnzPkSAXOUlQnPW2oKoYb2aLQ4Q5ejdjBcnH63rfypaW34CxaeBn1VMya2XaEU3P/R2qHpWyj+l0BT1A==
|
||||
|
||||
caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
@@ -1518,7 +1567,7 @@ caw@^2.0.0, caw@^2.0.1:
|
||||
tunnel-agent "^0.6.0"
|
||||
url-to-options "^1.0.1"
|
||||
|
||||
chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
|
||||
chalk@2.4.2, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
@@ -1697,10 +1746,10 @@ color@^3.0.0:
|
||||
color-convert "^1.9.1"
|
||||
color-string "^1.5.4"
|
||||
|
||||
colorette@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
|
||||
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
|
||||
colorette@^1.2.1, colorette@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
|
||||
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
@@ -1709,7 +1758,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.8.1:
|
||||
commander@^2.12.1, commander@^2.8.1:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
@@ -2181,6 +2230,11 @@ diacritics-map@^0.1.0:
|
||||
resolved "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz#6dfc0ff9d01000a2edf2865371cac316e94977af"
|
||||
integrity sha1-bfwP+dAQAKLt8oZTccrDFulJd68=
|
||||
|
||||
diff@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||
|
||||
dir-glob@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034"
|
||||
@@ -2355,10 +2409,10 @@ ee-first@1.1.1:
|
||||
resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
||||
|
||||
electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.621:
|
||||
version "1.3.634"
|
||||
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.634.tgz#82ea400f520f739c4f6ff00c1f7524827a917d25"
|
||||
integrity sha512-QPrWNYeE/A0xRvl/QP3E0nkaEvYUvH3gM04ZWYtIa6QlSpEetRlRI1xvQ7hiMIySHHEV+mwDSX8Kj4YZY6ZQAw==
|
||||
electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.723:
|
||||
version "1.3.749"
|
||||
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.749.tgz#0ecebc529ceb49dd2a7c838ae425236644c3439a"
|
||||
integrity sha512-F+v2zxZgw/fMwPz/VUGIggG4ZndDsYy0vlpthi3tjmDZlcfbhN5mYW0evXUsBr2sUtuDANFtle410A9u/sd/4A==
|
||||
|
||||
"emoji-regex@>=6.0.0 <=6.1.1":
|
||||
version "6.1.1"
|
||||
@@ -3049,6 +3103,18 @@ glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6, glob@~7.1.1:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.1.1, glob@^7.1.7:
|
||||
version "7.1.7"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
|
||||
integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
global-modules@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
|
||||
@@ -3460,6 +3526,11 @@ ini@^1.3.4, ini@^1.3.5:
|
||||
resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
|
||||
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
|
||||
|
||||
ini@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
|
||||
integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
|
||||
|
||||
inquirer@6.5.0:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42"
|
||||
@@ -3567,6 +3638,13 @@ is-core-module@^2.1.0:
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
is-core-module@^2.2.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
|
||||
integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
is-data-descriptor@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
|
||||
@@ -3864,7 +3942,7 @@ js-yaml@^3.13.1, js-yaml@^3.8.1:
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
@@ -4142,9 +4220,9 @@ lodash.uniq@^4.5.0:
|
||||
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
||||
|
||||
lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@~4.17.10:
|
||||
version "4.17.20"
|
||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||
version "4.17.21"
|
||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
logalot@^2.0.0:
|
||||
version "2.1.0"
|
||||
@@ -4379,7 +4457,7 @@ mixin-deep@^1.1.3, mixin-deep@^1.2.0:
|
||||
for-in "^1.0.2"
|
||||
is-extendable "^1.0.1"
|
||||
|
||||
mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1:
|
||||
mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
||||
@@ -4448,10 +4526,10 @@ node-modules-regexp@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
|
||||
integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
|
||||
|
||||
node-releases@^1.1.29, node-releases@^1.1.67:
|
||||
version "1.1.69"
|
||||
resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz#3149dbde53b781610cd8b486d62d86e26c3725f6"
|
||||
integrity sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==
|
||||
node-releases@^1.1.29, node-releases@^1.1.71:
|
||||
version "1.1.72"
|
||||
resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe"
|
||||
integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==
|
||||
|
||||
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
|
||||
version "2.5.0"
|
||||
@@ -5197,10 +5275,10 @@ prepend-http@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
|
||||
integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
|
||||
|
||||
prettier@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18"
|
||||
integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==
|
||||
prettier@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz#76903c3f8c4449bc9ac597acefa24dc5ad4cbea6"
|
||||
integrity sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==
|
||||
|
||||
prismjs@^1.22.0:
|
||||
version "1.23.0"
|
||||
@@ -5603,6 +5681,14 @@ resolve@^1.1.6, resolve@^1.10.0:
|
||||
is-core-module "^2.1.0"
|
||||
path-parse "^1.0.6"
|
||||
|
||||
resolve@^1.3.2:
|
||||
version "1.20.0"
|
||||
resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
|
||||
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
|
||||
dependencies:
|
||||
is-core-module "^2.2.0"
|
||||
path-parse "^1.0.6"
|
||||
|
||||
responselike@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
|
||||
@@ -6351,11 +6437,37 @@ truncate-html@^1.0.3:
|
||||
"@types/cheerio" "^0.22.8"
|
||||
cheerio "0.22.0"
|
||||
|
||||
tslib@^1.9.0, tslib@^1.9.3:
|
||||
tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslint@^6.1.3:
|
||||
version "6.1.3"
|
||||
resolved "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904"
|
||||
integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
builtin-modules "^1.1.1"
|
||||
chalk "^2.3.0"
|
||||
commander "^2.12.1"
|
||||
diff "^4.0.1"
|
||||
glob "^7.1.1"
|
||||
js-yaml "^3.13.1"
|
||||
minimatch "^3.0.4"
|
||||
mkdirp "^0.5.3"
|
||||
resolve "^1.3.2"
|
||||
semver "^5.3.0"
|
||||
tslib "^1.13.0"
|
||||
tsutils "^2.29.0"
|
||||
|
||||
tsutils@^2.29.0:
|
||||
version "2.29.0"
|
||||
resolved "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
|
||||
integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
|
||||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
tunnel-agent@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
|
||||
@@ -6381,6 +6493,11 @@ typedarray@^0.0.6:
|
||||
resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805"
|
||||
integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==
|
||||
|
||||
unbzip2-stream@^1.0.9:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7"
|
||||
@@ -6650,6 +6767,19 @@ yargs@^2.3.0:
|
||||
dependencies:
|
||||
wordwrap "0.0.2"
|
||||
|
||||
yarn-lock-check@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmjs.org/yarn-lock-check/-/yarn-lock-check-1.0.4.tgz#a0373de051be0c8442d8933070df7a45595263b4"
|
||||
integrity sha512-Gj0wRN85c4OPZUlE7WsQ0a1COv38uyeWWR0YAvJr2Vxw1f32bwK19xySjUZlxt9o4QopJkd8g6x6CLv81OHwYg==
|
||||
dependencies:
|
||||
"@types/glob" "^7.1.3"
|
||||
"@types/node" "^15.6.1"
|
||||
"@yarnpkg/lockfile" "^1.1.0"
|
||||
glob "^7.1.7"
|
||||
ini "^2.0.0"
|
||||
tslint "^6.1.3"
|
||||
typescript "^4.3.2"
|
||||
|
||||
yauzl@^2.4.2:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
|
||||
|
||||
@@ -40,6 +40,7 @@ nav:
|
||||
- Well-known Statuses: 'features/software-catalog/well-known-statuses.md'
|
||||
- Extending the model: 'features/software-catalog/extending-the-model.md'
|
||||
- External integrations: 'features/software-catalog/external-integrations.md'
|
||||
- Catalog Customization: 'features/software-catalog/catalog-customization.md'
|
||||
- API: 'features/software-catalog/api.md'
|
||||
- Kubernetes:
|
||||
- Overview: 'features/kubernetes/index.md'
|
||||
@@ -54,6 +55,8 @@ nav:
|
||||
- Builtin Actions: 'features/software-templates/builtin-actions.md'
|
||||
- Writing Custom Actions: 'features/software-templates/writing-custom-actions.md'
|
||||
- Writing Templates (Legacy): 'features/software-templates/legacy.md'
|
||||
- Migrating from v1alpha1 to v1beta2 templates: 'features/software-templates/migrating-from-v1alpha1-to-v1beta2.md'
|
||||
|
||||
- Backstage Search:
|
||||
- Overview: 'features/search/README.md'
|
||||
- Search Architecture: 'features/search/architecture.md'
|
||||
@@ -152,7 +155,6 @@ nav:
|
||||
- Backend: 'api/backend.md'
|
||||
- Tutorials:
|
||||
- Future developer journey: 'tutorials/journey.md'
|
||||
- Monorepo App Setup With Authentication: 'tutorials/quickstart-app-auth.md'
|
||||
- Adding Custom Plugin to Existing Monorepo App: 'tutorials/quickstart-app-plugin.md'
|
||||
- Switching Backstage from SQLite to PostgreSQL: 'tutorials/switching-sqlite-postgres.md'
|
||||
- Architecture Decision Records (ADRs):
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
"lerna": "lerna",
|
||||
"storybook": "yarn workspace storybook start",
|
||||
"build-storybook": "yarn workspace storybook build-storybook",
|
||||
"prepare": "husky install"
|
||||
"prepare": "husky install",
|
||||
"lock:check": "yarn-lock-check"
|
||||
},
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
@@ -49,24 +50,25 @@
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@microsoft/api-extractor": "7.13.2-pr1916.0",
|
||||
"@microsoft/api-documenter": "^7.12.16",
|
||||
"@microsoft/api-extractor": "7.13.2-pr1916.0",
|
||||
"@microsoft/api-extractor-model": "^7.12.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.14.0",
|
||||
"@octokit/openapi-types": "^2.2.0",
|
||||
"@spotify/eslint-config-oss": "^1.0.1",
|
||||
"@spotify/prettier-config": "^9.0.0",
|
||||
"@spotify/prettier-config": "^10.0.0",
|
||||
"command-exists": "^1.2.9",
|
||||
"concurrently": "^6.0.0",
|
||||
"eslint-plugin-notice": "^0.9.10",
|
||||
"fs-extra": "^9.0.0",
|
||||
"husky": "^6.0.0",
|
||||
"lerna": "^4.0.0",
|
||||
"lint-staged": "^10.1.0",
|
||||
"prettier": "^2.2.1",
|
||||
"recursive-readdir": "^2.2.2",
|
||||
"shx": "^0.3.2"
|
||||
"shx": "^0.3.2",
|
||||
"yarn-lock-check": "^1.0.4"
|
||||
},
|
||||
"prettier": "@spotify/prettier-config",
|
||||
"lint-staged": {
|
||||
|
||||
@@ -1,5 +1,111 @@
|
||||
# example-app
|
||||
|
||||
## 0.2.31
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [497f4ce18]
|
||||
- Updated dependencies [ee4eb5b40]
|
||||
- Updated dependencies [84160313e]
|
||||
- Updated dependencies [3772de8ba]
|
||||
- Updated dependencies [7e7c71417]
|
||||
- Updated dependencies [f430b6c6f]
|
||||
- Updated dependencies [2a942cc9e]
|
||||
- Updated dependencies [e7c5e4b30]
|
||||
- Updated dependencies [ebe802bc4]
|
||||
- Updated dependencies [1cf1d351f]
|
||||
- Updated dependencies [90a505a77]
|
||||
- Updated dependencies [76f99a1a0]
|
||||
- Updated dependencies [deaba2e13]
|
||||
- Updated dependencies [1157fa307]
|
||||
- Updated dependencies [8e919a6f8]
|
||||
- Updated dependencies [2305ab8fc]
|
||||
- Updated dependencies [054bcd029]
|
||||
- Updated dependencies [aad98c544]
|
||||
- Updated dependencies [f46a9e82d]
|
||||
- @backstage/plugin-scaffolder@0.9.7
|
||||
- @backstage/cli@0.6.14
|
||||
- @backstage/plugin-catalog@0.6.1
|
||||
- @backstage/theme@0.2.8
|
||||
- @backstage/catalog-model@0.8.1
|
||||
- @backstage/core@0.7.12
|
||||
- @backstage/plugin-tech-radar@0.4.0
|
||||
- @backstage/plugin-catalog-react@0.2.1
|
||||
- @backstage/plugin-techdocs@0.9.5
|
||||
|
||||
## 0.2.30
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [41c3ec421]
|
||||
- Updated dependencies [add62a455]
|
||||
- Updated dependencies [cc592248b]
|
||||
- Updated dependencies [17c497b81]
|
||||
- Updated dependencies [1cd0cacd9]
|
||||
- Updated dependencies [4ea9df9d3]
|
||||
- Updated dependencies [7a7da5146]
|
||||
- Updated dependencies [5baf2ff0f]
|
||||
- Updated dependencies [bf805b467]
|
||||
- Updated dependencies [203ce6f6f]
|
||||
- Updated dependencies [7ab5bfe68]
|
||||
- Updated dependencies [704875e26]
|
||||
- Updated dependencies [3a181cff1]
|
||||
- @backstage/plugin-cost-insights@0.10.1
|
||||
- @backstage/catalog-model@0.8.0
|
||||
- @backstage/core@0.7.11
|
||||
- @backstage/plugin-catalog@0.6.0
|
||||
- @backstage/plugin-catalog-react@0.2.0
|
||||
- @backstage/cli@0.6.13
|
||||
- @backstage/plugin-techdocs@0.9.4
|
||||
- @backstage/plugin-jenkins@0.4.4
|
||||
- @backstage/plugin-api-docs@0.4.15
|
||||
- @backstage/plugin-badges@0.2.2
|
||||
- @backstage/plugin-catalog-import@0.5.8
|
||||
- @backstage/plugin-circleci@0.2.15
|
||||
- @backstage/plugin-cloudbuild@0.2.16
|
||||
- @backstage/plugin-code-coverage@0.1.4
|
||||
- @backstage/plugin-explore@0.3.6
|
||||
- @backstage/plugin-github-actions@0.4.8
|
||||
- @backstage/plugin-kafka@0.2.8
|
||||
- @backstage/plugin-kubernetes@0.4.5
|
||||
- @backstage/plugin-lighthouse@0.2.17
|
||||
- @backstage/plugin-org@0.3.14
|
||||
- @backstage/plugin-pagerduty@0.3.5
|
||||
- @backstage/plugin-rollbar@0.3.6
|
||||
- @backstage/plugin-scaffolder@0.9.6
|
||||
- @backstage/plugin-search@0.3.7
|
||||
- @backstage/plugin-sentry@0.3.11
|
||||
- @backstage/plugin-todo@0.1.2
|
||||
|
||||
## 0.2.29
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [7cbfcae48]
|
||||
- Updated dependencies [2bfec55a6]
|
||||
- Updated dependencies [f7f7783a3]
|
||||
- Updated dependencies [65e6c4541]
|
||||
- Updated dependencies [68fdbf014]
|
||||
- Updated dependencies [5da6a561d]
|
||||
- Updated dependencies [ca6e0ab69]
|
||||
- Updated dependencies [5914a76d5]
|
||||
- Updated dependencies [81d7b9c6f]
|
||||
- Updated dependencies [a62cfe068]
|
||||
- Updated dependencies [35e091604]
|
||||
- Updated dependencies [a53f3d603]
|
||||
- Updated dependencies [b203699e9]
|
||||
- @backstage/plugin-cost-insights@0.10.0
|
||||
- @backstage/cli@0.6.12
|
||||
- @backstage/catalog-model@0.7.10
|
||||
- @backstage/plugin-scaffolder@0.9.5
|
||||
- @backstage/core@0.7.10
|
||||
- @backstage/plugin-api-docs@0.4.14
|
||||
- @backstage/plugin-cloudbuild@0.2.15
|
||||
- @backstage/plugin-github-actions@0.4.7
|
||||
- @backstage/plugin-techdocs@0.9.3
|
||||
- @backstage/plugin-catalog-import@0.5.7
|
||||
- @backstage/plugin-catalog@0.5.8
|
||||
|
||||
## 0.2.28
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const API_ENDPOINT = 'http://localhost:7000/api/search/query';
|
||||
|
||||
describe('SearchPage', () => {
|
||||
describe('Given a search context with a term, results, and filter values', () => {
|
||||
it('The results are rendered as expected', () => {
|
||||
const results = [
|
||||
{
|
||||
type: 'software-catalog',
|
||||
document: {
|
||||
title: 'backstage',
|
||||
text: 'Backstage system documentation',
|
||||
location: '/result/location/path',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
cy.enterAsGuest();
|
||||
cy.visit('/search-next', {
|
||||
onBeforeLoad(win) {
|
||||
cy.stub(win, 'fetch')
|
||||
.withArgs(`${API_ENDPOINT}?term=&pageCursor=`)
|
||||
.resolves({
|
||||
ok: true,
|
||||
json: () => ({ results }),
|
||||
});
|
||||
},
|
||||
});
|
||||
cy.contains('Search');
|
||||
|
||||
cy.contains(results[0].document.title);
|
||||
cy.contains(results[0].document.text);
|
||||
cy.get(`a[href="${results[0].document.location}"]`).should('be.visible');
|
||||
});
|
||||
|
||||
it('The filters are rendered as expected', () => {
|
||||
cy.enterAsGuest();
|
||||
cy.visit(
|
||||
'/search-next?filters%5Bkind%5D=Component&filters%5Blifecycle%5D%5B%5D=experimental',
|
||||
{
|
||||
onBeforeLoad(win) {
|
||||
cy.stub(win, 'fetch')
|
||||
.withArgs(
|
||||
`${API_ENDPOINT}?term=&filters%5Bkind%5D=Component&filters%5Blifecycle%5D%5B0%5D=experimental&pageCursor=`,
|
||||
)
|
||||
.resolves({
|
||||
ok: true,
|
||||
json: () => ({ results: [] }),
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
cy.contains('Search');
|
||||
|
||||
// lifecycle
|
||||
cy.contains('lifecycle');
|
||||
|
||||
cy.contains('experimental');
|
||||
cy.get(
|
||||
'[data-testid="search-checkboxfilter-next"] input[value="experimental"]',
|
||||
).should('have.attr', 'checked');
|
||||
|
||||
cy.contains('production');
|
||||
cy.get(
|
||||
'[data-testid="search-checkboxfilter-next"] input[value="production"]',
|
||||
).should('not.have.attr', 'checked');
|
||||
|
||||
// kind
|
||||
cy.contains('kind');
|
||||
cy.get(
|
||||
'[data-testid="search-selectfilter-next"] [role="button"][aria-haspopup="listbox"]',
|
||||
).click();
|
||||
|
||||
cy.contains('All');
|
||||
cy.contains('Template');
|
||||
cy.contains('Component');
|
||||
|
||||
cy.get('[role="option"][data-value="Component"]').should(
|
||||
'have.attr',
|
||||
'aria-selected',
|
||||
'true',
|
||||
);
|
||||
});
|
||||
|
||||
it('The search bar is rendered as expected', () => {
|
||||
cy.enterAsGuest();
|
||||
cy.visit('/search-next?query=backstage', {
|
||||
onBeforeLoad(win) {
|
||||
cy.stub(win, 'fetch')
|
||||
.withArgs(`${API_ENDPOINT}?term=backstage&pageCursor=`)
|
||||
.resolves({
|
||||
ok: true,
|
||||
json: () => ({ results: [] }),
|
||||
});
|
||||
},
|
||||
});
|
||||
cy.contains('Search');
|
||||
|
||||
cy.get('[data-testid="search-bar-next"] input').should(
|
||||
'have.attr',
|
||||
'value',
|
||||
'backstage',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
Cypress.Commands.add('enterAsGuest', () => {
|
||||
cy.visit('/');
|
||||
cy.get('button').contains('Enter').click();
|
||||
});
|
||||
@@ -14,3 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import '@testing-library/cypress/add-commands';
|
||||
import './commands';
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
{
|
||||
"name": "example-app",
|
||||
"version": "0.2.28",
|
||||
"version": "0.2.31",
|
||||
"private": true,
|
||||
"bundled": true,
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^0.7.9",
|
||||
"@backstage/cli": "^0.6.11",
|
||||
"@backstage/core": "^0.7.9",
|
||||
"@backstage/catalog-model": "^0.8.1",
|
||||
"@backstage/cli": "^0.6.14",
|
||||
"@backstage/core": "^0.7.12",
|
||||
"@backstage/integration-react": "^0.1.2",
|
||||
"@backstage/plugin-api-docs": "^0.4.13",
|
||||
"@backstage/plugin-badges": "^0.2.1",
|
||||
"@backstage/plugin-catalog": "^0.5.7",
|
||||
"@backstage/plugin-catalog-import": "^0.5.6",
|
||||
"@backstage/plugin-catalog-react": "^0.1.6",
|
||||
"@backstage/plugin-circleci": "^0.2.14",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.14",
|
||||
"@backstage/plugin-code-coverage": "^0.1.3",
|
||||
"@backstage/plugin-cost-insights": "^0.9.1",
|
||||
"@backstage/plugin-explore": "^0.3.5",
|
||||
"@backstage/plugin-api-docs": "^0.4.15",
|
||||
"@backstage/plugin-badges": "^0.2.2",
|
||||
"@backstage/plugin-catalog": "^0.6.1",
|
||||
"@backstage/plugin-catalog-import": "^0.5.8",
|
||||
"@backstage/plugin-catalog-react": "^0.2.1",
|
||||
"@backstage/plugin-circleci": "^0.2.15",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.16",
|
||||
"@backstage/plugin-code-coverage": "^0.1.4",
|
||||
"@backstage/plugin-cost-insights": "^0.10.1",
|
||||
"@backstage/plugin-explore": "^0.3.6",
|
||||
"@backstage/plugin-gcp-projects": "^0.2.6",
|
||||
"@backstage/plugin-github-actions": "^0.4.6",
|
||||
"@backstage/plugin-github-actions": "^0.4.8",
|
||||
"@backstage/plugin-graphiql": "^0.2.11",
|
||||
"@backstage/plugin-jenkins": "^0.4.3",
|
||||
"@backstage/plugin-kafka": "^0.2.7",
|
||||
"@backstage/plugin-kubernetes": "^0.4.4",
|
||||
"@backstage/plugin-lighthouse": "^0.2.16",
|
||||
"@backstage/plugin-jenkins": "^0.4.4",
|
||||
"@backstage/plugin-kafka": "^0.2.8",
|
||||
"@backstage/plugin-kubernetes": "^0.4.5",
|
||||
"@backstage/plugin-lighthouse": "^0.2.17",
|
||||
"@backstage/plugin-newrelic": "^0.2.7",
|
||||
"@backstage/plugin-org": "^0.3.13",
|
||||
"@backstage/plugin-pagerduty": "0.3.4",
|
||||
"@backstage/plugin-rollbar": "^0.3.5",
|
||||
"@backstage/plugin-scaffolder": "^0.9.4",
|
||||
"@backstage/plugin-search": "^0.3.6",
|
||||
"@backstage/plugin-sentry": "^0.3.10",
|
||||
"@backstage/plugin-org": "^0.3.14",
|
||||
"@backstage/plugin-pagerduty": "0.3.5",
|
||||
"@backstage/plugin-rollbar": "^0.3.6",
|
||||
"@backstage/plugin-scaffolder": "^0.9.7",
|
||||
"@backstage/plugin-search": "^0.3.7",
|
||||
"@backstage/plugin-sentry": "^0.3.11",
|
||||
"@backstage/plugin-shortcuts": "^0.1.2",
|
||||
"@backstage/plugin-tech-radar": "^0.3.11",
|
||||
"@backstage/plugin-techdocs": "^0.9.2",
|
||||
"@backstage/plugin-todo": "^0.1.1",
|
||||
"@backstage/plugin-tech-radar": "^0.4.0",
|
||||
"@backstage/plugin-techdocs": "^0.9.5",
|
||||
"@backstage/plugin-todo": "^0.1.2",
|
||||
"@backstage/plugin-user-settings": "^0.2.10",
|
||||
"@backstage/theme": "^0.2.7",
|
||||
"@backstage/theme": "^0.2.8",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
"@roadiehq/backstage-plugin-buildkite": "^1.0.0",
|
||||
"@roadiehq/backstage-plugin-github-insights": "^1.0.0",
|
||||
"@roadiehq/backstage-plugin-github-pull-requests": "^1.0.0",
|
||||
"@roadiehq/backstage-plugin-buildkite": "^1.0.3",
|
||||
"@roadiehq/backstage-plugin-github-insights": "^1.1.11",
|
||||
"@roadiehq/backstage-plugin-github-pull-requests": "^1.0.5",
|
||||
"@roadiehq/backstage-plugin-travis-ci": "^1.0.0",
|
||||
"history": "^5.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
@@ -56,7 +56,7 @@
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/test-utils": "^0.1.11",
|
||||
"@backstage/test-utils": "^0.1.13",
|
||||
"@testing-library/cypress": "^7.0.1",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^11.2.5",
|
||||
@@ -67,7 +67,7 @@
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"@types/zen-observable": "^0.8.0",
|
||||
"cross-env": "^7.0.0",
|
||||
"cypress": "^4.2.0",
|
||||
"cypress": "^7.3.0",
|
||||
"eslint-plugin-cypress": "^2.10.3",
|
||||
"start-server-and-test": "^1.10.11"
|
||||
},
|
||||
|
||||
@@ -54,6 +54,7 @@ import { Navigate, Route } from 'react-router';
|
||||
import { apis } from './apis';
|
||||
import { Root } from './components/Root';
|
||||
import { entityPage } from './components/catalog/EntityPage';
|
||||
import { searchPage } from './components/search/SearchPage';
|
||||
import { providers } from './identityProviders';
|
||||
import * as plugins from './plugins';
|
||||
|
||||
@@ -119,10 +120,9 @@ const routes = (
|
||||
<Route path="/gcp-projects" element={<GcpProjectsPage />} />
|
||||
<Route path="/newrelic" element={<NewRelicPage />} />
|
||||
<Route path="/search" element={<SearchPage />} />
|
||||
<Route
|
||||
path="/search-next"
|
||||
element={<SearchPageNext /* TODO: illustrate customization */ />}
|
||||
/>
|
||||
<Route path="/search-next" element={<SearchPageNext />}>
|
||||
{searchPage}
|
||||
</Route>
|
||||
<Route path="/cost-insights" element={<CostInsightsPage />} />
|
||||
<Route
|
||||
path="/cost-insights/investigating-growth"
|
||||
|
||||
@@ -44,6 +44,7 @@ describe('EntityPage Test', () => {
|
||||
getWorkflow: jest.fn(),
|
||||
getWorkflowRun: jest.fn(),
|
||||
reRunWorkflow: jest.fn(),
|
||||
listJobsForWorkflowRun: jest.fn(),
|
||||
downloadJobLogsForWorkflowRun: jest.fn(),
|
||||
} as jest.Mocked<typeof githubActionsApiRef.T>;
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ import {
|
||||
import { EntityBadgesDialog } from '@backstage/plugin-badges';
|
||||
import {
|
||||
EntityAboutCard,
|
||||
EntityDependsOnComponentsCard,
|
||||
EntityDependsOnResourcesCard,
|
||||
EntityHasComponentsCard,
|
||||
EntityHasSubcomponentsCard,
|
||||
EntityHasSystemsCard,
|
||||
@@ -37,6 +39,9 @@ import {
|
||||
EntitySwitch,
|
||||
isComponentType,
|
||||
isKind,
|
||||
EntityHasResourcesCard,
|
||||
EntityOrphanWarning,
|
||||
isOrphan,
|
||||
} from '@backstage/plugin-catalog';
|
||||
import {
|
||||
EntityCircleCIContent,
|
||||
@@ -211,7 +216,15 @@ const errorsContent = (
|
||||
|
||||
const overviewContent = (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isOrphan}>
|
||||
<Grid item xs={12}>
|
||||
<EntityOrphanWarning />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
<Grid item md={8} xs={12}>
|
||||
<EntityAboutCard variant="gridItem" />
|
||||
</Grid>
|
||||
|
||||
@@ -223,7 +236,7 @@ const overviewContent = (
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
<Grid item md={4} sm={6}>
|
||||
<Grid item md={4} xs={12}>
|
||||
<EntityLinksCard />
|
||||
</Grid>
|
||||
|
||||
@@ -257,7 +270,7 @@ const overviewContent = (
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
<Grid item md={6}>
|
||||
<Grid item md={8} xs={12}>
|
||||
<EntityHasSubcomponentsCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -288,6 +301,17 @@ const serviceEntityPage = (
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/dependencies" title="Dependencies">
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<EntityDependsOnComponentsCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityDependsOnResourcesCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
@@ -336,6 +360,17 @@ const websiteEntityPage = (
|
||||
{errorsContent}
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/dependencies" title="Dependencies">
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<Grid item md={6}>
|
||||
<EntityDependsOnComponentsCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityDependsOnResourcesCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
@@ -466,6 +501,9 @@ const systemPage = (
|
||||
<Grid item md={6}>
|
||||
<EntityHasApisCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityHasResourcesCard variant="gridItem" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
<EntityLayout.Route path="/diagram" title="Diagram">
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { makeStyles, Theme, Grid, List, Paper } from '@material-ui/core';
|
||||
|
||||
import { Content, Header, Lifecycle, Page } from '@backstage/core';
|
||||
import { CatalogResultListItem } from '@backstage/plugin-catalog';
|
||||
import {
|
||||
SearchBarNext as SearchBar,
|
||||
SearchFilterNext as SearchFilter,
|
||||
SearchResultNext as SearchResult,
|
||||
DefaultResultListItem,
|
||||
} from '@backstage/plugin-search';
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
bar: {
|
||||
padding: theme.spacing(1, 0),
|
||||
},
|
||||
filters: {
|
||||
padding: theme.spacing(2),
|
||||
},
|
||||
filter: {
|
||||
'& + &': {
|
||||
marginTop: theme.spacing(2.5),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const SearchPage = () => {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Page themeId="home">
|
||||
<Header title="Search" subtitle={<Lifecycle alpha />} />
|
||||
<Content>
|
||||
<Grid container direction="row">
|
||||
<Grid item xs={12}>
|
||||
<Paper className={classes.bar}>
|
||||
<SearchBar debounceTime={100} />
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<Paper className={classes.filters}>
|
||||
<SearchFilter.Select
|
||||
className={classes.filter}
|
||||
name="kind"
|
||||
values={['Component', 'Template']}
|
||||
/>
|
||||
<SearchFilter.Checkbox
|
||||
className={classes.filter}
|
||||
name="lifecycle"
|
||||
values={['experimental', 'production']}
|
||||
/>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<SearchResult>
|
||||
{({ results }) => (
|
||||
<List>
|
||||
{results.map(({ type, document }) => {
|
||||
switch (type) {
|
||||
case 'software-catalog':
|
||||
return (
|
||||
<CatalogResultListItem
|
||||
key={document.location}
|
||||
result={document}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<DefaultResultListItem
|
||||
key={document.location}
|
||||
result={document}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</List>
|
||||
)}
|
||||
</SearchResult>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export const searchPage = <SearchPage />;
|
||||
@@ -1,5 +1,30 @@
|
||||
# @backstage/backend-common
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- c7dad9218: All cache-related connection errors are now handled and logged by the cache manager. App Integrators may provide an optional error handler when instantiating the cache manager if custom error handling is needed.
|
||||
|
||||
```typescript
|
||||
// Providing an error handler
|
||||
const cacheManager = CacheManager.fromConfig(config, {
|
||||
onError: e => {
|
||||
if (isSomehowUnrecoverable(e)) {
|
||||
gracefullyShutThingsDown();
|
||||
process.exit(1);
|
||||
}
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
- 65e6c4541: Remove circular dependencies
|
||||
- 5001de908: Change GitlabUrlReader to SHA timestamp compare using only commits that modify given file path, if file path given
|
||||
- Updated dependencies [65e6c4541]
|
||||
- Updated dependencies [290405276]
|
||||
- @backstage/integration@0.5.3
|
||||
- @backstage/config-loader@0.6.2
|
||||
|
||||
## 0.8.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -73,7 +73,7 @@ export interface CacheClient {
|
||||
// @public
|
||||
export class CacheManager {
|
||||
forPlugin(pluginId: string): PluginCacheManager;
|
||||
static fromConfig(config: Config): CacheManager;
|
||||
static fromConfig(config: Config, options?: CacheManagerOptions): CacheManager;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-common",
|
||||
"description": "Common functionality library for Backstage backends",
|
||||
"version": "0.8.0",
|
||||
"version": "0.8.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -31,9 +31,9 @@
|
||||
"dependencies": {
|
||||
"@backstage/cli-common": "^0.1.1",
|
||||
"@backstage/config": "^0.1.5",
|
||||
"@backstage/config-loader": "^0.6.1",
|
||||
"@backstage/config-loader": "^0.6.2",
|
||||
"@backstage/errors": "^0.1.1",
|
||||
"@backstage/integration": "^0.5.2",
|
||||
"@backstage/integration": "^0.5.3",
|
||||
"@google-cloud/storage": "^5.8.0",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
"@types/cors": "^2.8.6",
|
||||
@@ -76,8 +76,8 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.6.11",
|
||||
"@backstage/test-utils": "^0.1.11",
|
||||
"@backstage/cli": "^0.6.12",
|
||||
"@backstage/test-utils": "^0.1.12",
|
||||
"@types/archiver": "^5.1.0",
|
||||
"@types/compression": "^1.7.0",
|
||||
"@types/concat-stream": "^1.6.0",
|
||||
|
||||
@@ -92,7 +92,8 @@ export class DefaultCacheClient implements CacheClient {
|
||||
const wellFormedKey = Buffer.from(candidateKey).toString('base64');
|
||||
|
||||
// Memcache in particular doesn't do well with keys > 250 bytes.
|
||||
if (wellFormedKey.length < 250) {
|
||||
// Padded because a plugin ID is also prepended to the key.
|
||||
if (wellFormedKey.length < 200) {
|
||||
return wellFormedKey;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,16 @@ describe('CacheManager', () => {
|
||||
expect(client).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('attaches error handler to client', () => {
|
||||
const pluginId = 'error-test';
|
||||
manager.forPlugin(pluginId).getClient();
|
||||
|
||||
const client = DefaultCacheClient as jest.Mock;
|
||||
const mockCalls = client.mock.calls.splice(-1);
|
||||
const realClient = mockCalls[0][0].client as Keyv;
|
||||
expect(realClient.on).toHaveBeenCalledWith('error', expect.any(Function));
|
||||
});
|
||||
|
||||
it('provides different plugins different cache clients', async () => {
|
||||
const plugin1Id = 'test1';
|
||||
const plugin2Id = 'test2';
|
||||
@@ -163,4 +173,53 @@ describe('CacheManager', () => {
|
||||
expect(mockMemcacheCalls[0][0]).toEqual(expectedHost);
|
||||
});
|
||||
});
|
||||
|
||||
describe('connection errors', () => {
|
||||
it('uses provided logger', () => {
|
||||
// Set up and inject mock logger.
|
||||
const mockLogger = { child: jest.fn(), error: jest.fn() };
|
||||
mockLogger.child.mockImplementation(() => mockLogger as any);
|
||||
const manager = CacheManager.fromConfig(defaultConfig(), {
|
||||
logger: mockLogger as any,
|
||||
});
|
||||
|
||||
// Set up a cache client using the configured manager.
|
||||
manager.forPlugin('error-logger-test').getClient();
|
||||
|
||||
// Retrieve the error handler attached to the cache client.
|
||||
const client = DefaultCacheClient as jest.Mock;
|
||||
const mockCalls = client.mock.calls.splice(-1);
|
||||
const realClient = mockCalls[0][0].client as Keyv;
|
||||
const realOnError = realClient.on as jest.Mock;
|
||||
const realHandler = realOnError.mock.calls.splice(-1)[0][1];
|
||||
|
||||
// Invoke the actual error handler.
|
||||
const expectedError = new Error('some error');
|
||||
realHandler(expectedError);
|
||||
expect(mockLogger.error).toHaveBeenCalledWith(expectedError);
|
||||
});
|
||||
|
||||
it('calls provided handler', () => {
|
||||
// Set up and inject mock logger.
|
||||
const mockHandler = jest.fn();
|
||||
const manager = CacheManager.fromConfig(defaultConfig(), {
|
||||
onError: mockHandler,
|
||||
});
|
||||
|
||||
// Set up a cache client using the configured manager.
|
||||
manager.forPlugin('error-handler-test').getClient();
|
||||
|
||||
// Retrieve the error handler attached to the cache client.
|
||||
const client = DefaultCacheClient as jest.Mock;
|
||||
const mockCalls = client.mock.calls.splice(-1);
|
||||
const realClient = mockCalls[0][0].client as Keyv;
|
||||
const realOnError = realClient.on as jest.Mock;
|
||||
const realHandler = realOnError.mock.calls.splice(-1)[0][1];
|
||||
|
||||
// Invoke the actual error handler.
|
||||
const expectedError = new Error('some error');
|
||||
realHandler(expectedError);
|
||||
expect(mockHandler).toHaveBeenCalledWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,9 +18,15 @@ import { Config } from '@backstage/config';
|
||||
import Keyv from 'keyv';
|
||||
// @ts-expect-error
|
||||
import KeyvMemcache from 'keyv-memcache';
|
||||
import { Logger } from 'winston';
|
||||
import { getRootLogger } from '../logging';
|
||||
import { DefaultCacheClient, CacheClient } from './CacheClient';
|
||||
import { NoStore } from './NoStore';
|
||||
import { PluginCacheManager } from './types';
|
||||
import {
|
||||
CacheManagerOptions,
|
||||
OptionalOnError,
|
||||
PluginCacheManager,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
* Implements a Cache Manager which will automatically create new cache clients
|
||||
@@ -38,8 +44,10 @@ export class CacheManager {
|
||||
none: this.getNoneClient,
|
||||
};
|
||||
|
||||
private readonly logger: Logger;
|
||||
private readonly store: keyof CacheManager['storeFactories'];
|
||||
private readonly connection: string;
|
||||
private readonly errorHandler: OptionalOnError;
|
||||
|
||||
/**
|
||||
* Creates a new CacheManager instance by reading from the `backend` config
|
||||
@@ -47,25 +55,38 @@ export class CacheManager {
|
||||
*
|
||||
* @param config The loaded application configuration.
|
||||
*/
|
||||
static fromConfig(config: Config): CacheManager {
|
||||
static fromConfig(
|
||||
config: Config,
|
||||
options: CacheManagerOptions = {},
|
||||
): CacheManager {
|
||||
// If no `backend.cache` config is provided, instantiate the CacheManager
|
||||
// with a "NoStore" cache client.
|
||||
const store = config.getOptionalString('backend.cache.store') || 'none';
|
||||
const connectionString =
|
||||
config.getOptionalString('backend.cache.connection') || '';
|
||||
return new CacheManager(store, connectionString);
|
||||
const logger = (options.logger || getRootLogger()).child({
|
||||
type: 'cacheManager',
|
||||
});
|
||||
return new CacheManager(store, connectionString, logger, options.onError);
|
||||
}
|
||||
|
||||
private constructor(store: string, connectionString: string) {
|
||||
private constructor(
|
||||
store: string,
|
||||
connectionString: string,
|
||||
logger: Logger,
|
||||
errorHandler: OptionalOnError,
|
||||
) {
|
||||
if (!this.storeFactories.hasOwnProperty(store)) {
|
||||
throw new Error(`Unknown cache store: ${store}`);
|
||||
}
|
||||
this.logger = logger;
|
||||
this.store = store as keyof CacheManager['storeFactories'];
|
||||
this.connection = connectionString;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a CacheManagerInstance for consumption by plugins.
|
||||
* Generates a PluginCacheManager for consumption by plugins.
|
||||
*
|
||||
* @param pluginId The plugin that the cache manager should be created for. Plugin names should be unique.
|
||||
*/
|
||||
@@ -73,6 +94,18 @@ export class CacheManager {
|
||||
return {
|
||||
getClient: (opts = {}): CacheClient => {
|
||||
const concreteClient = this.getClientWithTtl(pluginId, opts.defaultTtl);
|
||||
|
||||
// Always provide an error handler to avoid killing the process.
|
||||
concreteClient.on('error', (err: Error) => {
|
||||
// In all cases, just log the error.
|
||||
this.logger.error(err);
|
||||
|
||||
// Invoke any custom error handler if provided.
|
||||
if (typeof this.errorHandler === 'function') {
|
||||
this.errorHandler(err);
|
||||
}
|
||||
});
|
||||
|
||||
return new DefaultCacheClient({
|
||||
client: concreteClient,
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Logger } from 'winston';
|
||||
import { CacheClient } from './CacheClient';
|
||||
|
||||
type ClientOptions = {
|
||||
@@ -25,6 +26,21 @@ type ClientOptions = {
|
||||
defaultTtl?: number;
|
||||
};
|
||||
|
||||
export type OptionalOnError = ((err: Error) => void) | undefined;
|
||||
|
||||
export type CacheManagerOptions = {
|
||||
/**
|
||||
* An optional logger for use by the PluginCacheManager.
|
||||
*/
|
||||
logger?: Logger;
|
||||
|
||||
/**
|
||||
* An optional handler for connection errors emitted from the underlying data
|
||||
* store.
|
||||
*/
|
||||
onError?: OptionalOnError;
|
||||
};
|
||||
|
||||
/**
|
||||
* The PluginCacheManager manages access to cache stores that Plugins get.
|
||||
*/
|
||||
|
||||
@@ -29,11 +29,11 @@ import path from 'path';
|
||||
import { NotModifiedError } from '@backstage/errors';
|
||||
import { getVoidLogger } from '../logging';
|
||||
import { AzureUrlReader } from './AzureUrlReader';
|
||||
import { ReadTreeResponseFactory } from './tree';
|
||||
import { DefaultReadTreeResponseFactory } from './tree';
|
||||
|
||||
const logger = getVoidLogger();
|
||||
|
||||
const treeResponseFactory = ReadTreeResponseFactory.create({
|
||||
const treeResponseFactory = DefaultReadTreeResponseFactory.create({
|
||||
config: new ConfigReader({}),
|
||||
});
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ import parseGitUrl from 'git-url-parse';
|
||||
import { Minimatch } from 'minimatch';
|
||||
import { Readable } from 'stream';
|
||||
import { NotFoundError, NotModifiedError } from '@backstage/errors';
|
||||
import { ReadTreeResponseFactory } from './tree';
|
||||
import { stripFirstDirectoryFromPath } from './tree/util';
|
||||
import {
|
||||
ReadTreeResponseFactory,
|
||||
ReaderFactory,
|
||||
ReadTreeOptions,
|
||||
ReadTreeResponse,
|
||||
|
||||
@@ -28,9 +28,9 @@ import os from 'os';
|
||||
import path from 'path';
|
||||
import { NotModifiedError } from '@backstage/errors';
|
||||
import { BitbucketUrlReader } from './BitbucketUrlReader';
|
||||
import { ReadTreeResponseFactory } from './tree';
|
||||
import { DefaultReadTreeResponseFactory } from './tree';
|
||||
|
||||
const treeResponseFactory = ReadTreeResponseFactory.create({
|
||||
const treeResponseFactory = DefaultReadTreeResponseFactory.create({
|
||||
config: new ConfigReader({}),
|
||||
});
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ import parseGitUrl from 'git-url-parse';
|
||||
import { Minimatch } from 'minimatch';
|
||||
import { Readable } from 'stream';
|
||||
import { NotFoundError, NotModifiedError } from '@backstage/errors';
|
||||
import { ReadTreeResponseFactory } from './tree';
|
||||
import { stripFirstDirectoryFromPath } from './tree/util';
|
||||
import {
|
||||
ReadTreeResponseFactory,
|
||||
ReaderFactory,
|
||||
ReadTreeOptions,
|
||||
ReadTreeResponse,
|
||||
|
||||