@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Exports `CatalogLayout` and `CreateComponentButton` for catalog customization.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/codemods': patch
|
||||
---
|
||||
|
||||
Fix execution of `jscodeshift` on windows.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-welcome': patch
|
||||
---
|
||||
|
||||
Australian Greeting
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/core': patch
|
||||
---
|
||||
|
||||
Exported SignInProviderConfig to strongly type SignInPage providers
|
||||
@@ -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`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Add title prop in SupportButton component
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
Adding support for user owned document filter for TechDocs custom Homepage
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': minor
|
||||
---
|
||||
|
||||
Added support for Datadog rum events
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-proxy-backend': patch
|
||||
---
|
||||
|
||||
Bump http-proxy-middleware from 0.19.2 to 2.0.0
|
||||
+29
-1
@@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
_
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
yarn lint-staged
|
||||
@@ -4,6 +4,7 @@ microsite
|
||||
coverage
|
||||
*.hbs
|
||||
templates
|
||||
api-report.md
|
||||
plugins/scaffolder-backend/sample-templates
|
||||
.vscode
|
||||
dist-types
|
||||
|
||||
+32
-27
@@ -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 team’s 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 team’s engineering dependencies. |
|
||||
| [Oriflame](https://www.oriflame.com/) | [Oriflame](https://github.com/oriflame) | Internal developer portal for services, single page apps and packages overview, API documentation, technical guides, tech-radar and more. |
|
||||
| [Booz Allen Hamilton](https://www.boozallen.com/) | [Jason Miller](https://github.com/JasonMiller-BAH) | Developer portal for a full-stack software development ecosystem that accelerates consistent and repeatable Modern Software Development practices for internal innovation and investments. |
|
||||
| [Netflix](https://www.netflix.com/) | [bleathem](https://github.com/bleathem) | Our Backstage implementation will be the front door to a unified experience connecting our internal platform products across important workflows with integrated knowledge and support. |
|
||||
| [b.well](https://www.icanbwell.com/) | [Jacob Rosales](https://github.com/jrosales) | Foundation for our engineering portal and cloud insights. |
|
||||
| [PagerDuty](https://www.pagerduty.com/) | [Mark Shaw](https://github.com/markshawtoronto) | Developer portal, initially focused on software templates and tech-docs. |
|
||||
|
||||
-163
@@ -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
@@ -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`
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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 }}
|
||||
+2
-15
@@ -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 }}
|
||||
@@ -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.
|
||||
-8
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
+1
-1
@@ -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}/*",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"cypress": "^6.4.0",
|
||||
"cypress": "^7.3.0",
|
||||
"typescript": "^4.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 |
@@ -31,8 +31,8 @@ auth:
|
||||
providers:
|
||||
gitlab:
|
||||
development:
|
||||
clientId: ${AUTH_GITLAB_APPLICATION_ID}
|
||||
clientSecret: ${AUTH_GITLAB_SECRET}
|
||||
clientId: ${AUTH_GITLAB_CLIENT_ID}
|
||||
clientSecret: ${AUTH_GITLAB_CLIENT_SECRET}
|
||||
## uncomment if using self-hosted GitLab
|
||||
# audience: https://gitlab.company.com
|
||||
```
|
||||
|
||||
@@ -77,7 +77,6 @@ built-in providers:
|
||||
+
|
||||
const app = createApp({
|
||||
apis,
|
||||
plugins: Object.values(plugins),
|
||||
+ components: {
|
||||
+ SignInPage: props => (
|
||||
+ <SignInPage
|
||||
@@ -96,7 +95,6 @@ To also allow unauthenticated guest access, use the `providers` prop for
|
||||
```diff
|
||||
const app = createApp({
|
||||
apis,
|
||||
plugins: Object.values(plugins),
|
||||
+ components: {
|
||||
+ SignInPage: props => (
|
||||
+ <SignInPage
|
||||
|
||||
@@ -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 <path> 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 <name> 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 <format> Format to print the configuration in, either json or yaml [yaml]
|
||||
@@ -486,6 +508,7 @@ Usage: backstage-cli config:check [options]
|
||||
|
||||
Options:
|
||||
--package <name> Only load config schema that applies to the given package
|
||||
--lax Do not require environment variables to be set
|
||||
--config <path> Config files to load instead of app-config.yaml (default: [])
|
||||
-h, --help display help for command
|
||||
```
|
||||
|
||||
+12
-2
@@ -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
|
||||
|
||||
@@ -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,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).
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 don’t 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 |
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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`:
|
||||
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
```
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -22,8 +22,8 @@ entities that mirror your org setup.
|
||||
The processor that performs the import, `GithubOrgReaderProcessor`, comes
|
||||
installed with the default setup of Backstage.
|
||||
|
||||
If you replace the set of processors in your installation using that facility of
|
||||
the catalog builder class, you can import and add it as follows.
|
||||
If you have _replaced_ the set of processors in your installation using
|
||||
`replaceProcessors`, you can import and add it as follows:
|
||||
|
||||
```ts
|
||||
// Typically in packages/backend/src/plugins/catalog.ts
|
||||
@@ -45,30 +45,23 @@ catalog:
|
||||
locations:
|
||||
- type: github-org
|
||||
target: https://github.com/my-org-name
|
||||
processors:
|
||||
githubOrg:
|
||||
providers:
|
||||
- target: https://github.com
|
||||
apiBaseUrl: https://api.github.com
|
||||
token: ${GITHUB_TOKEN}
|
||||
```
|
||||
|
||||
If Backstage is configured to use GitHub Apps authentication you must grant
|
||||
`Read-Only` access for `Members` under `Organization` in order to ingest users
|
||||
correctly. You can modify the app's permissions under the organization settings,
|
||||
`https://github.com/organizations/{ORG}/settings/apps/{APP_NAME}/permissions`.
|
||||

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

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

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

|
||||
|
||||
@@ -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.
|
||||
|
||||

|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user