Merge pull request #1 from backstage/master

fetch from backstage
This commit is contained in:
Brett Wright
2021-06-14 12:33:02 +02:00
committed by GitHub
1933 changed files with 113608 additions and 12456 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog': patch
---
Exports `CatalogLayout` and `CreateComponentButton` for catalog customization.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/codemods': patch
---
Fix execution of `jscodeshift` on windows.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-welcome': patch
---
Australian Greeting
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core': patch
---
Exported SignInProviderConfig to strongly type SignInPage providers
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-user-settings': patch
---
Fix a bug that prevented changing themes on the user settings page when the theme `id` didn't match exactly the theme `variant`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-components': patch
---
Add title prop in SupportButton component
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
Adding support for user owned document filter for TechDocs custom Homepage
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-techdocs': patch
---
Add a test id to the shadow root element of the Reader to access it easily in e2e tests
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': minor
---
Added support for Datadog rum events
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-proxy-backend': patch
---
Bump http-proxy-middleware from 0.19.2 to 2.0.0
+29 -1
View File
@@ -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',
},
],
},
};
+5
View File
@@ -8,12 +8,17 @@
/docs/features/techdocs @backstage/techdocs-core
/docs/features/search @backstage/techdocs-core
/docs/assets/search @backstage/techdocs-core
/plugins/code-coverage @alde @nissayeva
/plugins/code-coverage-backend @alde @nissayeva
/plugins/cost-insights @backstage/silver-lining
/plugins/cloudbuild @trivago/ebarrios
/plugins/search @backstage/techdocs-core
/plugins/search-* @backstage/techdocs-core
/plugins/techdocs @backstage/techdocs-core
/plugins/techdocs-backend @backstage/techdocs-core
/plugins/ilert @yacut
/packages/search-common @backstage/techdocs-core
/packages/techdocs-common @backstage/techdocs-core
/.changeset/cost-insights-* @backstage/silver-lining
/.changeset/search-* @backstage/techdocs-core
/.changeset/techdocs-* @backstage/techdocs-core
+1
View File
@@ -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
+103 -80
View File
@@ -1,119 +1,60 @@
Apdex
Api
Autoscaling
Avro
Bigtable
Billett
Bitrise
Blackbox
Chai
Changesets
Chanwit
Cloudformation
Codecov
Codehilite
Config
Datadog
Debounce
Discoverability
Dockerfile
Dockerize
Docusaurus
Env
Expedia
Figma
Firekube
Fiverr
GitHub
GitLab
Grafana
GraphQL
Hackathons
Heroku
Hostname
Iain
JavaScript
Kaewkasi
Knex
Leasot
Lerna
Luxon
Minikube
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
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
codemod
codemods
codeowners
composability
composable
config
Config
configmaps
configs
const
cookiecutter
css
Datadog
dataflow
deadnaming
debounce
Debounce
declaratively
deps
destructured
@@ -121,58 +62,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
@@ -184,43 +166,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
@@ -231,17 +238,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
@@ -249,6 +264,7 @@ tooltips
touchpoints
transpilation
transpiled
truthy
ui
unmanaged
unregister
@@ -257,11 +273,18 @@ untracked
upvote
url
utils
validator
validators
varchar
Weaveworks
Webpack
winston
www
WWW
XML
xyz
yaml
Zalando
Zhou
zoomable
zsh
+1
View File
@@ -20,3 +20,4 @@ jobs:
version: yarn release
env:
GITHUB_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
HUSKY: '0'
@@ -48,5 +48,7 @@ jobs:
- uses: chromaui/action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
# projetToken intentionally shared to allow collaborators to run Chromatic on forks
# https://www.chromatic.com/docs/custom-ci-provider#run-chromatic-on-external-forks-of-open-source-projects
projectToken: 9tzak77m9nj
storybookBuildDir: 'packages/storybook/dist'
+49
View File
@@ -12,6 +12,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
@@ -76,6 +111,9 @@ jobs:
- name: prettier
run: yarn prettier:check
- name: lock
run: yarn lock:check
- name: validate config
run: yarn backstage-cli config:check --lax
@@ -85,6 +123,9 @@ jobs:
- name: type checking and declarations
run: yarn tsc:full
- name: check api reports
run: yarn build:api-reports:only --ci
- name: build changed packages
if: ${{ steps.yarn-lock.outcome == 'success' }}
run: yarn lerna -- run build --since origin/master --include-dependencies
@@ -99,12 +140,20 @@ jobs:
- name: test changed packages
if: ${{ steps.yarn-lock.outcome == 'success' }}
run: yarn lerna -- run test --since origin/master -- --coverage
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: test all packages (and upload coverage)
if: ${{ steps.yarn-lock.outcome == 'failure' }}
run: |
yarn lerna -- run test -- --coverage
bash <(curl -s https://codecov.io/bash) -N $(git rev-parse FETCH_HEAD)
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: verify plugin template
run: yarn lerna -- run diff -- --check
+6
View File
@@ -53,8 +53,14 @@ jobs:
- name: verify type dependencies
run: yarn lint:type-deps
# The core packages need to be built for the codemods tests to work
- name: build core packages
run: lerna run --scope @backstage/core-* build
- 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
+39
View File
@@ -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
View File
@@ -0,0 +1 @@
_
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn lint-staged
+1
View File
@@ -4,6 +4,7 @@ microsite
coverage
*.hbs
templates
api-report.md
plugins/scaffolder-backend/sample-templates
.vscode
dist-types
+32 -27
View File
@@ -1,27 +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 teams engineering dependencies. |
| 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 teams 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. |
-163
View File
@@ -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)
+1 -1
View File
@@ -93,7 +93,7 @@ Which will look something like the following in the repo;
```
Awesome commit message
Signed-off-by: Jane Smith jane.smith@example.com
Signed-off-by: Jane Smith <jane.smith@example.com>
```
- In case you forgot to add it to the most recent commit, use `git commit --amend --signoff`
+1 -1
View File
@@ -27,5 +27,5 @@ People that have made significant contributions to the project and earned write
- Andrew Thauer - Wealthsimple (GitHub: [andrewthauer](https://github.com/andrewthauer))
- Oliver Sand - SDA SE (GitHub: [Fox32](https://github.com/Fox32))
- David Tuite - Roadie (GitHub: [dtuite](https://github.com/dtuite))
- Adam Harvey - DXC Technology (GitHub: [adamdmharvey](https://github.com/adamdmharvey))
- Adam Harvey - Cisco (GitHub: [adamdmharvey](https://github.com/adamdmharvey))
- Dominik Henneke - SDA SE (GitHub: [dhenneke](https://github.com/dhenneke))
+14 -3
View File
@@ -2,9 +2,9 @@ app:
title: Backstage Example App
baseUrl: http://localhost:3000
googleAnalyticsTrackingId: # UA-000000-0
datadogRum:
clientToken: '123456789'
applicationId: qwerty
#datadogRum:
# clientToken: '123456789'
# applicationId: qwerty
# site: # datadoghq.eu default = datadoghq.com
# env: # optional
@@ -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
@@ -81,6 +85,13 @@ proxy:
headers:
Authorization: ${SENTRY_TOKEN}
'/ilert':
target: https://api.ilert.com
allowedMethods: ['GET', 'POST', 'PUT']
allowedHeaders: ['Authorization']
headers:
Authorization: ${ILERT_AUTH_HEADER}
organization:
name: My Company
+10
View File
@@ -129,6 +129,16 @@ For the CA, create a `configMap` named `<release name>-<chart name>-postgres-ca`
kubectl create configmap my-company-backstage-postgres-ca --from-file=ca.crt"
```
or disable CA mount
```yaml
backend:
postgresCertMountEnabled: false
lighthouse:
postgresCertMountEnabled: false
```
> Where the release name contains the chart name "backstage" then only the release name will be used.
Now install the helm chart:
@@ -214,7 +214,7 @@ Postgres port for the backend
{{- .Values.postgresql.service.port }}
{{- else if .Values.appConfig.backend.database.connection.port -}}
{{- .Values.appConfig.backend.database.connection.port }}
{{ else }}
{{- else -}}
5432
{{- end -}}
{{- end -}}
@@ -26,6 +26,13 @@ spec:
{{- end}}
containers:
- name: {{ .Chart.Name }}-backend
command: ["node"]
args:
- "packages/backend"
- "--config"
- "app-config.yaml"
- "--config"
- {{ printf "/usr/src/app/%s" (include "backstage.appConfigFilename" .) | quote }}
image: {{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
ports:
@@ -49,16 +56,20 @@ spec:
name: {{ include "backend.postgresql.passwordSecret" .}}
key: postgresql-password
volumeMounts:
{{- if .Values.backend.postgresCertMountEnabled }}
- name: postgres-ca
mountPath: {{ include "backstage.backend.postgresCaDir" . }}
{{- end }}
- name: app-config
mountPath: {{ printf "/usr/src/app/%s" (include "backstage.appConfigFilename" .) }}
subPath: {{ include "backstage.appConfigFilename" . }}
volumes:
{{- if .Values.backend.postgresCertMountEnabled }}
- name: postgres-ca
configMap:
name: {{ include "backstage.fullname" . }}-postgres-ca
{{- end }}
- name: app-config
configMap:
name: {{ include "backstage.fullname" . }}-app-config
@@ -83,5 +94,5 @@ spec:
app: backstage
component: backend
type: ClusterIP
type: {{ .Values.backend.serviceType }}
{{- end }}
@@ -1,3 +1,4 @@
{{- if .Values.frontend.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -46,7 +47,6 @@ spec:
{{- if .Values.global.nodeSelector }}
nodeSelector: {{- toYaml .Values.global.nodeSelector | nindent 8 }}
{{- end }}
{{- if .Values.frontend.enabled }}
---
apiVersion: v1
kind: Service
@@ -62,5 +62,5 @@ spec:
app: backstage
component: frontend
type: ClusterIP
type: {{ .Values.frontend.serviceType }}
{{- end }}
@@ -1,3 +1,4 @@
{{- if .Values.lighthouse.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
@@ -7,4 +8,5 @@ data:
PGUSER: {{ include "lighthouse.postgresql.user" . | quote }}
PGPORT: {{ include "lighthouse.postgresql.port" . | quote }}
PGHOST: {{ include "lighthouse.postgresql.host" . | quote }}
PGPATH_TO_CA: {{ include "backstage.lighthouse.postgresCaFilename" . | quote }}
PGPATH_TO_CA: {{ include "backstage.lighthouse.postgresCaFilename" . | quote }}
{{- end }}
@@ -51,14 +51,18 @@ spec:
name: {{ include "lighthouse.postgresql.passwordSecret" . }}
key: postgresql-password
{{- if .Values.lighthouse.postgresCertMountEnabled }}
volumeMounts:
- name: postgres-ca
mountPath: {{ include "backstage.lighthouse.postgresCaDir" . }}
{{- end }}
{{- if .Values.lighthouse.postgresCertMountEnabled }}
volumes:
- name: postgres-ca
configMap:
name: {{ include "backstage.fullname" . }}-postgres-ca
{{- end }}
{{- if .Values.global.nodeSelector }}
nodeSelector: {{- toYaml .Values.global.nodeSelector | nindent 8 }}
@@ -78,5 +82,5 @@ spec:
app: backstage
component: lighthouse-audit-service
type: ClusterIP
type: {{ .Values.lighthouse.serviceType }}
{{- end }}
@@ -0,0 +1,15 @@
{{- if not .Values.postgresql.enabled }}
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ include "backend.postgresql.passwordSecret" . }}
labels:
release: {{ .Release.Name }}
annotations:
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/hook-delete-policy": "before-hook-creation"
data:
postgresql-password: {{ .Values.appConfig.backend.database.connection.password | b64enc }}
{{- end }}
@@ -1,18 +1,4 @@
{{- if not .Values.postgresql.enabled }}
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ include "backend.postgresql.passwordSecret" . }}
labels:
release: {{ .Release.Name }}
annotations:
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/hook-delete-policy": "before-hook-creation"
data:
postgresql-password: {{ .Values.appConfig.backend.database.connection.password | b64enc }}
{{- end }}
{{- if .Values.lighthouse.enabled }}
{{- if not .Values.postgresql.enabled }}
---
apiVersion: v1
@@ -28,3 +14,4 @@ metadata:
data:
postgresql-password: {{ .Values.lighthouse.database.connection.password | b64enc }}
{{- end }}
{{- end }}
+7 -2
View File
@@ -3,13 +3,14 @@
# Declare variables to be passed into your templates.
frontend:
enabled: true
enabled: false
replicaCount: 1
image:
repository: martinaif/backstage-k8s-demo-frontend
tag: test1
pullPolicy: IfNotPresent
containerPort: 80
serviceType: ClusterIP
resources:
requests:
memory: 128Mi
@@ -23,9 +24,11 @@ backend:
replicaCount: 1
image:
repository: martinaif/backstage-k8s-demo-backend
tag: test1
tag: 20210423T1550
pullPolicy: IfNotPresent
containerPort: 7000
serviceType: ClusterIP
postgresCertMountEnabled: true
resources:
requests:
memory: 512Mi
@@ -40,6 +43,8 @@ lighthouse:
tag: latest
pullPolicy: IfNotPresent
containerPort: 3003
serviceType: ClusterIP
postgresCertMountEnabled: true
resources:
requests:
memory: 128Mi
@@ -1,18 +0,0 @@
FROM nginx:mainline
# The purpose of this image is to serve the frontend app content separately.
# By default the Backstage backend uses the app-backend plugin to serve the
# app from the backend itself, but it may be desirable to move the frontend
# content serving to a separate deployment, in which case this image can be used.
# This dockerfile requires the app to be built on the host first, as it
# simply copies in the build output into the image.
RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/*
COPY packages/app/dist /usr/share/nginx/html
COPY docker/default.conf.template /etc/nginx/conf.d/default.conf.template
COPY docker/run.sh /usr/local/bin/run.sh
CMD run.sh
ENV PORT 80
@@ -0,0 +1,58 @@
# The purpose of this image is to serve the frontend app content separately.
# By default the Backstage backend uses the app-backend plugin to serve the
# app from the backend itself, but it may be desirable to move the frontend
# content serving to a separate deployment, in which case this image can be
# used.
# This dockerfile also performs the build first inside docker. This may come
# with a build time impact, but is sometimes desirable. If you want to run the
# build on the host instead, use the file simply named Dockerfile in this folder
# instead.
# USAGE:
#
# - Copy this file and the "docker" folder from this directory to your project
# root
#
# - Update your .dockerignore, make sure that the source folders are not
# excluded, but do exclude node_modules and build artifacts:
#
# .git
# node_modules
# packages/*/dist
# packages/*/node_modules
# plugins/*/dist
# plugins/*/node_modules
#
# - Update the copy of this file to add configuration arguments to the "build"
# command, for example:
#
# RUN yarn workspace app build --config <config1> --config <config2> ...
#
# - In your project root, run:
#
# docker build -t backstage-frontend -f Dockerfile.dockerbuild .
FROM node:14-buster AS build
RUN mkdir /app
COPY . /app
WORKDIR /app
RUN yarn install
RUN yarn workspace app build
FROM nginx:mainline
RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/*
COPY --from=build /app/packages/app/dist /usr/share/nginx/html
COPY docker/default.conf.template /etc/nginx/templates/default.conf.template
COPY docker/inject-config.sh /docker-entrypoint.d/40-inject-config.sh
ENV PORT 80
@@ -0,0 +1,41 @@
# The purpose of this image is to serve the frontend app content separately.
# By default the Backstage backend uses the app-backend plugin to serve the
# app from the backend itself, but it may be desirable to move the frontend
# content serving to a separate deployment, in which case this image can be
# used.
# This dockerfile requires the app to be built on the host first, as it
# simply copies in the build output into the image. If you want to also perform
# the build itself inside docker, use Dockerfile.build in this folder instead.
# USAGE:
#
# - Copy this file and the "docker" folder from this directory to your project
# root
#
# - Add the following line to your .dockerignore to make sure that the built
# frontend actually can be transferred into the docker image:
#
# !packages/app/dist
#
# - In your project root, run:
#
# yarn install
# yarn tsc
# yarn build --config <config1> --config <config2> ...
# docker build -t backstage-frontend -f Dockerfile.hostbuild .
FROM nginx:mainline
RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/*
COPY packages/app/dist /usr/share/nginx/html
COPY docker/default.conf.template /etc/nginx/templates/default.conf.template
COPY docker/inject-config.sh /docker-entrypoint.d/40-inject-config.sh
ENV PORT 80
@@ -0,0 +1,16 @@
# Frontend with NGINX
This folder contains Docker images that let you run the Backstage frontend as
a separate image, rather than having it served through the `app-backend` plugin
from the backend.
Note that when running the frontend like this, the app configuration becomes
embedded into the actual static JavaScript files at build time. This means that
you will have to supply the list of configuration files as part of the command
line at build.
## Usage
There are two variants: one that builds inside Docker, and one that builds on
the host. See the comments at the top of the individual dockerfiles for usage
instructions.
@@ -2,13 +2,6 @@
set -Eeuo pipefail
# Run nginx as root
sed -i 's/user nginx.*$//' /etc/nginx/nginx.conf
# Write selected env vars to nginx config
envsubst '$PORT' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf
# Inject runtime config into the client
function inject_config() {
# Read runtime config from env in the same way as the @backstage/config-loader package
local config
@@ -41,4 +34,3 @@ function inject_config() {
inject_config
exec nginx -g 'daemon off;'
@@ -1,23 +0,0 @@
FROM node:12-buster AS build
RUN mkdir /app
COPY . /app
WORKDIR /app
RUN yarn install
RUN yarn workspace example-app build
# Contruct backstage-frontend image
FROM nginx:mainline
RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/*
# Copy from build stage
COPY --from=build /app/packages/app/dist /usr/share/nginx/html
COPY docker/default.conf.template /etc/nginx/conf.d/default.conf.template
COPY docker/run.sh /usr/local/bin/run.sh
CMD run.sh
ENV PORT 80
@@ -1,19 +0,0 @@
# Standalone Dockerfile for frontend
This directory contains the resources which will help you build backstage without any requirements
other than docker itself. It uses a multi-stage Dockerfile to build and ship backstage.
## Usage
You can simply run the following command to build backstage.
```
# Make sure you are in the root directory of backstage then run
docker build -t backstage-frontend -f ./contrib/docker/multi-stage-frontend/Dockerfile .
```
After a successful build, You can simply run backstage frontend with the following command.
```
docker run -it --rm -p 3080:80 backstage-frontend
```
@@ -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
+18 -54
View File
@@ -41,12 +41,9 @@ documentation to build a new Backstage Docker image:
```shell
$ yarn build
$ docker image build . -f packages/backend/Dockerfile --tag backstage
$ yarn build-image --tag backstage
```
This command builds a backend-only image, but you can similarly build a frontend
or combined Docker image.
Next, configure the [AWS CLI](https://aws.amazon.com/cli/) to use the
`ecr-publisher` user you created:
@@ -90,65 +87,37 @@ document, but it can be as easy as `eksctl create cluster` documented in the
guide](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html),
which uses a Cloudformation template to create the necessary resources.
To deploy the Docker image to EKS, create a `kubernetes` folder in your
Backstage source folder and add a Kubernetes `deployment.yaml`:
To deploy the Docker image to EKS, follow the [Kubernetes
guide](https://backstage.io/docs/deployment/k8s#creating-the-backstage-instance)
but set the Backstage deployment `image` to the ECR repository URL:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backstage-backend
labels:
app: backstage-backend
namespace: default
name: backstage
namespace: backstage
spec:
replicas: 1
selector:
matchLabels:
app: backstage-backend
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
...
template:
metadata:
labels:
app: backstage-backend
app: backstage
spec:
containers:
- image: <repo_url>/backstage:1.0.0
imagePullPolicy: Always
name: backstage-backend
ports:
- containerPort: 7000
protocol: TCP
...
```
Note the `image` key in the container spec referencing the ECR repository.
Now create a simple `service.yaml` to map the container ports:
```yaml
apiVersion: v1
kind: Service
metadata:
name: backstage-backend
spec:
selector:
app: backstage-backend
ports:
- protocol: TCP
port: 80
targetPort: 7000
```
Apply these Kubernetes definitions to the EKS cluster to complete the Backstage
deployment:
Create the [Service
descriptor](https://backstage.io/docs/deployment/k8s#creating-a-backstage-service)
as well, and apply these Kubernetes definitions to the EKS cluster to complete
the Backstage deployment:
```shell
$ kubectl apply -f deployment.yaml
$ kubectl apply -f service.yaml
$ kubectl apply -f kubernetes/backstage.yaml
$ kubectl apply -f kubernetes/backstage-service.yaml
```
Now you can see your Backstage workload running from the [EKS
@@ -158,14 +127,15 @@ console](https://console.aws.amazon.com/eks/home).
### Exposing Backstage with a load balancer
Backstage users need to query the backend, which means we need to expose
the workload with a load balancer. Follow the [Application load balancing on
To make the service useful, we need to expose the workload with a load balancer.
Follow the [Application load balancing on
EKS](https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html) guide to
set up a Load Balancer controller and Kubernetes ingress to your application.
This is ultimately a `kubectl apply` with an ingress definition:
```yaml
# kubernetes/backstage-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
@@ -187,9 +157,3 @@ spec:
port:
number: 80
```
### Updating the deployment
To update the Kubernetes deployment to a newly published version of your
Backstage Docker image, update the image tag reference in `deployment.yaml` and
then apply the changes to EKS with `kubectl apply -f deployment.yaml`.
@@ -0,0 +1,16 @@
# Deploying Backstage with AWS Fargate and Aurora
There are any number of ways to deploy backstage containers on AWS. One of the
simplest from a management and ops perspective is to leverage AWS Fargate and
Aurora PostgreSQL, where both the container orchestration and database clusters
are AWS managed services.
However, to use them properly there are a large number of supporting resources
(VPCs, Security Groups, Load Balancers, Certificate, etc) required. One approach
is to use [AWS Cloud Development Kit (CDK)](https://aws.amazon.com/cdk/) to
simplify and automate the creation of the entire infrastructure stack along with
automating the build and deploy of the container.
Check out the [Backstage On AWS](https://github.com/rbogle/backstage-on-aws)
repository, for a ready to use CDK application for deploying your custom
Backstage app onto AWS ECS Fargate and Aurora.
@@ -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.
@@ -16,7 +16,7 @@ spec:
app.kubernetes.io/name: {{ include "backstage.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- if .Values.app.enabled }}
{{- if .Values.backend.enabled }}
---
apiVersion: v1
kind: Service
@@ -1,44 +0,0 @@
# Plain Kubernetes Deployment
This directory contains an example of a simple Kubernetes deployment of Backstage. It is not intended to serve as a complete production deployment, but as a starting point for setting one up.
## Usage
You can try the deployment out as is. The easiest way is to use [Docker Desktop](https://www.docker.com/products/docker-desktop) with [Kubernetes](https://docs.docker.com/get-started/kube-deploy/).
You can now follow the documentation here to build the Backend Container [Docker Build](https://backstage.io/docs/getting-started/deployment-docker)
From a fresh clone of this repo, run the following in the root:
```bash
yarn install
yarn docker-build
kubectl apply -f contrib/kubernetes/plain_single_backend_deployment/deployment.yaml
```
You can use the following commands to monitor the deployment:
```bash
# List all resources in the backstage namespace
kubectl -n backstage get all
# Inspect the status of the deployment resource
kubectl -n backstage describe deployment backstage-backend
# Inspect the status of the pod running the backstage backend
kubectl -n backstage describe pod -l app=backstage,component=backend
```
Once the deployment is up and running, you can use the following to set up a proxy to reach the backend locally:
```bash
kubectl proxy
```
With the proxy up and running, you should be able to navigate to [http://localhost:8001/api/v1/namespaces/backstage/services/backstage-backend:http/proxy](http://localhost:8001/api/v1/namespaces/backstage/services/backstage-backend:http/proxy) and see Backstage. Note that you'll end up on a 404 page, but hitting the home icon in the sidebar should take you to the catalog page where you can see a few example services.
## Caveats
This deployment is for demonstration purposes only, for a production deployment you will need to set up at least a persistent database and some form of ingress. If your organization doesn't already have established patterns for these, you could look at options of managed PostgreSQL instances from cloud providers, or something like Zalando's [postgres-operator](https://github.com/zalando/postgres-operator). For ingress there are also [plenty of options](https://ramitsurana.gitbook.io/awesome-kubernetes/docs/projects/projects#load-balancing), where `nginx` is a popular choice to get started.
@@ -1,107 +0,0 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: backstage
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backstage-backend
namespace: backstage
spec:
replicas: 1
selector:
matchLabels:
app: backstage
component: backend
template:
metadata:
labels:
app: backstage
component: backend
spec:
containers:
- name: backend
# This image is built with `yarn docker-build` in the repo root.
# Replace this with your own image to deploy your own Backstage app.
image: example-backend:latest
imagePullPolicy: Never
command: [node, packages/backend]
args: [--config, app-config.yaml, --config, k8s-config.yaml]
env:
# We set this to development to make the backend start with incomplete configuration. In a production
# deployment you will want to make sure that you have a full configuration, and remove any plugins that
# you are not using.
- name: NODE_ENV
value: development
# This makes it possible for the app to reach the backend when serving through `kubectl proxy`
# If you expose the service using for example an ingress controller, you should
# switch this out or remove it.
#
# Note that we're not setting app.baseUrl here, as setting the base path is not working at the moment.
# Further work is needed around the routing in the frontend or react-router before we can support that.
- name: APP_CONFIG_backend_baseUrl
value: http://localhost:8001/api/v1/namespaces/backstage/services/backstage-backend:http/proxy
ports:
- name: http
containerPort: 7000
volumeMounts:
- name: config-volume
mountPath: /app/k8s-config.yaml
subPath: k8s-config.yaml
resources:
limits:
cpu: 1
memory: 0.5Gi
readinessProbe:
httpGet:
port: 7000
path: /healthcheck
livenessProbe:
httpGet:
port: 7000
path: /healthcheck
volumes:
- name: config-volume
configMap:
name: backstage-config
items:
- key: app-config
path: k8s-config.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: backstage-config
namespace: backstage
data:
# Note that the config here is only applied to the backend. The frontend config is applied at build time.
# To override frontend config in this deployment, use `APP_CONFIG_` env vars.
app-config: |
app:
baseUrl: http://localhost:8001/api/v1/namespaces/backstage/services/backstage-backend:http/proxy
backend:
baseUrl: http://localhost:8001/api/v1/namespaces/backstage/services/backstage-backend:http/proxy
---
apiVersion: v1
kind: Service
metadata:
name: backstage-backend
namespace: backstage
spec:
selector:
app: backstage
component: backend
ports:
- name: http
port: 80
targetPort: http
@@ -0,0 +1 @@
This terraform file should create a S3 bucket and setup IAM with a user with an inline policy which gives the user access to the bucket. After you have created the bucket, user and policy you should go to the user in the AWS console and create an access key. This access key should be used as the env variables in step 3a [here](https://backstage.io/docs/features/techdocs/using-cloud-storage#configuring-aws-s3-bucket-with-techdocs).
@@ -0,0 +1,81 @@
#==========================
# Variables
#==========================
variable "backstage_bucket" {
default = "backstage_bucket_for_my_corp"
}
variable "backstage_iam" {
default = "backstage"
}
variable "shared_managed_tag" {
default = "terraform_for_my_corp"
}
#==========================
# Bucket
#==========================
resource "aws_s3_bucket" "backstage" {
bucket = var.backstage_bucket
acl = "private"
provider = aws
lifecycle {
prevent_destroy = true
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
tags = {
Name = var.backstage_bucket
"Managed By Terraform" = var.shared_managed_tag
}
}
resource "aws_s3_bucket_public_access_block" "backstage" {
bucket = aws_s3_bucket.backstage.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
#==========================
# IAM
#==========================
resource "aws_iam_user" "backstage" {
name = var.backstage_iam
}
resource "aws_iam_user_policy" "backstage" {
name = var.backstage_iam
user = aws_iam_user.backstage.name
policy = data.aws_iam_policy_document.backstage_policy.json
}
data "aws_iam_policy_document" "backstage_policy" {
statement {
actions = [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket"
]
effect = "Allow"
resources = [
"${aws_s3_bucket.backstage.arn}",
"${aws_s3_bucket.backstage.arn}/*",
]
}
}
+1 -1
View File
@@ -5,7 +5,7 @@
"license": "MIT",
"private": true,
"dependencies": {
"cypress": "^6.4.0",
"cypress": "^7.3.0",
"typescript": "^4.1.3"
}
}
+76
View File
@@ -0,0 +1,76 @@
/*
* 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.
*/
/// <reference types="cypress" />
import 'os';
describe('Integrations', () => {
describe('ReadTree', () => {
it('should work for github', () => {
cy.loginAsGuest();
cy.request('POST', '/api/catalog/locations', {
target:
'https://github.com/backstage-verification/test-repo/blob/main/**/*',
type: 'url',
});
cy.visit('/catalog');
cy.contains('All').click();
cy.get('table').should('contain', 'github-repo');
cy.get('table').should('contain', 'github-repo-nested');
});
// it('should work for azure', () => {
// cy.loginAsGuest();
// cy.request('POST', '/api/catalog/locations', {
// target:
// 'https://dev.azure.com/backstage-verification/_git/test-repo?path=*',
// type: 'url',
// });
// });
it('should work for gitlab', () => {
cy.loginAsGuest();
cy.request('POST', '/api/catalog/locations', {
target:
'https://gitlab.com/backstage-verification/test-repo/-/tree/master/**/*',
type: 'url',
});
cy.visit('/catalog');
cy.contains('All').click();
cy.get('table').should('contain', 'gitlab-repo');
cy.get('table').should('contain', 'gitlab-repo-nested');
});
it('should work for bitbucket', () => {
cy.loginAsGuest();
cy.request('POST', '/api/catalog/locations', {
target:
'https://bitbucket.org/backstage-verification/test-repo/src/master/**/*',
type: 'url',
});
cy.visit('/catalog');
cy.contains('All').click();
cy.get('table').should('contain', 'bitbucket-repo');
cy.get('table').should('contain', 'bitbucket-repo-nested');
});
});
});
+89 -82
View File
@@ -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,
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+2 -2
View File
@@ -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
```
-2
View File
@@ -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
+23
View File
@@ -44,6 +44,7 @@ clean Delete cache directories
create-plugin Creates a new plugin in the current repository
remove-plugin Removes plugin in the current repository
config:docs Browse the configuration reference documentation
config:print Print the app configuration for the current package
config:check Validate that the given configuration loads and matches schema
config:schema Dump the app configuration schema
@@ -110,6 +111,7 @@ Usage: backstage-cli app:build
Options:
--stats Write bundle stats to output directory
--lax Do not require environment variables to be set
--config &lt;path&gt; Config files to load instead of app-config.yaml (default: [])
-h, --help display help for command
```
@@ -447,6 +449,25 @@ Options:
--backstage-cli-help display help for command
```
## config:docs
Scope: `root`
This commands opens up the reference documentation of your apps local
configuration schema in the browser. This is useful to get an overview of what
configuration values are available to use, a description of what they do and
their format, and where they get sent.
```text
Usage: backstage-cli config:docs [options]
Browse the configuration reference documentation
Options:
--package <name> Only include the schema that applies to the given package
-h, --help display help for command
```
## config:print
Scope: `root`
@@ -466,6 +487,7 @@ Usage: backstage-cli config:print [options]
Options:
--package &lt;name&gt; Only load config schema that applies to the given package
--lax Do not require environment variables to be set
--frontend Print only the frontend configuration
--with-secrets Include secrets in the printed configuration
--format &lt;format&gt; Format to print the configuration in, either json or yaml [yaml]
@@ -486,6 +508,7 @@ Usage: backstage-cli config:check [options]
Options:
--package &lt;name&gt; Only load config schema that applies to the given package
--lax Do not require environment variables to be set
--config &lt;path&gt; Config files to load instead of app-config.yaml (default: [])
-h, --help display help for command
```
+12 -2
View File
@@ -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
+4 -4
View File
@@ -19,9 +19,9 @@ their state, rather than using SQLite.
By default, in an app created with `@backstage/create-app`, the frontend is
bundled and served from the backend. This is done using the
`@backstage/plugin-app-backend` plugin, which also injects the frontend
configuration into the app. This means you that you only need to build and
deploy a single container in a minimal setup of Backstage. If you wish to
separate the serving of the frontend out from the backend, see the
configuration into the app. This means that you only need to build and deploy a
single container in a minimal setup of Backstage. If you wish to separate the
serving of the frontend out from the backend, see the
[separate frontend](#separate-frontend) topic below.
## Host Build
@@ -232,7 +232,7 @@ package, which is done as follows:
Once the `app-backend` is removed from the backend, you can use your favorite
static file serving method for serving the frontend. An example of how to set up
an NGINX image is available in the
[contrib folder in the main repo](https://github.com/backstage/backstage/blob/master/contrib/docker/frontend-with-nginx/Dockerfile)
[contrib folder in the main repo](https://github.com/backstage/backstage/blob/master/contrib/docker/frontend-with-nginx)
Note that if you're building a separate docker build of the frontend you
probably need to adjust `.dockerignore` appropriately. Most likely by making
+1 -3
View File
@@ -1,12 +1,10 @@
---
id: helm
title: Deploying Backstage with Helm
title: Deploying with Helm
description: How to deploy Backstage with Helm and Kubernetes
sidebar_label: Helm
---
# Helm charts
An example Backstage app can be deployed in Kubernetes using the
[Backstage Helm charts](https://github.com/backstage/backstage/tree/master/contrib/chart/backstage).
+3 -1
View File
@@ -30,7 +30,9 @@ There is also an example of deploying on [Heroku](heroku.md), which only
requires the first two steps.
An example of deploying Backstage with a [Helm chart](helm.md), a common pattern
in AWS, is also available.
in AWS, is also available. There is also a contrib guide to deploying Backstage
with
[AWS Fargate and Aurora PostgreSQL](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/aws-fargate-deployment.md)
Please consider contributing other deployment guides if you get Backstage set up
on common infrastructure, it would be a great benefit to the community.
+10
View File
@@ -357,6 +357,16 @@ spec:
name: postgres-secrets
- secretRef:
name: backstage-secrets
# Uncomment if health checks are enabled in your app:
# https://backstage.io/docs/plugins/observability#health-checks
# readinessProbe:
# httpGet:
# port: 7000
# path: /healthcheck
# livenessProbe:
# httpGet:
# port: 7000
# path: /healthcheck
```
For production deployments, the `image` reference will usually be a full URL to
+13
View File
@@ -25,6 +25,7 @@ kubernetes:
- url: http://127.0.0.1:9999
name: minikube
authProvider: 'serviceAccount'
skipTLSVerify: false
serviceAccountToken: ${K8S_MINIKUBE_TOKEN}
- url: http://127.0.0.2:9999
name: aws-cluster-1
@@ -32,6 +33,7 @@ kubernetes:
- type: 'gke'
projectId: 'gke-clusters'
region: 'europe-west1'
skipTLSVerify: true
```
### `serviceLocatorMethod`
@@ -77,6 +79,12 @@ cluster. Valid values are:
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `serviceAccount` | This will use a Kubernetes [service account](https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/) to access the Kubernetes API. When this is used the `serviceAccountToken` field should also be set. |
| `google` | This will use a user's Google auth token from the [Google auth plugin](https://backstage.io/docs/auth/) to access the Kubernetes API. |
| `aws` | This will use AWS credentials to access resources in EKS clusters |
##### `clusters.\*.skipTLSVerify`
This determines whether or not the Kubernetes client verifies the TLS
certificate presented by the API server. Defaults to `false`.
##### `clusters.\*.serviceAccountToken` (optional)
@@ -122,6 +130,11 @@ The Google Cloud project to look for Kubernetes clusters in.
The Google Cloud region to look for Kubernetes clusters in. Defaults to all
regions.
##### `skipTLSVerify`
This determines whether or not the Kubernetes client verifies the TLS
certificate presented by the API server. Defaults to `false`.
### `customResources` (optional)
Configures which [custom resources][3] to look for when returning an entity's
+25 -45
View File
@@ -8,52 +8,36 @@ The Kubernetes feature is a plugin to Backstage, and it is exposed as a tab when
viewing entities in the software catalog.
If you haven't setup Backstage already, read the
[Getting Started](../../getting-started/index.md).
[Getting Started](../../getting-started/index.md) guide.
## Adding the Kubernetes frontend plugin
The first step is to add the frontend Kubernetes plugin to your Backstage
application. Navigate to your new Backstage application directory. And then to
The first step is to add the Kubernetes frontend plugin to your Backstage
application. Navigate to your new Backstage application directory, and then to
your `packages/app` directory, and install the `@backstage/plugin-kubernetes`
package.
```bash
cd my-backstage-app/
# From your Backstage root directory
cd packages/app
yarn add @backstage/plugin-kubernetes
```
Once the package has been installed, you need to import the plugin in your app.
Add the following to `packages/app/src/plugins.ts`:
`plugins.ts`:
```typescript
export { plugin as Kubernetes } from '@backstage/plugin-kubernetes';
```
Now, add the "Kubernetes" tab to the catalog entity page. In
`packages/app/src/components/catalog/EntityPage.tsx`, you'll add a router to get
to the tab, and add the tab itself.
`EntityPage.tsx`:
Once the package has been installed, you need to import the plugin in your app
by adding the "Kubernetes" tab to the respective catalog pages.
```tsx
import { Router as KubernetesRouter } from '@backstage/plugin-kubernetes';
// In packages/app/src/components/catalog/EntityPage.tsx
import { EntityKubernetesContent } from '@backstage/plugin-kubernetes';
// ...
const ServiceEntityPage = ({ entity }: { entity: Entity }) => (
<EntityPageLayout>
// ...
<EntityPageLayout.Content
path="/kubernetes/*"
title="Kubernetes"
element={<KubernetesRouter entity={entity} />}
/>
// ...
</EntityPageLayout>
);
// You can add the tab to any number of pages, the service page is shown as an
// example here
const serviceEntityPage = (
<EntityLayout>
{/* other tabs... */}
<EntityLayout.Route path="/kubernetes" title="Kubernetes">
<EntityKubernetesContent />
</EntityLayout.Route>
```
That's it! But now, we need the Kubernetes Backend plugin for the frontend to
@@ -65,17 +49,16 @@ Navigate to `packages/backend` of your Backstage app, and install the
`@backstage/plugin-kubernetes-backend` package.
```bash
cd my-backstage-app/
# From your Backstage root directory
cd packages/backend
yarn add @backstage/plugin-kubernetes-backend
```
Create a file called `kubernetes.ts` inside `packages/backend/src/plugins/` and
add the following
`kubernetes.ts`:
add the following:
```typescript
// In packages/backend/src/plugins/kubernetes.ts
import { createRouter } from '@backstage/plugin-kubernetes-backend';
import { PluginEnvironment } from '../types';
@@ -91,18 +74,15 @@ And import the plugin to `packages/backend/src/index.ts`. There are three lines
of code you'll need to add, and they should be added near similar code in your
existing Backstage backend.
`index.ts`:
```typescript
// In packages/backend/src/index.ts
import kubernetes from './plugins/kubernetes';
// ...
const kubernetesEnv = useHotMemoize(module, () => createEnv('kubernetes'));
// ...
apiRouter.use('/kubernetes', await kubernetes(kubernetesEnv));
async function main() {
// ...
const kubernetesEnv = useHotMemoize(module, () => createEnv('kubernetes'));
// ...
apiRouter.use('/kubernetes', await kubernetes(kubernetesEnv));
```
That's it! The Kubernetes frontend and backend have now been added to your
+56 -29
View File
@@ -24,22 +24,22 @@ Backstage ecosystem.
## Project roadmap
| Version | Description |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Backstage Search v0 ✅ | Search Frontend letting you search through the entities of the software catalog. [See v0 Use Cases.](#backstage-search-v0) |
| [Backstage Search V0.5 ✅ ][v0.5] | Foundations for the architecture. |
| [Backstage Search v1 ⌛][v1] | Basic “out-of-the-box” in-memory indexing process of entities, and their metadata, registered to the Software Catalog. [See v1 Use Cases.](#backstage-search-v1) |
| [Backstage Search v2 ⌛][v2] | Search Backend responsible for the indexing process of entities, and their metadata, registered to the Software Catalog. [See v2 Use Cases.](#backstage-search-v2) |
| [Backstage Search v3 ⌛][v3] | Standardized Search API lets you index other plugins data to the search engine of choice. [See v3 Use Cases.](#backstage-search-v3) |
| Version | Description |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Backstage Search Pre-Alpha ✅ | Search Frontend letting you search through the entities of the software catalog. [See Pre-Alpha Use Cases.](#backstage-search-pre-alpha) |
| Backstage Search Alpha ✅ | Basic “out-of-the-box” in-memory indexing process of entities, and their metadata, registered to the Software Catalog. [See Alpha Use Cases](#backstage-search-alpha). |
| [Backstage Search Beta ⌛][beta] | At least one production-ready search engine that supports the same use-cases as in the alpha. [See Beta Use Cases](#backstage-search-beta). |
| [Backstage Search GA ⌛][ga] | A stable Search API for plugin developers to add search to their plugins, and app integrators to expose that to their users. [See GA Use Cases](#backstage-search-ga). |
[v0.5]: https://github.com/backstage/backstage/milestone/25
[v1]: https://github.com/backstage/backstage/milestone/26
[v2]: https://github.com/backstage/backstage/milestone/27
[v3]: https://github.com/backstage/backstage/milestone/28
[beta]: https://github.com/backstage/backstage/milestone/27
[ga]: https://github.com/backstage/backstage/milestone/28
## Use Cases
#### Backstage Search V.0
#### Backstage Search Pre-Alpha
The pre-alpha is intended to solve for the following user stories, but will get
there by means of a front-end only, non-extensible MVP.
- As a software engineer I should be able to navigate to a search page and
search for entities registered in the Software Catalog.
@@ -52,28 +52,48 @@ Backstage ecosystem.
- As a software engineer I should be able to hide the filters if I dont need to
use them.
#### Backstage Search V.1
#### Backstage Search Alpha
- As a software engineer I should be able to get a match of a search on all
entity metadata (e.g. owner, name, description, kind).
- As an integrator I should not have to plug in any search engine, instead I can
use the out of the box in-memory indexing process to index entities and their
metadata registered in the Software Catalog.
We will consider Backstage Search to be in alpha when the above use-cases are
met, but built on top of a flexible, extensible platform.
#### Backstage Search V.2
- As an integrator, I should be able to provide all of the pre-alpha experiences
to my users if I choose, but also be able to customize the experience using a
composable set of components.
- As a plugin developer, I should have a standard way to expose my plugin's data
to Backstage Search.
- As an integrator, I should still be able to expose everything in the Software
Catalog in search, but it should be possible to customize what is searchable.
- As an integrator, although I should be able to customize all of the above, it
should be possible to have the pre-alpha user experiences covered without
having to set up and configure a search engine.
- As an integrator I should be able to spin up an instance of ElasticSearch.
- As an integrator I should be able to define a ElasticSearch cluster in my
app_config.yaml where my data gets indexed to.
#### Backstage Search Beta
more to come...
We will consider Backstage Search to be in a beta phase when the above use-cases
are met, and can be deployed using a production-ready search engine.
#### Backstage Search V.3
- As an integrator, I should be able to power my Backstage Search experience
(including querying and indexing) using a production-ready search engine like
ElasticSearch.
- As an integrator, I should be able to configure the connection to my search
engine in `app_config.yaml`.
- As an integrator, I should be able to tune the queries sent to my chosen
search engine according to my organization's needs, but a sensible default
query should be in place so that I am not required to do so.
- As a contributor I should be able to integrate plugin data to the indexing
process of Backstage Search by using the standardized API.
- As a software engineer I should be able to search for all content (for
example, entities, metadata, documentation) in Backstage search.
#### Backstage Search GA
We will consider Backstage Search to be generally available (GA) when the above
use-cases are met, and an ecosystem of search-enabled plugins are available and
stable.
- As a plugin developer, there should be at least one example of a Backstage
plugin that integrates with search that I can use as inspiration for my own
plugin's search capabilities (for example, the TechDocs plugin).
- As an app integrator, there should be plenty of examples and documentation on
how to customize and extend search in my Backstage instance to meet my
organization's needs.
more to come...
@@ -84,12 +104,19 @@ the search engines are used.
| Search Engine | Support Status |
| ------------- | -------------- |
| Basic (lunr) | Not yet ❌ |
| Basic (lunr) | |
| ElasticSearch | Not yet ❌ |
[Reach out to us](#feedback) if you want to chat about support for more search
engines.
## Plugins Integrated with Search
| Plugin | Support Status |
| -------- | -------------- |
| Catalog | ✅ |
| TechDocs | Not yet ❌ |
## Tech Stack
| Stack | Location |
+112
View File
@@ -0,0 +1,112 @@
---
id: concepts
title: Search Concepts
description: Documentation on Backstage Search Concepts
---
# Search Concepts
Backstage Search lets you find the right information you are looking for in the
Backstage ecosystem.
To get started, you should get familiar with these core concepts:
- [Search Engines](#search-engines)
- [Query Translators](#query-translators)
- [Documents and Indices](#documents-and-indices)
- [Collators](#collators)
- [Decorators](#decorators)
- [The Scheduler](#the-scheduler)
- [The Search Page](#the-search-page)
- [Search Context and Components](#search-context-and-components)
### Search Engines
Backstage Search isn't a search engine itself, rather, it provides an interface
between your Backstage instance and a Search Engine of your choice. More
concretely, a `SearchEngine` is an interface whose concrete implementations
facilitate communication with different search engines (like ElasticSearch,
Lunr, Solr, etc). This abstraction exists in order to support your
organization's needs.
Out of the box, Backstage Search comes pre-packaged with an in-memory search
engine implementation built on top of Lunr.
### Query Translators
Because you can bring your own search engine, and because search engines have
very unique and robust query languages themselves, there needs to be a
translation layer between an abstract search query (containing search terms,
filters, and document types) into a concrete search query that is specific to a
search engine.
Search Engines come pre-packaged with simple translators that do rudimentary
transformations of search terms and filters, but you may want to provide your
own to help tune search results in the context of your organization.
### Documents and Indices
"Document" is an abstract concept representing something that can be found by
searching for it. A document can represent a software entity, a TechDocs page,
etc. Documents are made up of metadata fields, at a minimum including a title,
text, and location (as in a URL).
An index is a collection of such documents of a given type.
### Collators
You need to be able to search something! Collators are the way to define what
can be searched. Specifically, they're classes which return documents conforming
to a minimum set of fields (including a document title, location, and text), but
which can contain any other fields as defined by the collator itself. One
collator is responsible for defining and collecting documents of a type.
Some plugins, like the Catalog Backend, provide so-called "default" collators
which you can use out-of-the-box to start searching across Backstage quickly.
### Decorators
Sometimes you want to add extra information to a set of documents in your search
index that the collator may not be aware of. For example, the Software Catalog
knows about software entities, but it may not know about their usage or quality.
Decorators are classes which can add extra fields to pre-collated documents.
This extra metadata could then be used to bias search results or otherwise
improve the search experience in your Backstage instance.
### The Scheduler
There are many ways a search index could be built and maintained, but Backstage
Search chooses to completely rebuild indices on a schedule. Different collators
can be configured to refresh at different intervals, depending on how often the
source information is updated.
### The Search Page
Search pages are very custom things. Not every Backstage instance will want the
same interface! In order to allow you to customize your search experience to
your heart's content, the Search Plugin takes care of state management and other
search logic for you, but most of the layout of a search page lives in a search
page component defined in your Backstage App.
For an example of a simple search page, check
[getting started](./getting-started.md#adding-search-to-the-frontend)
### Search Context and Components
A search experience, like a page, is composed of any number of search
components, which are all wired up using a search context.
Each search experience's context consists of details like a search term,
filters, types, results, and a page cursor for handling pagination. Different
components use this context in different ways. For example, the `<SearchBar />`
can set the search term, `<SearchFilter />` components can set filters, and
search results can be displayed using the `<SearchResult />` component.
The `<SearchResult />` and `<SearchFilter />` components are special, in that
they themselves are extensible. For an example of how to extend these
components, check
[getting started](./getting-started.md#adding-search-to-the-frontend).
If you need even more customization, you can use the search context like any
other React context to create custom search components of your own.
+297
View File
@@ -0,0 +1,297 @@
---
id: getting-started
title: Getting Started with Search
description: How to set up and install Backstage Search
---
# Getting Started
Search functions as a plugin to Backstage, so you will need to use Backstage to
use Search.
If you haven't setup Backstage already, start
[here](../../getting-started/index.md).
> If you used `npx @backstage/create-app`, and you have a search page defined in
> `packages/app/src/components/search`, skip to
> [`Customizing Search`](#customizing-search) below.
## Adding Search to the Frontend
```bash
# From your Backstage root directory
cd packages/app
yarn add @backstage/plugin-search
```
Create a new `packages/app/src/components/search/SearchPage.tsx` file in your
Backstage app with the following contents:
```tsx
import React from 'react';
import { Content, Header, Page } from '@backstage/core';
import { Grid, List, Card, CardContent } from '@material-ui/core';
import {
SearchBar,
SearchResult,
DefaultResultListItem,
SearchFilter,
} from '@backstage/plugin-search';
import { CatalogResultListItem } from '@backstage/plugin-catalog';
export const searchPage = (
<Page themeId="home">
<Header title="Search" />
<Content>
<Grid container direction="row">
<Grid item xs={12}>
<SearchBar />
</Grid>
<Grid item xs={3}>
<Card>
<CardContent>
<SearchFilter.Select
name="kind"
values={['Component', 'Template']}
/>
</CardContent>
<CardContent>
<SearchFilter.Checkbox
name="lifecycle"
values={['experimental', 'production']}
/>
</CardContent>
</Card>
</Grid>
<Grid item xs={9}>
<SearchResult>
{({ results }) => (
<List>
{results.map(result => {
switch (result.type) {
case 'software-catalog':
return (
<CatalogResultListItem
key={result.document.location}
result={result.document}
/>
);
default:
return (
<DefaultResultListItem
key={result.document.location}
result={result.document}
/>
);
}
})}
</List>
)}
</SearchResult>
</Grid>
</Grid>
</Content>
</Page>
);
```
Bind the above Search Page to the `/search` route in your
`packages/app/src/App.tsx` file, like this:
```tsx
import { SearchPage } from '@backstage/plugin-search';
import { searchPage } from './components/search/SearchPage';
const routes = (
<FlatRoutes>
<Route path="/search" element={<SearchPage />}>
{searchPage}
</Route>
</FlatRoutes>
);
```
## Adding Search to the Backend
Add the following plugins into your backend app:
```bash
# From your Backstage root directory
cd packages/backend
yarn add @backstage/plugin-search-backend @backstage/plugin-search-backend-node
```
Create a `packages/backend/src/plugins/search.ts` file containing the following
code:
```typescript
import { useHotCleanup } from '@backstage/backend-common';
import { createRouter } from '@backstage/plugin-search-backend';
import {
IndexBuilder,
LunrSearchEngine,
} from '@backstage/plugin-search-backend-node';
import { PluginEnvironment } from '../types';
import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend';
export default async function createPlugin({
logger,
discovery,
}: PluginEnvironment) {
const searchEngine = new LunrSearchEngine({ logger });
const indexBuilder = new IndexBuilder({ logger, searchEngine });
indexBuilder.addCollator({
type: 'software-catalog',
defaultRefreshIntervalSeconds: 600,
collator: new DefaultCatalogCollator({ discovery }),
});
const { scheduler } = await indexBuilder.build();
scheduler.start();
useHotCleanup(module, () => scheduler.stop());
return await createRouter({
engine: indexBuilder.getSearchEngine(),
logger,
});
}
```
Make the following modifications to your `packages/backend/src/index.ts` file:
Import the `plugins/search` file you created above:
```typescript
import search from './plugins/search';
```
Set up an environment for search:
```typescript
const searchEnv = useHotMemoize(module, () => createEnv('search'));
```
Register the search service with the router:
```typescript
apiRouter.use('/search', await search(searchEnv));
```
## Customizing Search
### Frontend
The Search Plugin exposes several default filter types as static properties,
including `<SearchFilter.Select />` and `<SearchFilter.Checkbox />`. These allow
you to provide values relevant to your Backstage instance that, when selected,
get passed to the backend.
```tsx {2-5,8-11}
<CardContent>
<SearchFilter.Select
name="kind"
values={['Component', 'Template']}
/>
</CardContent>
<CardContent>
<SearchFilter.Checkbox
name="lifecycle"
values={['production', 'experimental']}
/>
</CardContent>
```
If you have advanced filter needs, you can specify your own filter component
like this (although new core filter contributions are welcome):
```tsx
import { useSearch, SearchFilter } from '@backstage/plugin-search';
const MyCustomFilter = () => {
// Note: filters contain filter data from other filter components. Be sure
// not to clobber other filters' data!
const { filters, setFilters } = useSearch();
return (/* ... */);
};
// Which could be rendered like this:
<SearchFilter component={MyCustomFilter} />
```
It's good practice for search results to highlight information that was used to
return it in the first place! The code below highlights how you might specify a
custom result item component, using the `<CatalogResultListItem />` component as
an example:
```tsx {7-13}
<SearchResult>
{({ results }) => (
<List>
{results.map(result => {
// result.type is the index type defined by the collator.
switch (result.type) {
case 'software-catalog':
return (
<CatalogResultListItem
key={result.document.location}
result={result.document}
/>
);
// ...
}
})}
</List>
)}
</SearchResult>
```
### Backend
Backstage Search isn't a search engine itself, rather, it provides an interface
between your Backstage instance and a
[Search Engine](./concepts.md#search-engines) of your choice. Currently, we only
support one, an in-memory search Engine called Lunr. It can be instantiated like
this:
```typescript
const searchEngine = new LunrSearchEngine({ logger });
const indexBuilder = new IndexBuilder({ logger, searchEngine });
```
Backstage Search can be used to power search of anything! Plugins like the
Catalog offer default [collators](./concepts.md#collators) which are responsible
for providing documents [to be indexed](./concepts.md#documents-and-indices).
You can register any number of collators with the `IndexBuilder` like this:
```typescript
const indexBuilder = new IndexBuilder({ logger, searchEngine });
indexBuilder.addCollator({
type: 'software-catalog',
defaultRefreshIntervalSeconds: 600,
collator: new DefaultCatalogCollator({ discovery }),
});
indexBuilder.addCollator({
type: 'my-custom-stuff',
defaultRefreshIntervalSeconds: 3600,
collator: new MyCustomCollator(),
});
```
Backstage Search builds and maintains its index
[on a schedule](./concepts.md#the-scheduler). You can change how often the
indexes are rebuilt for a given type of document. You may want to do this if
your documents are updated more or less frequently. You can do so by modifying
its `defaultRefreshIntervalSeconds` value, like this:
```typescript {3}
indexBuilder.addCollator({
type: 'software-catalog',
defaultRefreshIntervalSeconds: 600,
collator: new DefaultCatalogCollator({ discovery }),
});
```
@@ -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.
@@ -37,6 +37,13 @@ The locations added through static configuration cannot be removed through the
catalog locations API. To remove these locations, you must remove them from the
configuration.
Syntax errors or other types of errors present in `catalog-info.yaml` files will
be logged for investigation. Errors do not cause processing to abort.
When multiple `catalog-info.yaml` files with the same `metadata.name` property
are discovered, one will be processed and all others will be skipped. This
action is logged for further investigation.
### Integration Processors
Integrations may simply provide a mechanism to handle `url` location type for an
@@ -111,8 +118,7 @@ catalog:
> deleting entities will not work in this mode.**
A common use case for this configuration is when organizations have a remote
source that should be mirrored into backstage. If we want backstage to be a
mirror of this remote source we cannot allow users to also register entities
with e.g.
source that should be mirrored into Backstage. To make Backstage a mirror of
this remote source, users cannot also register new entities with e.g. the
[catalog-import](https://github.com/backstage/backstage/tree/master/plugins/catalog-import)
plugin.
@@ -23,6 +23,7 @@ we recommend that you name them `catalog-info.yaml`.
- [Common to All Kinds: The Envelope](#common-to-all-kinds-the-envelope)
- [Common to All Kinds: The Metadata](#common-to-all-kinds-the-metadata)
- [Common to All Kinds: Relations](#common-to-all-kinds-relations)
- [Common to All Kinds: Status](#common-to-all-kinds-status)
- [Kind: Component](#kind-component)
- [Kind: Template](#kind-template)
- [Kind: API](#kind-api)
@@ -44,7 +45,7 @@ metadata:
name: artist-web
description: The place to be, for great artists
labels:
system: public-websites
example.com/custom: custom_label_value
annotations:
example.com/service-discovery: artistweb
circleci.com/project-slug: github/example-org/artist-website
@@ -58,6 +59,7 @@ spec:
type: website
lifecycle: production
owner: artist-relations-team
system: public-websites
```
This is the same entity as returned in JSON from the software catalog API:
@@ -76,7 +78,7 @@ This is the same entity as returned in JSON from the software catalog API:
"etag": "ZjU2MWRkZWUtMmMxZS00YTZiLWFmMWMtOTE1NGNiZDdlYzNk",
"generation": 1,
"labels": {
"system": "public-websites"
"example.com/custom": "custom_label_value"
},
"links": [{
"url": "https://admin.example-org.com",
@@ -90,7 +92,8 @@ This is the same entity as returned in JSON from the software catalog API:
"spec": {
"lifecycle": "production",
"owner": "artist-relations-team",
"type": "website"
"type": "website",
"system": "public-websites"
}
}
```
@@ -394,6 +397,68 @@ with it (such as the default kind being `Group` if not specified).
See the [well-known relations section](well-known-relations.md) for a list of
well-known / common relations and their semantics.
## Common to All Kinds: Status
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).
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 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.
```js
{
// ...
"status": {
"items": [
{
"type": "backstage.io/catalog-processing",
"level": "error",
"message": "NotFoundError: File not found",
"error": {
"name": "NotFoundError",
"message": "File not found",
"stack": "..."
}
}
]
},
"spec": {
// ...
}
}
```
The fields of a status item are:
| 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. |
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 status types.
## Kind: Component
Describes the following entity kind:
@@ -639,22 +704,11 @@ A list of strings that can be associated with the template, e.g.
This list will also be used in the frontend to display to the user so you can
potentially search and group templates by these tags.
### `spec.type` [optional]
### `spec.type` [required]
The type of component as a string, e.g. `website`. This field is optional but
recommended.
The software catalog accepts any type value, but an organization should take
great care to establish a proper taxonomy for these. Tools including Backstage
itself may read this field and behave differently depending on its value. For
example, a website type component may present tooling in the Backstage interface
that is specific to just websites.
The current set of well-known and common values for this field is:
- `service` - a backend service, typically exposing an API
- `website` - a website
- `library` - a software library, such as an npm module or a Java library
The type of component created by the template, e.g. `website`. This is used for
filtering templates, and should ideally match the Component
[spec.type](#spectype-required) created by the template.
### `spec.parameters` [required]
@@ -666,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 template, 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:
@@ -1,6 +1,7 @@
---
id: extending-the-model
title: Extending the model
# prettier-ignore
description: Documentation on extending the catalog model
---
@@ -301,9 +302,9 @@ Example intents:
> "We have this concept of service maintainership, separate from ownership, that
> we would like to make relations to individual users for."
> We feel that we want to explicitly model the team-to-global-department mapping
> as a relation, because it is core to our org setup and we frequently query for
> it.
> "We feel that we want to explicitly model the team-to-global-department
> mapping as a relation, because it is core to our org setup and we frequently
> query for it."
Any processor can emit relations for entities as they are being processed, and
new processors can be added when building the backend catalog using the
@@ -349,3 +350,46 @@ If you want to extend the use of an established relation type in a way that has
an effect outside of your organization, reach out to the Backstage maintainers
or a support partner to discuss risk/impact. It may even be that one end of the
relation could be considered for addition to the core.
## Adding a New Status field
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. We
> find the `status.items` semantics a poor fit, so we would prefer to make our
> own custom field under `status` for these purposes."
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.
@@ -18,20 +18,15 @@ The catalog frontend plugin should be installed in your `app` package, which is
created as a part of `@backstage/create-app`. To install the package, run:
```bash
# From your Backstage root directory
cd packages/app
yarn add @backstage/plugin-catalog
```
### Adding the Plugin to your `packages/app`
Add the following entry to the head of your `packages/app/src/plugins.ts`:
```ts
export { catalogPlugin } from '@backstage/plugin-catalog';
```
Next we need to install the two pages that the catalog plugin provides. You can
choose any name for these routes, but we recommend the following:
Add the two pages that the catalog plugin provides to your app. You can choose
any name for these routes, but we recommend the following:
```tsx
// packages/app/src/App.tsx
@@ -109,6 +104,7 @@ The catalog backend should be installed in your `backend` package, which is
created as a part of `@backstage/create-app`. To install the package, run:
```bash
# From your Backstage root directory
cd packages/backend
yarn add @backstage/plugin-catalog-backend
```
@@ -273,6 +273,20 @@ project within your organization.
Specifying this annotation may enable SonarQube related features in Backstage
for that entity.
### backstage.io/code-coverage
```yaml
# Example:
metadata:
annotations:
backstage.io/code-coverage: scm-only
```
The value of this annotation controls the code-coverage backstage plugin. If set
to `scm-only`, the plugin will only take into account files stored in source
control (e.g. ignoring generated code). If set to `enabled`, all files covered
by a coverage report will be taken into account.
## Deprecated Annotations
The following annotations are deprecated, and only listed here to aid in
@@ -0,0 +1,55 @@
---
id: well-known-statuses
title: Well-known Status fields of Catalog Entities
sidebar_label: Well-known Statuses
# prettier-ignore
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 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 statuses, see
[Extending the model](extending-the-model.md).
## 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. 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.
## Status Item Types
This is a (non-exhaustive) list of `status.items.[].type` values that are known
to be in active use.
### `backstage.io/catalog-processing`
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
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.
```yaml
# Example:
status:
items:
- type: backstage.io/catalog-processing
level: error
message: 'NotFoundError: File not found'
error:
name: NotFoundError
message: File not found
stack: ...
```
@@ -20,20 +20,15 @@ The scaffolder frontend plugin should be installed in your `app` package, which
is created as a part of `@backstage/create-app`. To install the package, run:
```bash
# From your Backstage root directory
cd packages/app
yarn add @backstage/plugin-scaffolder
```
### Adding the Plugin to your `packages/app`
Add the following entry to the head of your `packages/app/src/plugins.ts`:
```ts
export { scaffolderPlugin } from '@backstage/plugin-scaffolder';
```
Next we need to install the root page that the Scaffolder plugin provides. You
can choose any path for the route, but we recommend the following:
Add the root page that the Scaffolder plugin provides to your app. You can
choose any path for the route, but we recommend the following:
```tsx
import { ScaffolderPage } from '@backstage/plugin-scaffolder';
@@ -63,6 +58,7 @@ The scaffolder backend should be installed in your `backend` package, which is
created as a part of `@backstage/create-app`. To install the package, run:
```bash
# From your Backstage root directory
cd packages/backend
yarn add @backstage/plugin-scaffolder-backend
```
@@ -74,6 +70,10 @@ creating a file called `packages/backend/src/plugins/scaffolder.ts` with the
following contents to get you up and running quickly.
```ts
import {
DockerContainerRunner,
SingleHostDiscovery,
} from '@backstage/backend-common';
import {
CookieCutter,
createRouter,
@@ -82,7 +82,6 @@ import {
CreateReactAppTemplater,
Templaters,
} from '@backstage/plugin-scaffolder-backend';
import { SingleHostDiscovery } from '@backstage/backend-common';
import type { PluginEnvironment } from '../types';
import Docker from 'dockerode';
import { CatalogClient } from '@backstage/catalog-client';
@@ -93,8 +92,11 @@ export default async function createPlugin({
database,
reader,
}: PluginEnvironment) {
const cookiecutterTemplater = new CookieCutter();
const craTemplater = new CreateReactAppTemplater();
const dockerClient = new Docker();
const containerRunner = new DockerContainerRunner({ dockerClient });
const cookiecutterTemplater = new CookieCutter({ containerRunner });
const craTemplater = new CreateReactAppTemplater({ containerRunner });
const templaters = new Templaters();
templaters.register('cookiecutter', cookiecutterTemplater);
@@ -103,8 +105,6 @@ export default async function createPlugin({
const preparers = await Preparers.fromConfig(config, { logger });
const publishers = await Publishers.fromConfig(config, { logger });
const dockerClient = new Docker();
const discovery = SingleHostDiscovery.fromConfig(config);
const catalogClient = new CatalogClient({ discoveryApi: discovery });
@@ -114,7 +114,6 @@ export default async function createPlugin({
publishers,
logger,
config,
dockerClient,
database,
catalogClient,
reader,
@@ -265,9 +264,17 @@ the templates at [localhost:3000/create](http://localhost:3000/create) now!
Software Templates use
[Cookiecutter](https://github.com/cookiecutter/cookiecutter) as templating
library. By default it will use the
[spotify/backstage-cookiecutter](<[spotify/backstage-cookiecutter](https://github.com/backstage/backstage/blob/37e35b910afc7d1270855aed0ec4718aba366c91/plugins/scaffolder-backend/scripts/Cookiecutter.dockerfile)>)
[spotify/backstage-cookiecutter](https://github.com/backstage/backstage/blob/37e35b910afc7d1270855aed0ec4718aba366c91/plugins/scaffolder-backend/scripts/Cookiecutter.dockerfile)
docker image.
If you are running backstage from a Docker container and you want to avoid
If you are running Backstage from a Docker container and you want to avoid
calling a container inside a container, you can set up Cookiecutter in your own
image, this will use the local installation instead.
You can do so by including the following lines in the last step of your
`Dockerfile`:
```Dockerfile
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip3 install cookiecutter
```
@@ -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!
@@ -106,7 +106,6 @@ return await createRouter({
publishers,
logger,
config,
dockerClient,
database,
catalogClient,
reader,
@@ -124,7 +123,6 @@ return await createRouter({
publishers,
logger,
config,
dockerClient,
database,
catalogClient,
reader,
@@ -136,11 +134,9 @@ return await createRouter({
want to have those as well as your new one, you'll need to do the following:
```ts
import { createBuiltinActions } from '@backstage/plugin-scaffolder-backend`;
import { createBuiltinActions } from '@backstage/plugin-scaffolder-backend';
const builtInActions = createBuiltinActions({
dockerClient,
integrations,
catalogClient,
templaters,
@@ -155,7 +151,6 @@ return await createRouter({
publishers,
logger,
config,
dockerClient,
database,
catalogClient,
reader,
@@ -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
@@ -271,6 +288,7 @@ template. These follow the same standard format:
```yaml
- id: fetch-base # A unique id for the step
name: Fetch Base # A title displayed in the frontend
if: '{{ parameters.name }}' # Optional condition, skip the step if not truthy
action: fetch:cookiecutter # an action to call
input: # input that is passed as arguments to the action handler
url: ./template
@@ -304,7 +322,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
+12
View File
@@ -45,3 +45,15 @@ metadata annotation is used in the build process of TechDocs. But when
annotation should still be present in entity descriptor file (e.g.
`catalog-info.yaml`) for Backstage to know that TechDocs is enabled for the
entity.
#### Is it possible for users to suggest changes or provide feedback on a TechDocs page?
This is supported for TechDocs sites whose source code is hosted in either
GitHub or GitLab. In order to add "edit this page" and "leave feedback" buttons
on a TechDocs page, be sure that you have `repo_url` and `edit_uri` values in
your `mkdocs.yml` files per
[MkDocs instructions](https://www.mkdocs.org/user-guide/configuration).
If the host name of your source code hosting URL does not include `github` or
`gitlab`, an `integrations` entry in your `app-config.yaml` pointed at your
source code provider is also needed (only the `host` key is necessary).
+5
View File
@@ -78,6 +78,11 @@ techdocs:
# https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
endpoint: ${AWS_ENDPOINT}
# (Optional) Whether to use path style URLs when communicating with S3.
# Defaults to false.
# This allows providers like LocalStack, Minio and Wasabi (and possibly others) to be used to host tech docs.
s3ForcePathStyle: false
# Required when techdocs.publisher.type is set to 'azureBlobStorage'. Skip otherwise.
azureBlobStorage:
@@ -148,6 +148,23 @@ jobs:
- uses: actions/setup-node@v2
- uses: actions/setup-python@v2
# the 2 steps below can be removed if you aren't using plantuml in your documentation
- name: setup java
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '11'
- name: download, validate, install plantuml and its dependencies
run: |
curl -o plantuml.jar -L http://sourceforge.net/projects/plantuml/files/plantuml.1.2021.4.jar/download
echo "be498123d20eaea95a94b174d770ef94adfdca18 plantuml.jar" | sha1sum -c -
mv plantuml.jar /opt/plantuml.jar
mkdir -p "$HOME/.local/bin"
echo $'#!/bin/sh\n\njava -jar '/opt/plantuml.jar' ${@}' >> "$HOME/.local/bin/plantuml"
chmod +x "$HOME/.local/bin/plantuml"
echo "$HOME/.local/bin" >> $GITHUB_PATH
sudo apt-get install -y graphviz
- name: Install techdocs-cli
run: sudo npm install -g @techdocs/cli
+24 -16
View File
@@ -22,21 +22,15 @@ Navigate to your new Backstage application directory. And then to your
`packages/app` directory, and install the `@backstage/plugin-techdocs` package.
```bash
cd my-backstage-app/
# From your Backstage root directory
cd packages/app
yarn add @backstage/plugin-techdocs
```
Once the package has been installed, you need to import the plugin in your app.
Add the following to `packages/app/src/plugins.ts`:
```typescript
export { plugin as TechDocs } from '@backstage/plugin-techdocs';
```
Now we can add a route for the TechDocs page. In `packages/app/src/App.tsx`,
import TechDocsPage and add the following to `FlatRoutes`:
In `packages/app/src/App.tsx`, import `TechDocsPage` and add the following to
`FlatRoutes`:
```tsx
import { TechDocsPage } from '@backstage/plugin-techdocs';
@@ -60,7 +54,7 @@ Navigate to `packages/backend` of your Backstage app, and install the
`@backstage/plugin-techdocs-backend` package.
```bash
cd my-backstage-app/
# From your Backstage root directory
cd packages/backend
yarn add @backstage/plugin-techdocs-backend
```
@@ -69,6 +63,7 @@ Create a file called `techdocs.ts` inside `packages/backend/src/plugins/` and
add the following
```typescript
import { DockerContainerRunner } from '@backstage/backend-common';
import {
createRouter,
Generators,
@@ -90,9 +85,14 @@ export default async function createPlugin({
reader,
});
// Docker client (conditionally) used by the generators, based on techdocs.generators config.
const dockerClient = new Docker();
const containerRunner = new DockerContainerRunner({ dockerClient });
// Generators are used for generating documentation sites.
const generators = await Generators.fromConfig(config, {
logger,
containerRunner,
});
// Publisher is used for
@@ -103,14 +103,13 @@ export default async function createPlugin({
discovery,
});
// Docker client (conditionally) used by the generators, based on techdocs.generators config.
const dockerClient = new Docker();
// checks if the publisher is working and logs the result
await publisher.getReadiness();
return await createRouter({
preparers,
generators,
publisher,
dockerClient,
logger,
config,
discovery,
@@ -214,10 +213,19 @@ environment is compatible with techdocs.
You will have to install the `mkdocs` and `mkdocs-techdocs-core` package from
pip, as well as `graphviz` and `plantuml` from your OS package manager (e.g.
apt). See our
apt).
You can do so by including the following lines in the last step of your
`Dockerfile`:
```Dockerfile
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip3 install mkdocs-techdocs-core==0.0.16
```
Please be aware that the version requirement could change, you need to check our
[`Dockerfile`](https://github.com/backstage/techdocs-container/blob/main/Dockerfile)
for the latest requirements. You should be trying to match your `Dockerfile`
with this one.
and make sure to match with it.
Note: We recommend Python version 3.7 or higher.
+81
View File
@@ -82,3 +82,84 @@ Caveat: Currently TechDocs sites built using URL Reader will be cached for 30
minutes which means they will not be re-built if new changes are made within 30
minutes. This cache invalidation will be replaced by commit timestamp based
implementation very soon.
## How to use a custom TechDocs home page?
### 1st way: TechDocsCustomHome with a custom configuration
As an example, in your main App.tsx:
```tsx
import {
TechDocsCustomHome,
PanelType,
TechDocsReaderPage,
} from '@backstage/plugin-techdocs';
import { Entity } from '@backstage/catalog-model';
const tabsConfig = [
{
label: 'Custom Tab',
panels: [
{
title: 'Custom Documents Cards 1',
description:
'Explore your internal technical ecosystem through documentation.',
panelType: 'DocsCardGrid' as PanelType,
// optional, is applied to a container of the panel (excludes header of panel)
panelCSS: { maxHeight: '400px', overflow:'auto' },
filterPredicate: (entity: Entity) => !!entity.metadata.annotations?.['customCardAnnotationOne'];
},
{
title: 'Custom Documents Cards 2',
description:
'Explore your internal technical ecosystem through documentation.',
panelType: 'DocsCardGrid' as PanelType,
panelCSS: { maxHeight: '400px', overflow:'auto' },
filterPredicate: (entity: Entity) => !!entity.metadata.annotations?.['customCardAnnotationTwo'];
},
],
},
{
label: 'Overview',
panels: [
{
title: 'Overview',
description:
'Explore your internal technical ecosystem through documentation.',
panelType: 'DocsTable' as PanelType,
filterPredicate: () => true,
},
],
},
];
const routes = (
<FlatRoutes>
<Route
path="/docs"
element={<TechDocsCustomHome tabsConfig={tabsConfig} />}
/>
<Route
path="/docs/:namespace/:kind/:name/*"
element={<TechDocsReaderPage />}
/>
</FlatRoutes>
```
An example of tabsConfig that corresponds to the default documentation home page
can be found at `plugins/techdocs/src/home/components/TechDocsHome.tsx`.
Currently `panelType` has DocsCardGrid and DocsTable available. We currently
recommend that DocsCardGrid can be optionally vertically stacked by setting a
maxHeight using `panelCSS`, and DocsTable to be in a tab by itself.
### 2nd way: Custom home page plugin
A custom home page plugin can be built that uses the components extensions
DocsCardGrid and DocsTable, exported from @backstage/techdocs. They both take a
array of documentation entities ( i.e.have a 'backstage.io/techdocs-ref'
annotation ) as an 'entities' attribute.
For a reference to the React structure of the default home page, please refer to
`plugins/techdocs/src/home/components/TechDocsCustomHome.tsx`.
+22 -5
View File
@@ -119,6 +119,7 @@ techdocs:
Create a dedicated AWS S3 bucket for the storage of TechDocs sites.
[Refer to the official documentation](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-bucket.html).
[Terraform example](https://github.com/backstage/backstage/blob/master/contrib/terraform/techdocs-s3-storage/terraform.tf).
TechDocs will publish documentation to this bucket and will fetch files from
here to serve documentation in Backstage. Note that the bucket names are
@@ -135,13 +136,29 @@ techdocs:
bucketName: 'name-of-techdocs-storage-bucket'
```
**3a. (Recommended) Setup authentication the AWS way, using environment
**3. Create minimal AWS IAM policies to manage TechDocs**
To _write_ TechDocs into the S3 bucket the IAM policy needs to have at a minimum
permissions to:
- `s3:ListBucket` to retrieve bucket metadata
- `s3:PutObject` to upload files to the bucket
To _read_ TechDocs from the S3 bucket the IAM policy needs to have at a minimum
permissions to:
- `s3:ListBucket` - To retrieve bucket metadata
- `s3:GetObject` - To retrieve files from the bucket
**4a. (Recommended) Setup authentication the AWS way, using environment
variables**
You should follow the
[AWS security best practices guide for authentication](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html).
TechDocs needs access to read files and metadata of the S3 bucket.
TechDocs needs access to read files and metadata of the S3 bucket. So if you are
creating a policy for a user you want to make sure it is granted access to
ListBucket, GetObject and PutObject.
If the environment variables
@@ -166,7 +183,7 @@ more in
The AWS Region of the bucket is optional since TechDocs uses AWS SDK V2 and not
V3.
**3b. Authentication using app-config.yaml**
**4b. Authentication using app-config.yaml**
AWS credentials and region can be provided to the AWS SDK via `app-config.yaml`.
If the configs below are present, they will be used over existing `AWS_*`
@@ -187,7 +204,7 @@ techdocs:
Refer to the
[official AWS documentation for obtaining the credentials](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/getting-your-credentials.html).
**3c. Authentication using an assumed role** Users with multiple AWS accounts
**4c. Authentication using an assumed role** Users with multiple AWS accounts
may want to use a role for S3 storage that is in a different AWS account. Using
the `roleArn` parameter as seen below, you can instruct the TechDocs publisher
to assume a role before accessing S3.
@@ -207,7 +224,7 @@ Note: Assuming a role requires that primary credentials are already configured
at `AWS.config.credentials`. Read more about
[assuming roles in AWS](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html).
**4. That's it!**
**5. That's it!**
Your Backstage app is now ready to use AWS S3 for TechDocs, to store and read
the static generated documentation files. When you start the backend of the app,
+28
View File
@@ -135,3 +135,31 @@ const themeOptions = createThemeOptions({
},
});
```
## Custom Logo
In addition to a custom theme, you can also customize the logo displayed at the
far top left of the site.
In your frontend app, locate `src/components/Root/` folder. You'll find two
components:
- `LogoFull.tsx` - A larger logo used when the Sidebar navigation is opened.
- `LogoIcon.tsx` - A smaller logo used when the sidebar navigation is closed.
To replace the images, you can simply replace the relevant code in those
components with raw SVG definitions.
You can also use another web image format such as PNG by importing it. To do
this, place your new image into a new subdirectory such as
`src/components/Root/logo/my-company-logo.png`, and then add this code:
```jsx
import MyCustomLogoFull from './logo/my-company-logo.png';
//...
const LogoFull = () => {
return <img src={MyCustomLogoFull} />;
};
```
@@ -27,30 +27,30 @@ package.json. Backstage Apps are set up as monorepos with
[yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/). Since
CircleCI is a frontend UI plugin, it goes in `app` rather than `backend`.
2. Add the plugin itself to the App:
2. Add the `EntityCircleCIContent` extension to the entity pages in the app:
```js
// packages/app/src/plugins.ts
export { plugin as Circleci } from '@backstage/plugin-circleci';
```diff
// packages/app/src/components/catalog/EntityPage.tsx
+import {
+ EntityCircleCIContent,
+ isCircleCIAvailable,
+} from '@backstage/plugin-circleci';
...
const cicdContent = (
<EntitySwitch>
...
+ <EntitySwitch.Case if={isCircleCIAvailable}>
+ <EntityCircleCIContent />
+ </EntitySwitch.Case>;
</EntitySwitch>
);
```
3. Register the plugin router:
```jsx
// packages/app/src/components/catalog/EntityPage.tsx
import { Router as CircleCIRouter } from '@backstage/plugin-circleci';
// Then somewhere inside <EntityPageLayout>
<EntityPageLayout.Content
path="/ci-cd/*"
title="CI/CD"
element={<CircleCIRouter />}
/>;
```
Note that stand-alone plugins that are not "attached" to the Software Catalog
would be added outside the `EntityPage`.
This is just one example, but each Backstage instance may integrate content or
cards to suit their needs on different pages, tabs, etc. Note that stand-alone
plugins that are not "attached" to the Software Catalog would be added outside
the `EntityPage`.
4. [Optional] Add proxy config:
+2 -1
View File
@@ -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`:
+26
View File
@@ -39,3 +39,29 @@ The target is composed of four parts:
- The path within each repository to find the catalog YAML file. This will
usually be `/catalog-info.yaml` or a similar variation for catalog files
stored in the root directory of each repository.
## Custom repository processing
The Bitbucket Discovery Processor will by default emit a location for each
matching repository for further processing by other processors. However, it is
possible to override this functionality and take full control of how each
matching repository is processed.
`BitbucketDiscoveryProcessor.fromConfig` takes an optional parameter
`options.parser` where you can set your own parser to be used for each matched
repository.
```typescript
const customRepositoryParser: BitbucketRepositoryParser = async function* customRepositoryParser({
client,
repository,
}) {
// Custom logic for interpret the matching repository.
// See defaultRepositoryParser for an example
};
const processor = BitbucketDiscoveryProcessor.fromConfig(env.config, {
parser: customRepositoryParser,
logger: env.logger,
});
```
+16 -12
View File
@@ -3,28 +3,32 @@ id: installation
title: Datadog RUM Installation
sidebar_label: Installation
# prettier-ignore
description: Adding Datadog RUM to Your App
description: Adding Datadog Real User Monitoring (RUM) to Your App
---
There is a basic [Datadog](https://docs.datadoghq.com/real_user_monitoring/)
Datadog Real User Monitoring (RUM) allows you to visualize and analyze the
real-time performance and user journeys of your application's individual users.
This is an option to profile and monitor the user experience of your Backstage
installation.
There is a basic [Datadog RUM](https://docs.datadoghq.com/real_user_monitoring/)
integration built into Backstage. You can enable it by adding the following to
your app configuration:
your `app-config.yaml`:
```yaml
app:
datadogRum:
clientToken: '123456789'
applicationId: qwerty
# site: # datadoghq.eu default = datadoghq.com
# env: # optional
# site: datadoghq.eu
# env: 'staging'
```
Replace the clientToken and applicationId with the ones generated for you
Datadog.
The `clientToken` and `applicationId` are generated from the Datadog RUM page
following
[these instructions](https://docs.datadoghq.com/real_user_monitoring/browser/).
optional arguments:
There are two optional arguments:
```
site: datadoghq.eu # default equals datadoghq.com
env: dev # allow to specify the environment
```
- `site`: The Datadog site of your organization; defaults to `datadoghq.com`
- `env`: The application environment for Datadog events (no default)
+17 -24
View File
@@ -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`.
![permissions](../../assets/integrations/github/permissions.png)
**Please note that when you change permissions, the app owner will get an email
that must be approved first before the changes are applied.**
![email](../../assets/integrations/github/email.png)
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`.
+48 -25
View File
@@ -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)]
![UI with different components highlighted](../assets/architecture-overview/core-vs-plugin-components-highlighted.png)
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)]
![The lighthouse plugin UI](../assets/architecture-overview/lighthouse-plugin.png)
@@ -67,33 +67,41 @@ is available at
### Installing plugins
Plugins are typically loaded by the UI in your Backstage applications
`plugins.ts` file. For example,
[here](https://github.com/backstage/backstage/blob/master/packages/app/src/plugins.ts)
is that file in the Backstage sample app.
Plugins are typically installed as React components in your Backstage
application. For example,
[here](https://github.com/backstage/backstage/blob/master/packages/app/src/App.tsx)
is a file that imports many full-page plugins in the Backstage sample app.
Plugins can be enabled, and passed configuration in `apis.ts`. For example,
[here](https://github.com/backstage/backstage/blob/master/packages/app/src/apis.ts)
is that file in the Backstage sample app.
This is how the Lighthouse plugin would be enabled in a typical Backstage
application:
An example of one of these plugin components is the `CatalogIndexPage`, which is
a full-page view that allows you to browse entities in the Backstage catalog. It
is installed in the app by importing it and adding it as an element like this:
```tsx
import { ApiHolder, ApiRegistry } from '@backstage/core';
import {
lighthouseApiRef,
LighthouseRestApi,
} from '@backstage/plugin-lighthouse';
import { CatalogIndexPage } from '@backstage/plugin-catalog';
const builder = ApiRegistry.builder();
...
export const lighthouseApi = new LighthouseRestApi(/* URL of the lighthouse microservice! */);
builder.add(lighthouseApiRef, lighthouseApi);
export default builder.build() as ApiHolder;
const routes = (
<FlatRoutes>
...
<Route path="/catalog" element={<CatalogIndexPage />} />
...
</FlatRoutes>
);
```
Note that we use `"/catalog"` as our path to this plugin page, but we can choose
any route we want for the page, as long as it doesn't collide with the routes
that we choose for the other plugins in the app.
These components that are exported from plugins are referred to as "Plugin
Extension Components", or "Extension Components". They are regular React
components, but in addition to being able to be rendered by React, they also
contain various pieces of metadata that is used to wire together the entire app.
Extension components are created using `create*Extension` methods, which you can
read more about in the
[composability documentation](../plugins/composability.md).
As of this moment, there is no config based install procedure for plugins. Some
code changes are required.
@@ -108,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.
![tech radar plugin ui](../assets/architecture-overview/tech-radar-plugin.png)
@@ -174,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
+16 -16
View File
@@ -6,37 +6,37 @@ description: Guidelines for how to use the Backstage logos and icons
---
Guidelines for how to use the Backstage logo and icon can be found
[here](/logo_assets/Backstage_Identity_Assets_Overview.pdf). The assets below
are all in `.svg` format. Other formats are available in the
[here](https://backstage.io/logo_assets/Backstage_Identity_Assets_Overview.pdf).
The assets below are all in `.svg` format. Other formats are available in the
[repository](https://github.com/backstage/backstage/tree/master/microsite/static/logo_assets).
## Backstage logo
<a href="/logo_assets/svg/Logo_White.svg">
<img src="/logo_assets/svg/Logo_White.svg" width="600" />
<a href="https://backstage.io/logo_assets/svg/Logo_White.svg">
<img src="https://backstage.io/logo_assets/svg/Logo_White.svg" width="600" />
</a>
<a href="/logo_assets/svg/Logo_Teal.svg">
<img src="/logo_assets/svg/Logo_Teal.svg" width="600" />
<a href="https://backstage.io/logo_assets/svg/Logo_Teal.svg">
<img src="https://backstage.io/logo_assets/svg/Logo_Teal.svg" width="600" />
</a>
<a href="/logo_assets/svg/Logo_Black.svg">
<img src="/logo_assets/svg/Logo_Black.svg" width="600" style="background-color:white" />
<a href="https://backstage.io/logo_assets/svg/Logo_Black.svg">
<img src="https://backstage.io/logo_assets/svg/Logo_Black.svg" width="600" style="background-color:white" />
</a>
## Backstage icon
<div>
<a href="/logo_assets/svg/Icon_White.svg">
<img src="/logo_assets/svg/Icon_White.svg" width="180" height="180" />
<a href="https://backstage.io/logo_assets/svg/Icon_White.svg">
<img src="https://backstage.io/logo_assets/svg/Icon_White.svg" width="180" height="180" />
</a>
<a href="/logo_assets/svg/Icon_Teal.svg">
<img src="/logo_assets/svg/Icon_Teal.svg" width="180" height="180" />
<a href="https://backstage.io/logo_assets/svg/Icon_Teal.svg">
<img src="https://backstage.io/logo_assets/svg/Icon_Teal.svg" width="180" height="180" />
</a>
<a href="/logo_assets/svg/Icon_Gradient.svg">
<img src="/logo_assets/svg/Icon_Gradient.svg" width="180" height="180" />
<a href="https://backstage.io/logo_assets/svg/Icon_Gradient.svg">
<img src="https://backstage.io/logo_assets/svg/Icon_Gradient.svg" width="180" height="180" />
</a>
<a href="/logo_assets/svg/Icon_Black.svg">
<img src="/logo_assets/svg/Icon_Black.svg" width="180" height="180" style="background-color:white" />
<a href="https://backstage.io/logo_assets/svg/Icon_Black.svg">
<img src="https://backstage.io/logo_assets/svg/Icon_Black.svg" width="180" height="180" style="background-color:white" />
</a>
</div>
+25 -35
View File
@@ -108,50 +108,40 @@ 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.
Stability: `2`.
#### Section: App API
### `cost-insights` [GitHub](https://github.com/backstage/backstage/tree/master/plugins/cost-insights)
The APIs used exclusively in the app, such as `createApp` and the system icons.
A frontend plugin that allows users to visualize, understand and optimize your
team's cloud costs.
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: `1`
### `create-app` [GitHub](https://github.com/backstage/backstage/tree/master/packages/create-app/)
@@ -359,7 +349,7 @@ https://github.com/backstage/backstage/issues/2771.
### `tech-radar` [GitHub](https://github.com/backstage/backstage/tree/master/plugins/tech-radar/)
Visualize the your company's official guidelines of different areas of software
Visualize your company's official guidelines of different areas of software
development.
Stability: `0`
+148 -3
View File
@@ -1,7 +1,152 @@
---
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!
## Making Use of a Database
The Backstage backend comes with a builtin facility for SQL database access.
Most plugins that have persistence needs will choose to make use of this
facility, so that Backstage operators can manage database needs uniformly.
As part of the environment object that is passed to your `createPlugin`
function, there is a `database` field. You can use that to get a
[Knex](http://knexjs.org/) connection object.
```ts
// in packages/backend/src/plugins/carmen.ts
export default async function createPlugin(env: PluginEnvironment) {
const db: Knex<any, unknown[]> = await env.database.getClient();
// You will then pass this client into your actual plugin implementation
// code, maybe similar to the following:
const model = new CarmenDatabaseModel(db);
return await createRouter({
model: model,
logger: env.logger,
});
}
```
You may note that the `getClient` call has no parameters. This is because all
plugin database needs are configured under the `backend.database` config key of
your `app-config.yaml`. The framework may even make sure behind the scenes that
the logical database is created automatically if it doesn't exist, based on
rules that the Backstage operator decides on.
The framework does not handle database schema migrations for you, however. The
builtin plugins in the main repo have chosen to use the Knex library to manage
schema migrations as well, but you can do so in any manner that you see fit.
See the [Knex library documentation](http://knexjs.org/) for examples and
details on how to write schema migrations and perform SQL queries against your
database..
@@ -1,7 +1,7 @@
---
id: integrating-plugin-into-service-catalog
title: Integrate into the Service Catalog
description: Documentation on How to integrate plugin into service catalog
description: How to integrate a plugin into service catalog
---
> This is an advanced use case and currently is an experimental feature. Expect

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