Merge branch 'master' into ryanv/infocard-forward-classes-prop
@@ -1,5 +1,6 @@
|
||||
**/node_modules/**
|
||||
**/dist/**
|
||||
**/dist-types/**
|
||||
**/storybook-static/**
|
||||
**/coverage/**
|
||||
**/build/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: 'Feature Request'
|
||||
about: 'Suggest new features and changes'
|
||||
labels: help wanted
|
||||
labels: enhancement
|
||||
---
|
||||
|
||||
<!--- Provide a general summary of the feature request in the Title above -->
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: 'RFC'
|
||||
about: 'Request For Comments (RFC) from the community'
|
||||
labels: rfc
|
||||
title: '[RFC] <name>'
|
||||
---
|
||||
|
||||
**Status:** Open for comments
|
||||
|
||||
<!--- Open for comments |Closed for comments (RFC no longer maintained) --->
|
||||
|
||||
## Need
|
||||
|
||||
<!--- Why are we proposing this change? Why is this the problem we’re trying to address and what benefits/impact do we expect to get from this --->
|
||||
|
||||
## Proposal
|
||||
|
||||
<!--- The proposed approach. Describe the proposal in as much detail as needed for reviewers to give concrete feedback. Take special care in this section to describe any implications on data privacy or security. --->
|
||||
|
||||
## Alternatives
|
||||
|
||||
<!--- What alternatives to the proposed solution were considered? What criteria/data was used to discard these --->
|
||||
|
||||
## Risks
|
||||
|
||||
<!--- What other things happening could conflict or compete (for example for resources) with the proposal? What risk are there and how do we plan to handle them --->
|
||||
@@ -4,7 +4,9 @@
|
||||
That makes it easier to understand the change so we can :shipit: faster. -->
|
||||
|
||||
#### :heavy_check_mark: Checklist
|
||||
|
||||
<!--- Put an `x` in all the boxes that apply: -->
|
||||
|
||||
- [ ] All tests are passing `yarn test`
|
||||
- [ ] Screenshots attached (for UI changes)
|
||||
- [ ] Relevant documentation updated
|
||||
|
||||
@@ -14,7 +14,37 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0 # Required to retrieve git history
|
||||
- run: yarn install && yarn build-storybook
|
||||
|
||||
# Beginning of yarn setup, keep in sync between all workflows, see ci.yml
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/ # Needed for auth
|
||||
- name: cache all node_modules
|
||||
id: cache-modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }}
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
if: steps.cache-modules.outputs.cache-hit != 'true'
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
if: steps.cache-modules.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
# End of yarn setup
|
||||
|
||||
- run: yarn build-storybook
|
||||
|
||||
- uses: chromaui/action@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
name: Frontend CI
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'microsite/**'
|
||||
jobs:
|
||||
build:
|
||||
verify:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
@@ -20,47 +20,67 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: fetch branch master
|
||||
run: git fetch origin master
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: cache node_modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
# Beginning of yarn setup, keep in sync between all workflows.
|
||||
# TODO(Rugvip): move this to composite action once all features we use are supported
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/ # Needed for auth
|
||||
|
||||
# Cache every node_modules folder inside the monorepo
|
||||
- name: cache all node_modules
|
||||
id: cache-modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
# We use both yarn.lock and package.json as cache keys to ensure that
|
||||
# changes to local monorepo packages bust the cache.
|
||||
key: ${{ runner.os }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }}
|
||||
|
||||
# If we get a cache hit for node_modules, there's no need to bring in the global
|
||||
# yarn cache or run yarn install, as all dependencies will be installed already.
|
||||
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
if: steps.cache-modules.outputs.cache-hit != 'true'
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
if: steps.cache-modules.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: yarn install
|
||||
if: steps.cache-modules.outputs.cache-hit != 'true'
|
||||
run: yarn install --frozen-lockfile
|
||||
# End of yarn setup
|
||||
|
||||
- name: check for yarn.lock changes
|
||||
id: yarn-lock
|
||||
run: git diff --quiet origin/master HEAD -- yarn.lock
|
||||
continue-on-error: true
|
||||
|
||||
- name: yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: verify doc links
|
||||
run: node docs/verify-links.js
|
||||
|
||||
- name: prettier
|
||||
run: yarn prettier:check
|
||||
|
||||
- name: lint
|
||||
run: yarn lerna -- run lint --since origin/master
|
||||
|
||||
- name: type checking and declarations
|
||||
run: yarn tsc --incremental false
|
||||
run: yarn tsc:full
|
||||
|
||||
- name: build changed packages
|
||||
if: ${{ steps.yarn-lock.outcome == 'success' }}
|
||||
# Need to build all dependencies as well to be able to run tests later
|
||||
run: yarn lerna -- run build --since origin/master --include-dependencies
|
||||
run: yarn lerna -- run build --since origin/master
|
||||
|
||||
- name: build all packages
|
||||
if: ${{ steps.yarn-lock.outcome == 'failure' }}
|
||||
@@ -80,5 +100,15 @@ jobs:
|
||||
- name: verify plugin template
|
||||
run: yarn lerna -- run diff -- --check
|
||||
|
||||
- name: verify storybook
|
||||
run: yarn workspace storybook build-storybook
|
||||
- name: ensure clean working directory
|
||||
run: |
|
||||
if files=$(git ls-files --exclude-standard --others --modified) && [[ -z "$files" ]]; then
|
||||
exit 0
|
||||
else
|
||||
echo ""
|
||||
echo "Working directory has been modified:"
|
||||
echo ""
|
||||
git status --short
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,12 +1,13 @@
|
||||
name: CLI Test Windows
|
||||
name: E2E Test Windows
|
||||
|
||||
# Building on windows is really slow, so this workflow is separate from cli.yml and only builds on changes
|
||||
# Building on windows is really slow, so this workflow is separate from e2e.yml and only builds on changes
|
||||
# to the cli itself. They're more likely to introduce issues on windows, compared to changes to core and yarn.lock.
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/cli-win.yml'
|
||||
- '.github/workflows/e2e-win.yml'
|
||||
- 'packages/cli/**'
|
||||
- 'packages/e2e/**'
|
||||
- 'packages/create-app/**'
|
||||
|
||||
jobs:
|
||||
@@ -25,6 +26,13 @@ jobs:
|
||||
name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# Beginning of yarn setup, keep in sync between all workflows, see ci.yml
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/ # Needed for auth
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
@@ -32,16 +40,15 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
# End of yarn setup
|
||||
|
||||
- run: yarn tsc
|
||||
- run: yarn build
|
||||
- name: verify app and plugin creation
|
||||
run: node ${{ github.workspace }}/packages/cli/e2e-test/cli-e2e-test.js
|
||||
- name: yarn build
|
||||
run: yarn build --ignore example-app --ignore example-backend --ignore @techdocs/cli
|
||||
- name: run E2E test
|
||||
run: yarn workspace e2e-test start
|
||||
@@ -1,11 +1,10 @@
|
||||
name: CLI Test
|
||||
name: E2E Test Linux
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'microsite/**'
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -34,30 +33,44 @@ jobs:
|
||||
name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
# Beginning of yarn setup, keep in sync between all workflows, see ci.yml
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/ # Needed for auth
|
||||
- name: cache all node_modules
|
||||
id: cache-modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }}
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
if: steps.cache-modules.outputs.cache-hit != 'true'
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
if: steps.cache-modules.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
# End of yarn setup
|
||||
|
||||
- run: yarn tsc
|
||||
- run: yarn build
|
||||
- name: verify app and plugin creation
|
||||
- name: yarn build
|
||||
run: yarn build --ignore example-app --ignore example-backend --ignore @techdocs/cli
|
||||
- name: run E2E test
|
||||
run: |
|
||||
sudo sysctl fs.inotify.max_user_watches=524288
|
||||
yarn workspace e2e-test start
|
||||
env:
|
||||
POSTGRES_HOST: localhost
|
||||
POSTGRES_PORT: ${{ job.services.postgres.ports[5432] }}
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
run: |
|
||||
sudo sysctl fs.inotify.max_user_watches=524288
|
||||
node ${{ github.workspace }}/packages/cli/e2e-test/cli-e2e-test.js
|
||||
@@ -0,0 +1,60 @@
|
||||
name: Master Build Windows
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
|
||||
env:
|
||||
CI: true
|
||||
NODE_OPTIONS: --max-old-space-size=4096
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# Beginning of yarn setup, keep in sync between all workflows, see ci.yml
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/ # Needed for auth
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
# End of yarn setup
|
||||
|
||||
- name: lint
|
||||
run: yarn lerna -- run lint
|
||||
|
||||
- name: type checking and declarations
|
||||
run: yarn tsc:full
|
||||
|
||||
- name: verify type dependencies
|
||||
run: yarn lint:type-deps
|
||||
|
||||
- name: test
|
||||
run: yarn lerna -- run test
|
||||
|
||||
- name: Discord notification
|
||||
if: ${{ failure() }}
|
||||
uses: Ilshidur/action-discord@0.2.0
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
with:
|
||||
args: 'Windows master build failed https://github.com/{{GITHUB_REPOSITORY}}/actions/runs/{{GITHUB_RUN_ID}}'
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Master Build
|
||||
name: Main Master Build
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -18,35 +18,40 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: cache node_modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
# Beginning of yarn setup, keep in sync between all workflows, see ci.yml
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/ # Needed for auth
|
||||
|
||||
- name: cache all node_modules
|
||||
id: cache-modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }}
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
if: steps.cache-modules.outputs.cache-hit != 'true'
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
if: steps.cache-modules.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- name: yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
# End of yarn setup
|
||||
|
||||
- name: lint
|
||||
run: yarn lerna -- run lint
|
||||
|
||||
- name: type checking and declarations
|
||||
run: yarn tsc --incremental false
|
||||
run: yarn tsc:full
|
||||
|
||||
- name: build
|
||||
run: yarn build
|
||||
@@ -66,6 +71,14 @@ jobs:
|
||||
# Tags the commit with the version in the core package if the tag doesn't exist
|
||||
- uses: Klemensas/action-autotag@1.2.3
|
||||
with:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
package_root: "packages/core"
|
||||
tag_prefix: "v"
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
package_root: 'packages/core'
|
||||
tag_prefix: 'v'
|
||||
|
||||
- name: Discord notification
|
||||
if: ${{ failure() }}
|
||||
uses: Ilshidur/action-discord@0.2.0
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
with:
|
||||
args: 'Master build failed https://github.com/{{GITHUB_REPOSITORY}}/actions/runs/{{GITHUB_RUN_ID}}'
|
||||
|
||||
@@ -21,32 +21,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: cache node_modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/ # Needed for auth
|
||||
|
||||
# Skip caching of microsite dependencies, it keeps the global cache size
|
||||
# smaller, which make Windows builds a lot faster for the rest of the project.
|
||||
- name: yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: microsite
|
||||
|
||||
- name: build microsite
|
||||
run: yarn workspace backstage-microsite build
|
||||
run: yarn build
|
||||
working-directory: microsite
|
||||
|
||||
@@ -25,23 +25,6 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: find location of global yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: cache global yarn cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: cache node_modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
@@ -49,11 +32,18 @@ jobs:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/ # Needed for auth
|
||||
|
||||
- name: yarn install
|
||||
# We avoid caching in this workflow, as we're running an install of both the top-level
|
||||
# dependencies and the microsite. We leave it to the main master workflow to produce the
|
||||
# cache, as that results in a smaller bundle.
|
||||
- name: top-level yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: microsite yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: microsite
|
||||
|
||||
- name: build microsite
|
||||
run: yarn workspace backstage-microsite build
|
||||
run: yarn build
|
||||
working-directory: microsite
|
||||
|
||||
- name: build storybook
|
||||
run: yarn workspace storybook build-storybook
|
||||
|
||||
@@ -89,9 +89,7 @@ typings/
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Microsite build output
|
||||
microsite/build
|
||||
dist-types
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
.yarn
|
||||
dist
|
||||
microsite/build
|
||||
coverage
|
||||
*.hbs
|
||||
templates
|
||||
plugins/scaffolder-backend/sample-templates
|
||||
.vscode
|
||||
@@ -1,13 +1,15 @@
|
||||
| Organization | Contact | Description of Use |
|
||||
| --------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
|
||||
| [Spotify](https://www.spotify.com) | [@stefanalund](https://github.com/stefanalund) | 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 |
|
||||
| Organization | Contact | Description of Use |
|
||||
| -------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
|
||||
| [Spotify](https://www.spotify.com) | [@stefanalund](https://github.com/stefanalund) | 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 |
|
||||
|
||||
@@ -8,6 +8,21 @@ If you encounter issues while upgrading to a newer version, don't hesitate to re
|
||||
|
||||
> Collect changes for the next release below
|
||||
|
||||
- The backend plugin
|
||||
[service builder](https://github.com/spotify/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.
|
||||
|
||||
## v0.1.1-alpha.20
|
||||
|
||||
- Includes https://github.com/spotify/backstage/pull/2097 to resolve issues with create-plugin command.
|
||||
|
||||
## v0.1.1-alpha.19
|
||||
|
||||
### @backstage/create-app
|
||||
|
||||
- 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/spotify/backstage/issues/1536) gets sorted out, but for now you may need to install some plugins just to get pages to work.
|
||||
|
||||
@@ -4,12 +4,12 @@ This code of conduct outlines our expectations for participants within the **Spo
|
||||
|
||||
Our open source community strives to:
|
||||
|
||||
* **Be friendly and patient.**
|
||||
* **Be welcoming**: We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
|
||||
* **Be considerate**: Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language.
|
||||
* **Be respectful**: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.
|
||||
* **Be careful in the words that we choose**: we are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable.
|
||||
* **Try to understand why we disagree**: Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.
|
||||
- **Be friendly and patient.**
|
||||
- **Be welcoming**: We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
|
||||
- **Be considerate**: Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language.
|
||||
- **Be respectful**: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.
|
||||
- **Be careful in the words that we choose**: we are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable.
|
||||
- **Try to understand why we disagree**: Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.
|
||||
|
||||
## Definitions
|
||||
|
||||
@@ -18,7 +18,7 @@ Harassment includes, but is not limited to:
|
||||
- Offensive comments related to gender, gender identity and expression, sexual orientation, disability, mental illness, neuro(a)typicality, physical appearance, body size, race, age, regional discrimination, political or religious affiliation
|
||||
- Unwelcome comments regarding a person’s lifestyle choices and practices, including those related to food, health, parenting, drugs, and employment
|
||||
- Deliberate misgendering. This includes deadnaming or persistently using a pronoun that does not correctly reflect a person's gender identity. You must address people by the name they give you when not addressing them by their username or handle
|
||||
- Physical contact and simulated physical contact (eg, textual descriptions like “*hug*” or “*backrub*”) without consent or after a request to stop
|
||||
- Physical contact and simulated physical contact (eg, textual descriptions like “_hug_” or “_backrub_”) without consent or after a request to stop
|
||||
- Threats of violence, both physical and psychological
|
||||
- Incitement of violence towards any individual, including encouraging a person to commit suicide or to engage in self-harm
|
||||
- Deliberate intimidation
|
||||
@@ -39,7 +39,6 @@ Our open source community prioritizes marginalized people’s safety over privil
|
||||
- Communicating in a ‘tone’ you don’t find congenial
|
||||
- Criticizing racist, sexist, cissexist, or otherwise oppressive behavior or assumptions
|
||||
|
||||
|
||||
### Diversity Statement
|
||||
|
||||
We encourage everyone to participate and are committed to building a community for all. Although we will fail at times, we seek to treat everyone both as fairly and equally as possible. Whenever a participant has made a mistake, we expect them to take responsibility for it. If someone has been harmed or offended, it is our responsibility to listen carefully and respectfully, and do our best to right the wrong.
|
||||
@@ -53,18 +52,18 @@ If you experience or witness unacceptable behavior—or have any other concerns
|
||||
|
||||
- Your contact information.
|
||||
- Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional witnesses, please
|
||||
include them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public IRC logger), please include a link.
|
||||
include them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public IRC logger), please include a link.
|
||||
- Any additional information that may be helpful.
|
||||
|
||||
After filing a report, a representative will contact you personally, review the incident, follow up with any additional questions, and make a decision as to how to respond. If the person who is harassing you is part of the response team, they will recuse themselves from handling your incident. If the complaint originates from a member of the response team, it will be handled by a different member of the response team. We will respect confidentiality requests for the purpose of protecting victims of abuse.
|
||||
|
||||
### Attribution & Acknowledgements
|
||||
|
||||
We all stand on the shoulders of giants across many open source communities. We'd like to thank the communities and projects that established code of conducts and diversity statements as our inspiration:
|
||||
We all stand on the shoulders of giants across many open source communities. We'd like to thank the communities and projects that established code of conducts and diversity statements as our inspiration:
|
||||
|
||||
* [Django](https://www.djangoproject.com/conduct/reporting/)
|
||||
* [Python](https://www.python.org/community/diversity/)
|
||||
* [Ubuntu](http://www.ubuntu.com/about/about-ubuntu/conduct)
|
||||
* [Contributor Covenant](http://contributor-covenant.org/)
|
||||
* [Geek Feminism](http://geekfeminism.org/about/code-of-conduct/)
|
||||
* [Citizen Code of Conduct](http://citizencodeofconduct.org/)
|
||||
- [Django](https://www.djangoproject.com/conduct/reporting/)
|
||||
- [Python](https://www.python.org/community/diversity/)
|
||||
- [Ubuntu](http://www.ubuntu.com/about/about-ubuntu/conduct)
|
||||
- [Contributor Covenant](http://contributor-covenant.org/)
|
||||
- [Geek Feminism](http://geekfeminism.org/about/code-of-conduct/)
|
||||
- [Citizen Code of Conduct](http://citizencodeofconduct.org/)
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
---
|
||||
id: CONTRIBUTING
|
||||
title: Contributing
|
||||
---
|
||||
# Contributing to Backstage
|
||||
|
||||
Our vision for Backstage is for it to become the trusted standard toolbox (read: UX layer) for the open source infrastructure landscape. Think of it like Kubernetes for developer experience. We realize this is an ambitious goal. We can’t do it alone.
|
||||
|
||||
@@ -31,7 +28,7 @@ What kind of plugins should/could be created? Some inspiration from the 120+ plu
|
||||
|
||||
## Suggesting a plugin
|
||||
|
||||
If you start developing a plugin that you aim to release as open source, we suggest that you create a new [new Issue](https://github.com/spotify/backstage/issues/new?template=plugin_template.md). This helps the community know what plugins are in development.
|
||||
If you start developing a plugin that you aim to release as open source, we suggest that you create a new [new Issue](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). This helps the community know what plugins are in development.
|
||||
|
||||
You can also use this process if you have an idea for a good plugin but you hope that someone else will pick up the work.
|
||||
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
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.
|
||||
|
||||
# The safest way to build this image is to use `yarn docker-build`
|
||||
# The safest way to build this image is to use `yarn docker-build:app`
|
||||
|
||||
RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
@@ -29,16 +29,6 @@ For more information go to [backstage.io](https://backstage.io) or join our [Dis
|
||||
|
||||
A detailed project roadmap, including already delivered milestones, is available [here](https://backstage.io/docs/overview/roadmap).
|
||||
|
||||
## Overview
|
||||
|
||||
The Backstage platform consists of a number of different components:
|
||||
|
||||
- **app** - Main web application that users interact with. It's built up by a number of different _Plugins_. This repo contains an example implementation of an app (located in `packages/app`) and you can easily get started with your own app by [creating one](docs/getting-started/create-an-app.md).
|
||||
- [**plugins**](https://github.com/spotify/backstage/tree/master/plugins) - Each plugin is treated as a self-contained web app and can include almost any type of content. Plugins all use a common set of platform API's and reusable UI components. Plugins can fetch data either from the _backend_ or through any RESTful API exposed through the _proxy_.
|
||||
- [**service catalog**](https://github.com/spotify/backstage/tree/master/packages/backend) - Service that holds the model of your software ecosystem, including organisational information and what team owns what software. The backend also has a Plugin model for extending its graph.
|
||||
- [**proxy**](https://github.com/spotify/backstage/tree/master/plugins/proxy-backend) - Terminates HTTPS and exposes any RESTful API to Plugins.
|
||||
- **identity** - A backend service that holds your organisation's metadata.
|
||||
|
||||
## Getting Started
|
||||
|
||||
There are two different ways to get started with Backstage, either by creating a standalone app, or by cloning this repo. Which method you use depends on what you're planning to do.
|
||||
@@ -71,7 +61,7 @@ Take a look at the [Getting Started](https://backstage.io/docs/getting-started/i
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Main documentation](https://backstage.io/docs/overview/what-is-backstage)
|
||||
- [Main documentation](https://backstage.io/docs)
|
||||
- [Service Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview)
|
||||
- [Architecture](https://backstage.io/docs/overview/architecture-terminology) ([Decisions](https://backstage.io/docs/architecture-decisions/adrs-overview))
|
||||
- [Designing for Backstage](https://backstage.io/docs/dls/design)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
app:
|
||||
baseUrl: http://localhost:3000
|
||||
|
||||
backend:
|
||||
baseUrl: http://localhost:7000
|
||||
listen:
|
||||
port: 7000
|
||||
cors:
|
||||
origin: http://localhost:3000
|
||||
methods: [GET, POST, PUT, DELETE]
|
||||
credentials: true
|
||||
@@ -1,34 +1,24 @@
|
||||
app:
|
||||
title: Backstage Example App
|
||||
baseUrl: http://localhost:3000
|
||||
baseUrl: http://localhost:7000
|
||||
|
||||
backend:
|
||||
baseUrl: http://localhost:7000
|
||||
listen:
|
||||
port: 7000
|
||||
cors:
|
||||
origin: http://localhost:3000
|
||||
methods: [GET, POST, PUT, DELETE]
|
||||
credentials: true
|
||||
database:
|
||||
client: sqlite3
|
||||
connection: ':memory:'
|
||||
|
||||
# See README.md in the proxy-backend plugin for information on the configuration format
|
||||
proxy:
|
||||
'/circleci/api':
|
||||
target: 'https://circleci.com/api/v1.1'
|
||||
changeOrigin: true
|
||||
pathRewrite:
|
||||
'^/proxy/circleci/api/': '/'
|
||||
'/circleci/api': https://circleci.com/api/v1.1
|
||||
'/jenkins/api':
|
||||
target: 'http://localhost:8080'
|
||||
changeOrigin: true
|
||||
target: http://localhost:8080
|
||||
headers:
|
||||
Authorization:
|
||||
$secret:
|
||||
env: JENKINS_BASIC_AUTH_HEADER
|
||||
pathRewrite:
|
||||
'^/proxy/jenkins/api/': '/'
|
||||
|
||||
organization:
|
||||
name: Spotify
|
||||
@@ -50,6 +40,50 @@ newrelic:
|
||||
baseUrl: 'https://api.newrelic.com/v2'
|
||||
key: NEW_RELIC_REST_API_KEY
|
||||
|
||||
lighthouse:
|
||||
baseUrl: http://localhost:3003
|
||||
|
||||
catalog:
|
||||
rules:
|
||||
- allow: [Component, API, Group, Template, Location]
|
||||
processors:
|
||||
githubApi:
|
||||
privateToken:
|
||||
$secret:
|
||||
env: GITHUB_PRIVATE_TOKEN
|
||||
bitbucketApi:
|
||||
username:
|
||||
$secret:
|
||||
env: BITBUCKET_USERNAME
|
||||
appPassword:
|
||||
$secret:
|
||||
env: BITBUCKET_APP_PASSWORD
|
||||
gitlabApi:
|
||||
privateToken:
|
||||
$secret:
|
||||
env: GITLAB_PRIVATE_TOKEN
|
||||
azureApi:
|
||||
privateToken:
|
||||
$secret:
|
||||
env: AZURE_PRIVATE_TOKEN
|
||||
exampleEntityLocations:
|
||||
github:
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-order-component.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/podcast-api-component.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/queue-proxy-component.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/searcher-component.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-lib-component.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/www-artist-component.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/shuffle-api-component.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml
|
||||
- https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/hello-world-api.yaml
|
||||
- https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/streetlights-api.yaml
|
||||
|
||||
auth:
|
||||
providers:
|
||||
google:
|
||||
@@ -82,10 +116,9 @@ auth:
|
||||
audience:
|
||||
$secret:
|
||||
env: GITLAB_BASE_URL
|
||||
# saml:
|
||||
# development:
|
||||
# entryPoint: "http://localhost:7001/"
|
||||
# issuer: "passport-saml"
|
||||
saml:
|
||||
entryPoint: 'http://localhost:7001/'
|
||||
issuer: 'passport-saml'
|
||||
okta:
|
||||
development:
|
||||
clientId:
|
||||
@@ -122,3 +155,14 @@ auth:
|
||||
domain:
|
||||
$secret:
|
||||
env: AUTH_AUTH0_DOMAIN
|
||||
microsoft:
|
||||
development:
|
||||
clientId:
|
||||
$secret:
|
||||
env: AUTH_MICROSOFT_CLIENT_ID
|
||||
clientSecret:
|
||||
$secret:
|
||||
env: AUTH_MICROSOFT_CLIENT_SECRET
|
||||
tenantId:
|
||||
$secret:
|
||||
env: AUTH_MICROSOFT_TENANT_ID
|
||||
|
||||
@@ -3,10 +3,10 @@ kind: Component
|
||||
metadata:
|
||||
name: backstage
|
||||
description: |
|
||||
Backstage is an open-source developer portal that puts the developer experience first.
|
||||
Backstage is an open-source developer portal that puts the developer experience first.
|
||||
annotations:
|
||||
github.com/project-slug: spotify/backstage
|
||||
backstage.io/github-actions-id: spotify/backstage
|
||||
backstage.io/techdocs-ref: github:https://github.com/spotify/backstage.git
|
||||
spec:
|
||||
type: library
|
||||
owner: Spotify
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
# Make sure that before you
|
||||
# run the docker-compose that you have run
|
||||
# $ yarn docker-build:all
|
||||
# $ yarn docker-build
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
frontend:
|
||||
image: 'spotify/backstage:latest'
|
||||
ports:
|
||||
- '3000:80'
|
||||
backend:
|
||||
backstage:
|
||||
image: 'example-backend:latest'
|
||||
ports:
|
||||
- '7000:7000'
|
||||
|
||||
@@ -3,7 +3,7 @@ id: FAQ
|
||||
title: FAQ
|
||||
---
|
||||
|
||||
## Product FAQ:
|
||||
## Product FAQ
|
||||
|
||||
### Can we call Backstage something different? So that it fits our company better?
|
||||
|
||||
@@ -67,7 +67,7 @@ valuable as you grow.
|
||||
Yes! The Backstage UI is built using Material-UI. With the theming capabilities
|
||||
of Material-UI, you are able to adapt the interface to your brand guidelines.
|
||||
|
||||
## Technical FAQ:
|
||||
## Technical FAQ
|
||||
|
||||
### Why Material-UI?
|
||||
|
||||
|
||||
@@ -1,104 +1,3 @@
|
||||
# Documentation structure
|
||||
# Documentation
|
||||
|
||||
**Note!** This documentation structure is very much work in progress. If (when,
|
||||
really 😆) you find broken links or missing content, please create an issue or,
|
||||
better yet, a pull request.
|
||||
|
||||
# Plugins
|
||||
|
||||
- Overview
|
||||
- [What is Backstage?](overview/what-is-backstage.md)
|
||||
- [Backstage architecture](overview/architecture-overview.md)
|
||||
- [Architecture and terminology](overview/architecture-terminology.md)
|
||||
- [Roadmap](overview/roadmap.md)
|
||||
- [Vision](overview/vision.md)
|
||||
- Getting started
|
||||
- [Running Backstage locally](getting-started/index.md)
|
||||
- [Installation](getting-started/installation.md)
|
||||
- [Local development](getting-started/development-environment.md)
|
||||
- [Demo deployment](https://backstage-demo.roadie.io)
|
||||
- Production deployments
|
||||
- [Create an App](getting-started/create-an-app.md)
|
||||
- App configuration
|
||||
- [Configuring App with plugins](getting-started/configure-app-with-plugins.md)
|
||||
- [Customize the look-and-feel of your App](getting-started/app-custom-theme.md)
|
||||
- Deployment scenarios
|
||||
- [Kubernetes](getting-started/deployment-k8s.md)
|
||||
- [Other](getting-started/deployment-other.md)
|
||||
- Features
|
||||
- Software Catalog
|
||||
- [Overview](features/software-catalog/index.md)
|
||||
- [System model](features/software-catalog/system-model.md)
|
||||
- [YAML File Format](features/software-catalog/descriptor-format.md)
|
||||
- [Extending the model](features/software-catalog/extending-the-model.md)
|
||||
- [External integrations](features/software-catalog/external-integrations.md)
|
||||
- [API](features/software-catalog/api.md)
|
||||
- Software creation templates
|
||||
- [Overview](features/software-templates/index.md)
|
||||
- [Adding templates](features/software-templates/adding-templates.md)
|
||||
- Extending the Scaffolder:
|
||||
- [Overview](features/software-templates/extending/index.md)
|
||||
- [Create your own Templater](features/software-templates/extending/create-your-own-templater.md)
|
||||
- [Create your own Publisher](features/software-templates/extending/create-your-own-publisher.md)
|
||||
- [Create your own Preparer](features/software-templates/extending/create-your-own-preparer.md)
|
||||
- Docs-like-code
|
||||
- [Overview](features/techdocs/README.md)
|
||||
- [Getting Started](features/techdocs/getting-started.md)
|
||||
- [Concepts](features/techdocs/concepts.md)
|
||||
- [Creating and Publishing Documentation](features/techdocs/creating-and-publishing.md)
|
||||
- [FAQ](features/techdocs/FAQ.md)
|
||||
- Plugins
|
||||
- [Overview](plugins/index.md)
|
||||
- [Existing plugins](plugins/existing-plugins.md)
|
||||
- [Creating a new plugin](plugins/create-a-plugin.md)
|
||||
- [Developing a plugin](plugins/plugin-development.md)
|
||||
- [Structure of a plugin](plugins/structure-of-a-plugin.md)
|
||||
- Backends and APIs
|
||||
- [Proxying](plugins/proxying.md)
|
||||
- [Backstage backend plugin](plugins/backend-plugin.md)
|
||||
- [Call existing API](plugins/call-existing-api.md)
|
||||
- Testing
|
||||
- [Overview](plugins/testing.md)
|
||||
- Publishing
|
||||
- [Open source and NPM](plugins/publishing.md)
|
||||
- [Private/internal (non-open source)](plugins/publish-private.md)
|
||||
- Configuration
|
||||
- [Overview](conf/index.md)
|
||||
- [Reading Configuration](conf/reading.md)
|
||||
- [Writing Configuration](conf/writing.md)
|
||||
- [Defining Configuration](conf/defining.md)
|
||||
- Authentication and identity
|
||||
- [Overview](auth/index.md)
|
||||
- [Add auth provider](auth/add-auth-provider.md)
|
||||
- [Auth backend](auth/auth-backend.md)
|
||||
- [OAuth](auth/oauth.md)
|
||||
- [Glossary](auth/glossary.md)
|
||||
- Designing for Backstage
|
||||
- [Backstage Design Language System (DLS)](dls/design.md)
|
||||
- [Storybook -- reusable UI components](http://backstage.io/storybook)
|
||||
- [Contributing to Storybook](dls/contributing-to-storybook.md)
|
||||
- [Figma resources](dls/figma.md)
|
||||
- API references
|
||||
- TypeScript API
|
||||
- [Utility APIs](api/utility-apis.md)
|
||||
- [Utility API References](reference/utility-apis/README.md)
|
||||
- [createPlugin](reference/createPlugin.md)
|
||||
- [createPlugin-feature-flags](reference/createPlugin-feature-flags.md)
|
||||
- [createPlugin-router](reference/createPlugin-router.md)
|
||||
- Backend APIs
|
||||
- [Backend](api/backend.md)
|
||||
- Tutorials
|
||||
- [Overview](tutorials/index.md)
|
||||
- Architecture Decision Records (ADRs)
|
||||
- [Overview](architecture-decisions/index.md)
|
||||
- [ADR001 - Architecture Decision Record (ADR) log](architecture-decisions/adr001-add-adr-log.md)
|
||||
- [ADR002 - Default Software Catalog File Format](architecture-decisions/adr002-default-catalog-file-format.md)
|
||||
- [ADR003 - Avoid Default Exports and Prefer Named Exports](architecture-decisions/adr003-avoid-default-exports.md)
|
||||
- [ADR004 - Module Export Structure](architecture-decisions/adr004-module-export-structure.md)
|
||||
- [ADR005 - Catalog Core Entities](architecture-decisions/adr005-catalog-core-entities.md)
|
||||
- [ADR006 - Avoid React.FC and React.SFC](architecture-decisions/adr006-avoid-react-fc.md)
|
||||
- [ADR007 - Use MSW for Mocking Network Requests](architecture-decisions/adr007-use-msw-to-mock-service-requests.md)
|
||||
- [ADR008 - Default Catalog File Name](architecture-decisions/adr008-default-catalog-file-name.md)
|
||||
- [Contribute](../CONTRIBUTING.md)
|
||||
- [Support](overview/support.md)
|
||||
- [FAQ](FAQ.md)
|
||||
The Backstage documentation is available at https://backstage.io/docs
|
||||
|
||||
@@ -71,18 +71,22 @@ import {
|
||||
AlertApiForwarder,
|
||||
ErrorApiForwarder,
|
||||
ErrorAlerter,
|
||||
ConfigApi,
|
||||
} from '@backstage/core';
|
||||
|
||||
const builder = ApiRegistry.builder();
|
||||
const apis = (config: ConfigApi) => {
|
||||
const builder = ApiRegistry.builder();
|
||||
|
||||
// The alert API is a self-contained implementation that shows alerts to the user.
|
||||
const alertApi = builder.add(alertApiRef, new AlertApiForwarder());
|
||||
// The alert API is a self-contained implementation that shows alerts to the user.
|
||||
const alertApi = builder.add(alertApiRef, new AlertApiForwarder());
|
||||
|
||||
// The error API uses the alert API to send error notifications to the user.
|
||||
builder.add(errorApiRef, new ErrorAlerter(alertApi, new ErrorApiForwarder()));
|
||||
// The error API uses the alert API to send error notifications to the user.
|
||||
builder.add(errorApiRef, new ErrorAlerter(alertApi, new ErrorApiForwarder()));
|
||||
return builder.build();
|
||||
};
|
||||
|
||||
const app = createApp({
|
||||
apis: apiBuilder.build(),
|
||||
apis,
|
||||
// ... other config
|
||||
});
|
||||
```
|
||||
|
||||
@@ -4,8 +4,6 @@ title: Architecture Decision Records (ADR)
|
||||
sidebar_label: Overview
|
||||
---
|
||||
|
||||
#
|
||||
|
||||
The substantial architecture decisions made in the Backstage project lives here.
|
||||
For more information about ADRs, when to write them, and why, please see
|
||||
[this blog post](https://engineering.atspotify.com/2020/04/14/when-should-i-write-an-architecture-decision-record/).
|
||||
@@ -25,7 +23,10 @@ Records should be stored under the `architecture-decisions` directory.
|
||||
- Submit a pull request
|
||||
- Address and integrate feedback from the community
|
||||
- Eventually, assign a number
|
||||
- Add the full path of the ADR to the [`mkdocs.yml`](/mkdocs.yml)
|
||||
- Add the path of the ADR to the microsite sidebar in
|
||||
[`sidebars.json`](https://github.com/spotify/backstage/blob/master/microsite/sidebars.json)
|
||||
- Add the path of the ADR to the
|
||||
[`mkdocs.yml`](https://github.com/spotify/backstage/blob/master/mkdocs.yml)
|
||||
- Merge the pull request
|
||||
|
||||
## Superseding an ADR
|
||||
|
||||
|
After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 303 KiB After Width: | Height: | Size: 303 KiB |
|
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 269 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 414 KiB After Width: | Height: | Size: 414 KiB |
|
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 234 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 746 KiB |
|
After Width: | Height: | Size: 134 KiB |
@@ -48,22 +48,35 @@ provider class which implements a handler for the chosen framework.
|
||||
#### Adding an OAuth based provider
|
||||
|
||||
If we're adding an `OAuth` based provider we would implement the
|
||||
[OAuthProviderHandlers](#OAuthProviderHandlers) interface.
|
||||
[OAuthProviderHandlers](#OAuthProviderHandlers) interface. By implementing this
|
||||
interface we can use the `OAuthProvider` class provided by `lib/oauth`, meaning
|
||||
we don't need to implement the full
|
||||
[AuthProviderRouteHandlers](#AuthProviderRouteHandlers) interface that providers
|
||||
otherwise need to implement.
|
||||
|
||||
The provider class takes the provider's configuration as a class parameter. It
|
||||
also imports the `Strategy` from the passport package.
|
||||
The provider class takes the provider's options as a class parameter. It also
|
||||
imports the `Strategy` from the passport package.
|
||||
|
||||
```ts
|
||||
import { Strategy as ProviderAStrategy } from 'passport-provider-a';
|
||||
|
||||
export type ProviderAProviderOptions = OAuthProviderOptions & {
|
||||
// extra options here
|
||||
}
|
||||
|
||||
export class ProviderAAuthProvider implements OAuthProviderHandlers {
|
||||
private readonly providerConfig: AuthProviderConfig;
|
||||
private readonly _strategy: ProviderAStrategy;
|
||||
|
||||
constructor(providerConfig: AuthProviderConfig) {
|
||||
this.providerConfig = providerConfig;
|
||||
constructor(options: ProviderAProviderOptions) {
|
||||
this._strategy = new ProviderAStrategy(
|
||||
{ ...providerConfig.options },
|
||||
{
|
||||
clientID: options.clientId,
|
||||
clientSecret: options.clientSecret,
|
||||
callbackURL: options.callbackUrl,
|
||||
passReqToCallback: false as true,
|
||||
response_type: 'code',
|
||||
/// ... etc
|
||||
}
|
||||
verifyFunction, // See the "Verify Callback" section
|
||||
);
|
||||
}
|
||||
@@ -82,14 +95,18 @@ An non-`OAuth` based provider could implement
|
||||
[AuthProviderRouteHandlers](#AuthProviderRouteHandlers) instead.
|
||||
|
||||
```ts
|
||||
type ProviderAOptions = {
|
||||
// ...
|
||||
};
|
||||
|
||||
export class ProviderAAuthProvider implements AuthProviderRouteHandlers {
|
||||
private readonly providerConfig: AuthProviderConfig;
|
||||
private readonly _strategy: ProviderAStrategy;
|
||||
|
||||
constructor(providerConfig: AuthProviderConfig) {
|
||||
this.providerConfig = providerConfig;
|
||||
constructor(options: ProviderAOptions) {
|
||||
this._strategy = new ProviderAStrategy(
|
||||
{ ...providerConfig.options },
|
||||
{
|
||||
// ...
|
||||
},
|
||||
verifyFunction, // See the "Verify Callback" section
|
||||
);
|
||||
}
|
||||
@@ -101,31 +118,61 @@ export class ProviderAAuthProvider implements AuthProviderRouteHandlers {
|
||||
}
|
||||
```
|
||||
|
||||
#### Create method
|
||||
#### Factory function
|
||||
|
||||
Each provider exports a create method that creates the provider instance,
|
||||
optionally extending a supported authorization framework. This method exists to
|
||||
allow for flexibility if additional frameworks are supported in the future.
|
||||
Each provider exports a factory function that instantiates the provider. The
|
||||
factory should implement [AuthProviderFactory](#AuthProviderFactory), which
|
||||
passes in a object with utilities for configuration, logging, token issuing,
|
||||
etc. The factory should return an implementation of
|
||||
[AuthProviderRouteHandlers](#AuthProviderRouteHandlers).
|
||||
|
||||
Implementing OAuth by returning an instance of `OAuthProvider` based of the
|
||||
provider's class:
|
||||
The factory is what decides the mapping from
|
||||
[static configuration](../conf/index.md) to the creation of auth providers. For
|
||||
example, OAuth providers use `OAuthEnvironmentHandler` to allow for multiple
|
||||
different configurations, one for each environment, which looks like this;
|
||||
|
||||
```ts
|
||||
export function createProviderAProvider(config: AuthProviderConfig) {
|
||||
const provider = new ProviderAAuthProvider(config);
|
||||
const oauthProvider = new OAuthProvider(provider, config.provider, true);
|
||||
return oauthProvider;
|
||||
}
|
||||
export const createOktaProvider: AuthProviderFactory = ({
|
||||
globalConfig,
|
||||
config,
|
||||
tokenIssuer,
|
||||
}) =>
|
||||
OAuthEnvironmentHandler.mapConfig(config, envConfig => {
|
||||
// read options from config
|
||||
const clientId = envConfig.getString('clientId');
|
||||
const clientSecret = envConfig.getString('clientSecret');
|
||||
|
||||
// instantiate our OAuthProviderHandlers implementation
|
||||
const provider = new OktaAuthProvider({
|
||||
audience,
|
||||
clientId,
|
||||
clientSecret,
|
||||
callbackUrl,
|
||||
});
|
||||
|
||||
// Wrap the OAuthProviderHandlers with OAuthProvider, which implements AuthProviderRouteHandlers
|
||||
return OAuthProvider.fromConfig(globalConfig, provider, {
|
||||
disableRefresh: false,
|
||||
providerId,
|
||||
tokenIssuer,
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Not extending with OAuth, the main difference here is that the create method is
|
||||
returning a instance of the class without adding the OAuth authorization
|
||||
framework to it.
|
||||
The purpose of the different environments is to allow for a single auth-backend
|
||||
to serve as the authentication service for multiple different frontend
|
||||
environments, such as local development, staging, and production.
|
||||
|
||||
The factory function for other providers can be a lot simpler, as they might not
|
||||
have configuration for each environment. Looking something like this:
|
||||
|
||||
```ts
|
||||
export function createProviderAProvider(config: AuthProviderConfig) {
|
||||
return new ProviderAAuthProvider(config);
|
||||
}
|
||||
export const createProviderAProvider: AuthProviderFactory = ({ config }) => {
|
||||
const a = config.getString('a');
|
||||
const b = config.getString('b');
|
||||
|
||||
return new ProviderAAuthProvider({ a, b });
|
||||
};
|
||||
```
|
||||
|
||||
#### Verify Callback
|
||||
@@ -144,7 +191,7 @@ export function createProviderAProvider(config: AuthProviderConfig) {
|
||||
> http://www.passportjs.org/docs/configure/
|
||||
|
||||
**`plugins/auth-backend/src/providers/providerA/index.ts`** is simply
|
||||
re-exporting the create method to be used for hooking the provider up to the
|
||||
re-exporting the factory function to be used for hooking the provider up to the
|
||||
backend.
|
||||
|
||||
```ts
|
||||
@@ -153,26 +200,14 @@ export { createProviderAProvider } from './provider';
|
||||
|
||||
### Hook it up to the backend
|
||||
|
||||
**`plugins/auth-backend/src/providers/config.ts`** The provider needs to be
|
||||
configured properly so you need to add it to the list of configured providers,
|
||||
all of which implement [AuthProviderConfig](#AuthProviderConfig):
|
||||
|
||||
```ts
|
||||
export const providers = [
|
||||
{
|
||||
provider: 'providerA', # used as an identifier
|
||||
options: { ... }, # consult the provider documentation for which options you should provide
|
||||
disableRefresh: true # if the provider lacks refresh tokens
|
||||
},
|
||||
```
|
||||
|
||||
**`plugins/auth-backend/src/providers/factories.ts`** When the `auth-backend`
|
||||
starts it sets up routing for all the available providers by calling
|
||||
`createAuthProviderRouter` on each provider. You need to import the create
|
||||
method from the provider and add it to the factory:
|
||||
`createAuthProviderRouter` on each provider. You need to import the factory
|
||||
function from the provider and add it to the factory:
|
||||
|
||||
```ts
|
||||
import { createProviderAProvider } from './providerA';
|
||||
|
||||
const factories: { [providerId: string]: AuthProviderFactory } = {
|
||||
providerA: createProviderAProvider,
|
||||
};
|
||||
@@ -203,10 +238,21 @@ web browser and you should be able to trigger the authorization flow.
|
||||
|
||||
```ts
|
||||
export interface OAuthProviderHandlers {
|
||||
start(req: express.Request, options: any): Promise<any>;
|
||||
handler(req: express.Request): Promise<any>;
|
||||
refresh?(refreshToken: string, scope: string): Promise<any>;
|
||||
logout?(): Promise<any>;
|
||||
start(
|
||||
req: express.Request,
|
||||
options: Record<string, string>,
|
||||
): Promise<RedirectInfo>;
|
||||
handler(
|
||||
req: express.Request,
|
||||
): Promise<{
|
||||
response: AuthResponse<OAuthProviderInfo>;
|
||||
refreshToken?: string;
|
||||
}>;
|
||||
refresh?(
|
||||
refreshToken: string,
|
||||
scope: string,
|
||||
): Promise<AuthResponse<OAuthProviderInfo>>;
|
||||
logout?(): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -221,12 +267,17 @@ export interface AuthProviderRouteHandlers {
|
||||
}
|
||||
```
|
||||
|
||||
##### AuthProviderConfig
|
||||
##### AuthProviderFactory
|
||||
|
||||
```ts
|
||||
export type AuthProviderConfig = {
|
||||
provider: string;
|
||||
options: any;
|
||||
disableRefresh?: boolean;
|
||||
export type AuthProviderFactoryOptions = {
|
||||
globalConfig: AuthProviderConfig;
|
||||
config: Config;
|
||||
logger: Logger;
|
||||
tokenIssuer: TokenIssuer;
|
||||
};
|
||||
|
||||
export type AuthProviderFactory = (
|
||||
options: AuthProviderFactoryOptions,
|
||||
) => AuthProviderRouteHandlers;
|
||||
```
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# Authentication Backend Classes Layout and Description
|
||||
---
|
||||
id: auth-backend-classes
|
||||
title: Auth backend classes
|
||||
---
|
||||
|
||||
## How Does Authentication Work?
|
||||
|
||||
@@ -23,7 +26,7 @@ refer to the type documentation under
|
||||
`plugins/auth-backend/src/providers/types.ts`.
|
||||
|
||||
There are currently two different classes for two authentication mechanisms that
|
||||
implement this interface: an `OAuthProvider` for [OAuth](https://oauth.net/2/)
|
||||
implement this interface: an `OAuthAdapter` for [OAuth](https://oauth.net/2/)
|
||||
based mechanisms and a `SAMLAuthProvider` for
|
||||
[SAML](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html)
|
||||
based mechanisms.
|
||||
@@ -47,11 +50,12 @@ OAuth2) providers, you can configure them by setting the right variables in
|
||||
Each authentication provider (except SAML) needs five parameters: an OAuth
|
||||
client ID, a client secret, an authorization endpoint and a token endpoint, and
|
||||
an app origin. The app origin is the URL at which the frontend of the
|
||||
application is hosted. This is required because the application opens a popup
|
||||
window to perform the authentication, and once the flow is completed, the popup
|
||||
window sends a `postMessage` to the frontend application to indicate the result
|
||||
of the operation. Also this URL is used to verify that authentication requests
|
||||
are coming from only this endpoint.
|
||||
application is hosted, and it is read from the `app.baseUrl` config. This is
|
||||
required because the application opens a popup window to perform the
|
||||
authentication, and once the flow is completed, the popup window sends a
|
||||
`postMessage` to the frontend application to indicate the result of the
|
||||
operation. Also this URL is used to verify that authentication requests are
|
||||
coming from only this endpoint.
|
||||
|
||||
These values are configured via the `app-config.yaml` present in the root of
|
||||
your app folder.
|
||||
@@ -61,8 +65,6 @@ auth:
|
||||
providers:
|
||||
google:
|
||||
development:
|
||||
appOrigin: "http://localhost:3000/"
|
||||
secure: false
|
||||
clientId:
|
||||
$secret:
|
||||
env: AUTH_GOOGLE_CLIENT_ID
|
||||
@@ -71,8 +73,6 @@ auth:
|
||||
env: AUTH_GOOGLE_CLIENT_SECRET
|
||||
github:
|
||||
development:
|
||||
appOrigin: "http://localhost:3000/"
|
||||
secure: false
|
||||
clientId:
|
||||
$secret:
|
||||
env: AUTH_GITHUB_CLIENT_ID
|
||||
@@ -84,8 +84,6 @@ auth:
|
||||
env: AUTH_GITHUB_ENTERPRISE_INSTANCE_URL
|
||||
gitlab:
|
||||
development:
|
||||
appOrigin: "http://localhost:3000/"
|
||||
secure: false
|
||||
clientId:
|
||||
$secret:
|
||||
...
|
||||
@@ -93,24 +91,34 @@ auth:
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### EnvironmentHandler
|
||||
### OAuthEnvironmentHandler
|
||||
|
||||
The concept of an "env" is core to the way the auth backend works. It uses an
|
||||
`env` query parameter to identify the environment in which the application is
|
||||
running (`development`, `staging`, `production`, etc). Each runtime can support
|
||||
multiple environments at the same time and the right handler for each request is
|
||||
identified and dispatched to based on the `env` parameter. All
|
||||
`AuthProviderRouteHandlers` are wrapped within an `EnvironmentHandler`.
|
||||
`AuthProviderRouteHandlers` are wrapped within an `OAuthEnvironmentHandler`.
|
||||
|
||||
An `EnvironmentHandler` takes an ID for each provider that it wraps, the
|
||||
handlers for each env the provider is supported in, and a function that, given a
|
||||
`Request` as argument, can extract the information about the env under which it
|
||||
should be processed.
|
||||
To instantiate multiple OAuth providers for different environments, use
|
||||
`OAuthEnvironmentHandler.mapConfig`. It's a helper to iterate over a
|
||||
configuration object that is a map of environment to configurations. See one of
|
||||
the existing OAuth providers for an example of how it is used.
|
||||
|
||||
Each provider exposes a factory function `createXProvider` (where X is the name
|
||||
of the provider) that takes the global config, env and other parameters and
|
||||
returns an `AuthProviderRouteHandlers` for each env, and an `envIdentifier`
|
||||
function to identify the env of a request.
|
||||
Given the following configuration:
|
||||
|
||||
```yaml
|
||||
development:
|
||||
clientId: abc
|
||||
clientSecret: secret
|
||||
production:
|
||||
clientId: xyz
|
||||
clientSecret: supersecret
|
||||
```
|
||||
|
||||
The `OAuthEnvironmentHandler.mapConfig(config, envConfig => ...)` call will
|
||||
split the `config` by the top level `development` and `production` keys, and
|
||||
pass on each block as `envConfig`.
|
||||
|
||||
For a list of currently available providers, look in the `factories` module
|
||||
located in `plugins/auth-backend/src/providers/factories.ts`
|
||||
|
||||
@@ -104,6 +104,8 @@ request an access token.
|
||||
|
||||
The following diagram visualizes the flow described in the previous section.
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
@startuml oauth-popup-flow
|
||||
|
||||
@@ -152,5 +154,3 @@ Browser <- Backend: Tokens and info
|
||||
|
||||
@enduml
|
||||
-->
|
||||
|
||||

|
||||
|
||||
@@ -3,7 +3,7 @@ id: design
|
||||
title: Design
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Much like Backstage Open Source, this is a _living_ document! We'll keep this
|
||||
updated as we evolve our practices!
|
||||
@@ -116,8 +116,8 @@ components. If you’d like to help build up our design system, you can also add
|
||||
components we’ve designed to the Storybook as well.
|
||||
|
||||
**[Figma](https://www.figma.com/@backstage)** - we're stoked to be using Figma
|
||||
Community to share our design assets. You can duplicate our component library
|
||||
and design your own plugin for Backstage.
|
||||
Community to share our design assets. You can duplicate our UI Kit and design
|
||||
your own plugin for Backstage.
|
||||
|
||||
**[Discord](https://discord.gg/EBHEGzX)** - all design questions should be
|
||||
directed to the _#design_ channel.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
id: software-catalog-configuration
|
||||
title: Catalog Configuration
|
||||
---
|
||||
|
||||
## Static Location Configuration
|
||||
|
||||
To enable declarative catalog setups, it is possible to add locations to the
|
||||
catalog via [static configuration](../../conf/index.md). Locations are added to
|
||||
the catalog under the `catalog.locations` key, for example:
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
locations:
|
||||
- type: github
|
||||
target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml
|
||||
```
|
||||
|
||||
The locations added through static configuration can not be removed through the
|
||||
catalog locations API. To remove the locations, you have to remove them from the
|
||||
configuration.
|
||||
|
||||
## Catalog Rules
|
||||
|
||||
By default the catalog will only allow ingestion of entities with the kind
|
||||
`Component`, `API` and `Location`. In order to allow entities of other kinds to
|
||||
be added, you need to add rules to the catalog. Rules are added either in a
|
||||
separate `catalog.rules` key, or added to statically configured locations.
|
||||
|
||||
For example, given the following configuration:
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
rules:
|
||||
- allow: [Component, API, Location, Template]
|
||||
|
||||
locations:
|
||||
- type: github
|
||||
target: https://github.com/org/example/blob/master/org-data.yaml
|
||||
rules:
|
||||
- allow: [Group]
|
||||
```
|
||||
|
||||
We are able to add entities of kind `Component`, `API`, `Location`, or
|
||||
`Template` from any location, and `Group` entities from the `org-data.yaml`,
|
||||
which will also be read as statically configured location.
|
||||
|
||||
Note that if the `catalog.rules` key is present it will replace the default
|
||||
value, meaning that you need to add rules for the default kinds if you want
|
||||
those to still be allowed.
|
||||
|
||||
The following configuration will reject any kind of entities from being added to
|
||||
the catalog:
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
rules: []
|
||||
```
|
||||
@@ -235,6 +235,9 @@ The `backstage.io/` prefix is reserved for use by Backstage core components.
|
||||
|
||||
Values can be of any length, but are limited to being strings.
|
||||
|
||||
There is a list of [well-known annotations](well-known-annotations.md), but
|
||||
anybody is free to add more annotations as they see fit.
|
||||
|
||||
### `tags` [optional]
|
||||
|
||||
A list of single-valued strings, for example to classify catalog entities in
|
||||
@@ -290,7 +293,7 @@ Exactly equal to `backstage.io/v1alpha1` and `Component`, respectively.
|
||||
|
||||
The type of component as a string, e.g. `website`. This field is required.
|
||||
|
||||
The software catalog accepts any type value, but an organisation should take
|
||||
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
|
||||
@@ -304,9 +307,9 @@ The current set of well-known and common values for this field is:
|
||||
|
||||
### `spec.lifecycle` [required]
|
||||
|
||||
The lifecyle state of the component, e.g. `production`. This field is required.
|
||||
The lifecycle state of the component, e.g. `production`. This field is required.
|
||||
|
||||
The software catalog accepts any lifecycle value, but an organisation should
|
||||
The software catalog accepts any lifecycle value, but an organization should
|
||||
take great care to establish a proper taxonomy for these.
|
||||
|
||||
The current set of well-known and common values for this field is:
|
||||
@@ -370,8 +373,8 @@ metadata:
|
||||
description:
|
||||
Next.js application skeleton for creating isomorphic web applications.
|
||||
tags:
|
||||
- Recommended
|
||||
- React
|
||||
- recommended
|
||||
- react
|
||||
spec:
|
||||
owner: web@example.com
|
||||
templater: cookiecutter
|
||||
@@ -418,7 +421,7 @@ potentially search and group templates by these tags.
|
||||
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 organisation should take
|
||||
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
|
||||
@@ -508,7 +511,7 @@ Exactly equal to `backstage.io/v1alpha1` and `API`, respectively.
|
||||
The type of the API definition as a string, e.g. `openapi`. This field is
|
||||
required.
|
||||
|
||||
The software catalog accepts any type value, but an organisation should take
|
||||
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, an OpenAPI type API may be displayed using an OpenAPI viewer tooling in
|
||||
|
||||
@@ -12,7 +12,7 @@ Backstage natively supports tracking of the following component
|
||||
- Documentation
|
||||
- Other
|
||||
|
||||

|
||||

|
||||
|
||||
Since these types are likely not the only kind of software you will want to
|
||||
track in Backstage, it is possible to
|
||||
@@ -31,9 +31,10 @@ catalog.
|
||||
It might be tempting to put software that doesn't fit into any of the existing
|
||||
types into Other. There are a few reasons why we advice against this; firstly,
|
||||
we have found that it is preferred to match the conceptual model that your
|
||||
engineers have when describing your sofware. Secondly, Backstage helps your
|
||||
engineers manage their software by integrating the infratrucure tooling through
|
||||
plugins. Different plugins are used for managing different types of components.
|
||||
engineers have when describing your software. Secondly, Backstage helps your
|
||||
engineers manage their software by integrating the infrastructure tooling
|
||||
through plugins. Different plugins are used for managing different types of
|
||||
components.
|
||||
|
||||
For example, the
|
||||
[Lighthouse plugin](https://github.com/spotify/backstage/tree/master/plugins/lighthouse)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: software-catalog-overview
|
||||
title: Backstage Service Catalog (alpha)
|
||||
sidebar_label: Overview
|
||||
---
|
||||
|
||||
## What is a Service Catalog?
|
||||
@@ -47,25 +48,25 @@ There are 3 ways to add components to the catalog:
|
||||
|
||||
1. Manually register components
|
||||
2. Creating new components through Backstage
|
||||
3. Integrating with and [external source](external-integrations.md)
|
||||
3. Integrating with an [external source](external-integrations.md)
|
||||
|
||||
### Manually register components
|
||||
|
||||
Users can register new components by going to `/create` and clicking the
|
||||
**REGISTER EXISTING COMPONENT** button:
|
||||
|
||||

|
||||

|
||||
|
||||
Backstage expects the full URL to the YAML in your source control. Example:
|
||||
|
||||
```
|
||||
```bash
|
||||
https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml
|
||||
```
|
||||
|
||||
_More examples can be found
|
||||
[here](https://github.com/spotify/backstage/tree/master/packages/catalog-model/examples)._
|
||||
|
||||

|
||||

|
||||
|
||||
It is important to note that any kind of software can be registered in
|
||||
Backstage. Even if the software is not maintained by your company (SaaS
|
||||
@@ -78,12 +79,28 @@ All software created through the
|
||||
[Backstage Software Templates](../software-templates/index.md) are automatically
|
||||
registered in the catalog.
|
||||
|
||||
### Static catalog configuration
|
||||
|
||||
In addition to manually registering components, it is also possible to register
|
||||
components though [static configuration](../../conf/index.md). For example, the
|
||||
above example can be added using the following configuration:
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
locations:
|
||||
- type: github
|
||||
target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml
|
||||
```
|
||||
|
||||
More information about catalog configuration can be found
|
||||
[here](configuration.md).
|
||||
|
||||
### Updating component metadata
|
||||
|
||||
Teams owning the components are responsible for maintaining the metadata about
|
||||
them, and do so using their normal Git workflow.
|
||||
|
||||

|
||||

|
||||
|
||||
Once the change has been merged, Backstage will automatically show the updated
|
||||
metadata in the service catalog after a short while.
|
||||
@@ -92,25 +109,25 @@ metadata in the service catalog after a short while.
|
||||
|
||||
By default the service catalog shows components owned by the team of the logged
|
||||
in user. But you can also switch to _All_ to see all the components across your
|
||||
companie's software ecosystem. Basic inline _search_ and _column filtering_
|
||||
makes it easy to browse a big set of components.
|
||||
company's software ecosystem. Basic inline _search_ and _column filtering_ makes
|
||||
it easy to browse a big set of components.
|
||||
|
||||

|
||||

|
||||
|
||||
## Starring components
|
||||
|
||||
For easy and quick access to components you visit frequently, Backstage supports
|
||||
_starring_ of components:
|
||||
|
||||

|
||||

|
||||
|
||||
## Integrated tooling through plugins
|
||||
|
||||
The service catalog is a great way to organise the infrastructure tools you use
|
||||
The service catalog is a great way to organize the infrastructure tools you use
|
||||
to manage the software. This is how Backstage creates one developer portal for
|
||||
all your tools. Rather than asking teams to jump between different
|
||||
infrastructure UI’s (and incurring additional cognitive overhead each time they
|
||||
make a context switch), most of these tools can be organised around the entities
|
||||
infrastructure UIs (and incurring additional cognitive overhead each time they
|
||||
make a context switch), most of these tools can be organized around the entities
|
||||
in the catalog.
|
||||
|
||||

|
||||
|
||||
@@ -3,55 +3,26 @@ id: system-model
|
||||
title: System Model
|
||||
---
|
||||
|
||||
We believe that a strong shared understanding and terminology around systems,
|
||||
software and resources leads to a better Backstage experience.
|
||||
We believe that a strong shared understanding and terminology around software
|
||||
and resources leads to a better Backstage experience.
|
||||
|
||||
_This description originates from
|
||||
[this RFC](https://github.com/spotify/backstage/issues/390). Note that some of
|
||||
the concepts are not yet supported in Backstage._
|
||||
|
||||
## Concepts
|
||||
## Core Entities
|
||||
|
||||
We model our technology using these five concepts (further explained below):
|
||||
We model software in the Backstage catalogue using these three core entities
|
||||
(further explained below):
|
||||
|
||||
- **Components** are individual pieces of software
|
||||
|
||||
- **APIs** are the boundaries between different components
|
||||
|
||||
- **Domains** are a high-level grouping of systems
|
||||
- **Systems** encapsulate the implementation of APIs
|
||||
- **APIs** are the boundaries between different components and systems
|
||||
- **Components** are pieces of software
|
||||
- **Resources** are physical or virtual infrastructure needed to operate a
|
||||
system
|
||||
component
|
||||
|
||||

|
||||
|
||||
### Domain
|
||||
|
||||
While systems are the basic level of encapsulation for resources, components and
|
||||
APIs, it is often useful to group a collection of systems that share
|
||||
terminology, domain models, business purpose, or documentation, i.e. they form a
|
||||
bounded context.
|
||||
|
||||
For example, it would make sense if the different systems in the “Payments”
|
||||
domain would come with some documentation on how to accept payments for a new
|
||||
product or use-case, share the same entity types in their APIs, and integrate
|
||||
well with each other.
|
||||
|
||||
### System
|
||||
|
||||
With increasing complexity in software, we believe that systems form an
|
||||
important abstraction level to help us reason about software ecosystems. Systems
|
||||
are a useful concept in that they allow us to ignore the implementation details
|
||||
of a certain functionality for consumers, while allowing the owning team to make
|
||||
changes as they see fit (leading to low coupling).
|
||||
|
||||
A system, in this sense, is a collection of resources and components that
|
||||
exposes one or several APIs. Components and resources in a system are typically
|
||||
owned by the same team and are expected to co-evolve. As such, systems usually
|
||||
consist of at most a handful of components.
|
||||
|
||||
For example, a playlist management system might encapsulate a backend service to
|
||||
update playlists, a backend service to query them, and a database to store them.
|
||||
It could expose an RPC API, a daily snapshots dataset, and an event stream of
|
||||
playlist updates.
|
||||

|
||||
|
||||
### Component
|
||||
|
||||
@@ -60,34 +31,80 @@ backend service or data pipeline (list not exhaustive). A component can be
|
||||
tracked in source control, or use some existing open source or commercial
|
||||
software.
|
||||
|
||||
A component can implement APIs for other components to consume. It might depend
|
||||
on the resources of the system it belongs to, and APIs from other components or
|
||||
other systems. All other aspects of the component, e.g. any code dependencies,
|
||||
must be encapsulated.
|
||||
A component can implement APIs for other components to consume. In turn it might
|
||||
depend on APIs implemented by other components, or resources that are attached
|
||||
to it at runtime.
|
||||
|
||||
### API
|
||||
|
||||
We believe APIs form an important (maybe the most important) abstraction that
|
||||
allows large software ecosystems to scale. Thus, APIs are a first class citizen
|
||||
in the Backstage model and the primary way to discover existing functionality in
|
||||
the ecosystem.
|
||||
APIs form an important (maybe the most important) abstraction that allows large
|
||||
software ecosystems to scale. Thus, APIs are a first class citizen in the
|
||||
Backstage model and the primary way to discover existing functionality in the
|
||||
ecosystem.
|
||||
|
||||
APIs are implemented by components and form boundaries between components and
|
||||
systems. They might be defined using an RPC IDL (eg Protobuf, GraphQL, ...), a
|
||||
data schema (eg Avro, TFRecord, ...), or as code interfaces. In any case, APIs
|
||||
exposed by components need to be in a known machine-readable format so we can
|
||||
build further tooling and analysis on top.
|
||||
APIs are implemented by components and form boundaries between components. They
|
||||
might be defined using an RPC IDL (eg Protobuf, GraphQL, ...), a data schema (eg
|
||||
Avro, TFRecord, ...), or as code interfaces. In any case, APIs exposed by
|
||||
components need to be in a known machine-readable format so we can build further
|
||||
tooling and analysis on top.
|
||||
|
||||
Some APIs might be exposed by the system, making them available for any other
|
||||
Spotify component to consume. Those public APIs must be documented and humanly
|
||||
discoverable in Backstage.
|
||||
APIs have a visibility: they are either public (making them available for any
|
||||
other component to consume), restricted (only available to a whitelisted set of
|
||||
consumers), or private (only available within their system). As public APIs are
|
||||
going to be the primary way interaction between components, Backstage supports
|
||||
documenting, indexing and searching all APIs so we can browse them as
|
||||
developers.
|
||||
|
||||
### Resource
|
||||
|
||||
Resources are the infrastructure a system needs to operate, like BigTable
|
||||
databases, Pub/Sub topics, S3 buckets or CDNs. Modelling them together with
|
||||
components and systems will better allow us to visualize resource footprint, and
|
||||
create tooling around them.
|
||||
Resources are the infrastructure a component needs to operate at runtime, like
|
||||
BigTable databases, Pub/Sub topics, S3 buckets or CDNs. Modelling them together
|
||||
with components and systems will better allow us to visualize resource
|
||||
footprint, and create tooling around them.
|
||||
|
||||
## Ecosystem Modeling
|
||||
|
||||
A large catalogue of components, APIs and resources can be highly granular and
|
||||
hard to understand as a whole. It might thus be convenient to further categorize
|
||||
these entities using the following (optional) concepts:
|
||||
|
||||
- **Systems** are a collection of entities that cooperate to perform some
|
||||
function
|
||||
- **Domains** relate entities and systems to part of the business
|
||||
|
||||
### System
|
||||
|
||||
With increasing complexity in software, systems form an important abstraction
|
||||
level to help us reason about software ecosystems. Systems are a useful concept
|
||||
in that they allow us to ignore the implementation details of a certain
|
||||
functionality for consumers, while allowing the owning team to make changes as
|
||||
they see fit (leading to low coupling).
|
||||
|
||||
A system, in this sense, is a collection of resources and components that
|
||||
exposes one or several public APIs. The main benefit of modelling a system is
|
||||
that it hides its resources and private APIs between the components for any
|
||||
consumers. This means that as the owner, you can evolve the implementation, in
|
||||
terms of components and resources, without your consumers being able to notice.
|
||||
Typically, a system will consist of at most a handful of components (see Domain
|
||||
for a grouping of systems).
|
||||
|
||||
For example, a playlist management system might encapsulate a backend service to
|
||||
update playlists, a backend service to query them, and a database to store them.
|
||||
It could expose an RPC API, a daily snapshots dataset, and an event stream of
|
||||
playlist updates.
|
||||
|
||||
### Domain
|
||||
|
||||
While systems are the basic level of encapsulation for related entities, it is
|
||||
often useful to group a collection of systems that share terminology, domain
|
||||
models, metrics, KPIs, business purpose, or documentation, i.e. they form a
|
||||
bounded context.
|
||||
|
||||
For example, it would make sense if the different systems in the “Payments”
|
||||
domain would come with some documentation on how to accept payments for a new
|
||||
product or use-case, share the same entity types in their APIs, and integrate
|
||||
well with each other. Other domains could be “Content Ingestion”, “Ads” or
|
||||
“Search”.
|
||||
|
||||
## Current status
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
---
|
||||
id: well-known-annotations
|
||||
title: Well-known Annotations on Catalog Entities
|
||||
sidebar_label: Well-known Annotations
|
||||
---
|
||||
|
||||
This section lists a number of well known
|
||||
[annotations](descriptor-format.md#annotations-optional), that have defined
|
||||
semantics. They can be attached to catalog entities and consumed by plugins as
|
||||
needed.
|
||||
|
||||
## Annotations
|
||||
|
||||
This is a (non-exhaustive) list of annotations that are known to be in active
|
||||
use.
|
||||
|
||||
### backstage.io/managed-by-location
|
||||
|
||||
```yaml
|
||||
# Example:
|
||||
metadata:
|
||||
annotations:
|
||||
backstage.io/managed-by-location: github:http://github.com/spotify/backstage/catalog-info.yaml
|
||||
```
|
||||
|
||||
The value of this annotation is a so called location reference string, that
|
||||
points to the source from which the entity was originally fetched. This
|
||||
annotation is added automatically by the catalog as it fetches the data from a
|
||||
registered location, and is not meant to normally be written by humans. The
|
||||
annotation may point to any type of generic location that the catalog supports,
|
||||
so it cannot be relied on to always be specifically of type `github`, nor that
|
||||
it even represents a single file. Note also that a single location can be the
|
||||
source of many entities, so it represents a many-to-one relationship.
|
||||
|
||||
The format of the value is `<type>:<target>`. Note that the target may also
|
||||
contain colons, so it is not advisable to naively split the value on `:` and
|
||||
expecting a two-item array out of it. The format of the target part is
|
||||
type-dependent and could conceivably even be an empty string, but the separator
|
||||
colon is always present.
|
||||
|
||||
### backstage.io/techdocs-ref
|
||||
|
||||
```yaml
|
||||
# Example:
|
||||
metadata:
|
||||
annotations:
|
||||
backstage.io/techdocs-ref: github:https://github.com/spotify/backstage.git
|
||||
```
|
||||
|
||||
The value of this annotation is a location reference string (see above). If this
|
||||
annotation is specified, it is expected to point to a repository that the
|
||||
TechDocs system can read and generate docs from.
|
||||
|
||||
### backstage.io/jenkins-github-folder
|
||||
|
||||
```yaml
|
||||
# Example:
|
||||
metadata:
|
||||
annotations:
|
||||
backstage.io/jenkins-github-folder: folder-name/job-name
|
||||
```
|
||||
|
||||
The value of this annotation is the path to a job on Jenkins, that builds this
|
||||
entity.
|
||||
|
||||
Specifying this annotation may enable Jenkins related features in Backstage for
|
||||
that entity.
|
||||
|
||||
### github.com/project-slug
|
||||
|
||||
```yaml
|
||||
# Example:
|
||||
metadata:
|
||||
annotations:
|
||||
github.com/project-slug: spotify/backstage
|
||||
```
|
||||
|
||||
The value of this annotation is the so-called slug that identifies a project on
|
||||
[GitHub](https://github.com) that is related to this entity. It is on the format
|
||||
`<organization>/<project>`, and is the same as can be seen in the URL location
|
||||
bar of the browser when viewing that project.
|
||||
|
||||
Specifying this annotation will enable GitHub related features in Backstage for
|
||||
that entity.
|
||||
|
||||
### sentry.io/project-slug
|
||||
|
||||
```yaml
|
||||
# Example:
|
||||
metadata:
|
||||
annotations:
|
||||
sentry.io/project-slug: pump-station
|
||||
```
|
||||
|
||||
The value of this annotation is the so-called slug (or alternatively, the ID) of
|
||||
a [Sentry](https://sentry.io) project within your organization. The organization
|
||||
slug is currently not configurable on a per-entity basis, but is assumed to be
|
||||
the same for all entities in the catalog.
|
||||
|
||||
Specifying this annotation may enable Sentry related features in Backstage for
|
||||
that entity.
|
||||
|
||||
### rollbar.com/project-slug
|
||||
|
||||
```yaml
|
||||
# Example:
|
||||
metadata:
|
||||
annotations:
|
||||
rollbar.com/project-slug: spotify/pump-station
|
||||
```
|
||||
|
||||
The value of this annotation is the so-called slug (or alternatively, the ID) of
|
||||
a [Rollbar](https://rollbar.com) project within your organization. The value can
|
||||
be the format of `[organization]/[project-slug]` or just `[project-slug]`. When
|
||||
the organization slug is omitted the `app-config.yaml` will be used as a
|
||||
fallback (`rollbar.organization` followed by `organization.name`).
|
||||
|
||||
Specifying this annotation may enable Rollbar related features in Backstage for
|
||||
that entity.
|
||||
|
||||
## Deprecated Annotations
|
||||
|
||||
The following annotations are deprecated, and only listed here to aid in
|
||||
migrating away from them.
|
||||
|
||||
### backstage.io/github-actions-id
|
||||
|
||||
This annotation was used for a while to enable the GitHub Actions feature. This
|
||||
is now instead using the [github.com/project-slug](#github-com-project-slug)
|
||||
annotation, with the same value format.
|
||||
|
||||
## Links
|
||||
|
||||
- [Descriptor Format: annotations](descriptor-format.md#annotations-optional)
|
||||
@@ -22,8 +22,8 @@ metadata:
|
||||
Next.js application skeleton for creating isomorphic web applications.
|
||||
# some tags to display in the frontend
|
||||
tags:
|
||||
- Recommended
|
||||
- React
|
||||
- recommended
|
||||
- react
|
||||
spec:
|
||||
# which templater key to use in the templaters builder
|
||||
templater: cookiecutter
|
||||
@@ -54,11 +54,34 @@ contains more information about the required fields.
|
||||
Once we have a `template.yaml` ready, we can then add it to the service catalog
|
||||
for use by the scaffolder.
|
||||
|
||||
Currently the catalog supports loading definitions from Github + Local Files. To
|
||||
Currently the catalog supports loading definitions from GitHub + Local Files. To
|
||||
load from other places, not only will there need to be another preparer, but the
|
||||
support to load the location will also need to be added to the Catalog.
|
||||
|
||||
For loading from a file the following command should work when the backend is
|
||||
You can add the template files to the catalog through
|
||||
[static location configuration](../software-catalog/configuration.md#static-location-configuration),
|
||||
for example
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
locations:
|
||||
- type: github
|
||||
target: https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml
|
||||
rules:
|
||||
- allow: [Template]
|
||||
```
|
||||
|
||||
Templates can also be added by posting the to the catalog directly. Note that if
|
||||
you're doing this, you need to configure the catalog to allow template entities
|
||||
to be ingested from any source, for example:
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
rules:
|
||||
- allow: [Component, API, Template]
|
||||
```
|
||||
|
||||
For loading from a file, the following command should work when the backend is
|
||||
running:
|
||||
|
||||
```sh
|
||||
@@ -69,7 +92,7 @@ curl \
|
||||
--data-raw "{\"type\": \"file\", \"target\": \"${YOUR PATH HERE}/template.yaml\"}"
|
||||
```
|
||||
|
||||
If loading from a git location, you can run the following
|
||||
If loading from a Git location, you can run the following
|
||||
|
||||
```sh
|
||||
curl \
|
||||
@@ -83,7 +106,7 @@ This should then have added the catalog, and also should now be listed under the
|
||||
create page at http://localhost:3000/create.
|
||||
|
||||
Alternatively, if you want to get setup with some mock templates that are
|
||||
already provided for you, you can run the following to load those templates:
|
||||
already provided, run the following to load those templates:
|
||||
|
||||
```
|
||||
yarn lerna run mock-data
|
||||
|
||||
@@ -54,7 +54,7 @@ The `protocol` is set on the
|
||||
when added to the service catalog. You can see more about this `PreparerKey`
|
||||
here in [Register your own template](../adding-templates.md)
|
||||
|
||||
**note:** Currently the catalog supports loading definitions from Github + Local
|
||||
**note:** Currently the catalog supports loading definitions from GitHub + Local
|
||||
Files, which translate into the two `PreparerKeys` `file` and `github`. To load
|
||||
from other places, not only will there need to be another preparer, but the
|
||||
support to load the location will also need to be added to the Catalog.
|
||||
|
||||
@@ -7,18 +7,18 @@ Publishers are responsible for pushing and storing the templated skeleton after
|
||||
the values have been templated by the `Templater`. See
|
||||
[Create your own templater](./create-your-own-templater.md) for more info.
|
||||
|
||||
They recieve a directory or location where the templater has sucessfully run on,
|
||||
and is now ready to store somewhere. They also get given some other options
|
||||
which are sent from the frontend, such as the `storePath` which is a string of
|
||||
where the frontend thinks we should save this templated folder.
|
||||
They receive a directory or location where the templater has sucessfully run and
|
||||
is now ready to store somewhere. They also are given some other options which
|
||||
are sent from the frontend, such as the `storePath` which is a string of where
|
||||
the frontend thinks we should save this templated folder.
|
||||
|
||||
Currently we provide the following `publishers`:
|
||||
|
||||
- `github`
|
||||
|
||||
This publisher is passed through to the `createRouter` function of the
|
||||
`@spotify/plugin-scaffolder-backend`. Currently only one publisher is supported,
|
||||
but PR's are always welcome.
|
||||
`@spotify/plugin-scaffolder-backend`. Currently, only one publisher is
|
||||
supported, but PR's are always welcome.
|
||||
|
||||
An full example backend can be found
|
||||
[here](https://github.com/spotify/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts),
|
||||
|
||||
@@ -8,14 +8,14 @@ returned by the preparers, and then executing the templating command on top of
|
||||
the file and returning the completed template path. This may or may not be the
|
||||
same directory as the input directory.
|
||||
|
||||
They also recieve additional values from the frontend, which can be used to
|
||||
They also receive additional values from the frontend, which can be used to
|
||||
interpolate into the skeleton files.
|
||||
|
||||
Currently we provide the following templaters:
|
||||
|
||||
- `cookiecutter`
|
||||
|
||||
This templater is added the `TemplaterBuilder` and then passed into the
|
||||
This templater is added to the `TemplaterBuilder` and then passed into the
|
||||
`createRouter` function of the `@spotify/plugin-scaffolder-backend`
|
||||
|
||||
An full example backend can be found
|
||||
@@ -48,7 +48,7 @@ This `TemplaterKey` is used to select the correct templater from the
|
||||
`spec.templater` in the
|
||||
[Template Entity](../../software-catalog/descriptor-format.md#kind-template).
|
||||
|
||||
If you wish to add a new templater you'll need to register it with the
|
||||
If you wish to add a new templater, you'll need to register it with the
|
||||
`TemplaterBuilder`.
|
||||
|
||||
### Creating your own Templater to add to the `TemplaterBuilder`
|
||||
@@ -83,10 +83,10 @@ follows:
|
||||
- `dockerClient` - a [dockerode](https://github.com/apocas/dockerode) client to
|
||||
be able to run docker containers.
|
||||
|
||||
_note_ currently the templaters that we provide are basically docker action
|
||||
_note_ Currently the templaters that we provide are basically Docker action
|
||||
containers that are run on top of the skeleton folder. This keeps dependencies
|
||||
to a minimal for running backstage scaffolder, but you don't /have/ to use
|
||||
docker. You could create your own templater that spins up an EC2 instance and
|
||||
Docker. You could create your own templater that spins up an EC2 instance and
|
||||
downloads the folder and does everything using an AMI if you want. It's entirely
|
||||
up to you!
|
||||
|
||||
@@ -116,8 +116,8 @@ metadata:
|
||||
description:
|
||||
Next.js application skeleton for creating isomorphic web applications.
|
||||
tags:
|
||||
- Recommended
|
||||
- React
|
||||
- recommended
|
||||
- react
|
||||
spec:
|
||||
owner: web@example.com
|
||||
templater: handlebars
|
||||
@@ -138,7 +138,7 @@ spec:
|
||||
description: Description of the component
|
||||
```
|
||||
|
||||
You see that the `spec.templater` is set as `handlebars`, you'll need to
|
||||
You see that the `spec.templater` is set as `handlebars`, so you'll need to
|
||||
register this with the `TemplaterBuilder` like so:
|
||||
|
||||
```ts
|
||||
|
||||
@@ -5,11 +5,11 @@ title: Extending the Scaffolder
|
||||
|
||||
Welcome. Take a seat. You're at the Scaffolder Documentation.
|
||||
|
||||
So - You wanna create stuff inside your company from some prebaked templates?
|
||||
So, you want to create stuff inside your company from some prebaked templates?
|
||||
You're at the right place.
|
||||
|
||||
This guide is gonna take you through how the Scaffolder in Backstage works.
|
||||
We'll dive into some jargon and run through whats going on in the backend to be
|
||||
This guide is going to take you through how the Scaffolder in Backstage works.
|
||||
We'll dive into some jargon and run through what's going on in the backend to be
|
||||
able to create these templates. There's also more guides that you might find
|
||||
useful at the bottom of this document. At it's core, theres 3 simple stages.
|
||||
|
||||
@@ -25,9 +25,9 @@ scaffolder that you will need to know:
|
||||
3. Publish
|
||||
|
||||
Each of these steps can be configured for your own use case, but we provide some
|
||||
sensible defaults too.
|
||||
sensible defaults, too.
|
||||
|
||||
Lets dive a little deeper into these phases.
|
||||
Let's dive a little deeper into these phases.
|
||||
|
||||
### Glossary and Jargon
|
||||
|
||||
@@ -38,8 +38,8 @@ the router to pick the correct `Preparer` to run for the `Template` entity.
|
||||
|
||||
**Templater** - The templater is responsible for actually running the chosen
|
||||
templater on top of the previously returned temporary directory from the
|
||||
**Preprarer**. We advise making these docker containers as it can keep all
|
||||
dependencies, for example Cookiecutter, self contained and not a dependency on
|
||||
**Preprarer**. We advise making these Docker containers as it can keep all
|
||||
dependencies--for example Cookiecutter--self contained and not a dependency on
|
||||
the host machine.
|
||||
|
||||
**Publisher** - The publisher is responsible for taking the finished directory,
|
||||
@@ -50,11 +50,11 @@ passed through to the scaffolder backend.
|
||||
|
||||
### How it works
|
||||
|
||||
The main of the heavy lifting is done in the
|
||||
Most of the heavy lifting is done in the
|
||||
[router.ts](https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/src/service/router.ts#L93)
|
||||
file in the `scaffolder-backend` plugin.
|
||||
|
||||
There are 2 routes defined in the router. `POST /v1/jobs` and
|
||||
There are two routes defined in the router: `POST /v1/jobs` and
|
||||
`GET /v1/job/:jobId`
|
||||
|
||||
To create a scaffolding job, a JSON object containing the
|
||||
@@ -78,7 +78,7 @@ additional templating values must be posted as the post body.
|
||||
The values should represent something that is valid with the `schema` part of
|
||||
the [Template Entity](../../software-catalog/descriptor-format.md#kind-template)
|
||||
|
||||
Once that has been posted, a job will be setup with different stages. And the
|
||||
Once that has been posted, a job will be setup with different stages, and the
|
||||
job processor will complete each stage before moving onto the next stage, whilst
|
||||
collecting logs and mutating the running job.
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
---
|
||||
id: software-templates-index
|
||||
title: Software Templates
|
||||
title: Backstage Software Templates
|
||||
sidebar_label: Overview
|
||||
---
|
||||
|
||||
The Software Templates part of Backstage is a tool that can help you create
|
||||
Components inside Backstage. It by default has the ability to load skeletons of
|
||||
code, template in some variables and then publish the template to some location
|
||||
Components inside Backstage. By default, it has the ability to load skeletons of
|
||||
code, template in some variables, and then publish the template to some location
|
||||
like GitHub.
|
||||
|
||||
<video width="100%" height="100%" controls>
|
||||
@@ -33,8 +34,8 @@ internally.
|
||||

|
||||
|
||||
After filling in these variables, you'll get some more fields to fill out which
|
||||
are required for backstage usage. The owner, which is a `user` in the backstage
|
||||
system, and the `storePath` which right now must be a Github Organisation and a
|
||||
are required for backstage usage: the owner, (which is a `user` in the backstage
|
||||
system), the `storePath` (which right now must be a GitHub Organisation), and a
|
||||
non-existing github repository name in the format `organisation/reponame`.
|
||||
|
||||

|
||||
@@ -51,13 +52,13 @@ It shouldn't take too long, and you'll have a success screen!
|
||||

|
||||
|
||||
If it fails, you'll be able to click on each section to get the log from the
|
||||
step that failed which can be helpful to debug.
|
||||
step that failed which can be helpful in debugging.
|
||||
|
||||

|
||||
|
||||
### View Component in Catalog
|
||||
|
||||
When it's been created you'll see the `View in Catalog` button, which will take
|
||||
When it's been created, you'll see the `View in Catalog` button, which will take
|
||||
you to the registered component in the catalog:
|
||||
|
||||

|
||||
|
||||
@@ -109,7 +109,7 @@ export default async function createPlugin({ logger }: PluginEnvironment) {
|
||||
preparers.register('file', filePreparer);
|
||||
preparers.register('github', githubPreparer);
|
||||
|
||||
// Create Github client with your access token from environment variables
|
||||
// Create GitHub client with your access token from environment variables
|
||||
const githubClient = new Octokit({ auth: process.env.GITHUB_ACCESS_TOKEN });
|
||||
const publisher = new GithubPublisher({ client: githubClient });
|
||||
|
||||
|
||||
@@ -101,3 +101,7 @@ more to come...
|
||||
https://github.com/spotify/backstage/blob/master/packages/techdocs-container
|
||||
[techdocs/cli]:
|
||||
https://github.com/spotify/backstage/blob/master/packages/techdocs-cli
|
||||
|
||||
## TechDocs Big Picture
|
||||
|
||||

|
||||
|
||||
@@ -42,7 +42,7 @@ sites with the Backstage UI.
|
||||
|
||||
The TechDocs Reader purpose is also to open up the opportunity to integrate
|
||||
TechDocs widgets for a customized full-featured TechDocs experience.
|
||||
([coming soon V.2](https://github.com/spotify/backstage/milestone/17))
|
||||
([coming soon V.3](./README.md#project-roadmap))
|
||||
|
||||
[TechDocs Reader](https://github.com/spotify/backstage/blob/master/plugins/techdocs/src/reader/README.md)
|
||||
|
||||
@@ -53,4 +53,4 @@ Reader. The reason why transformers were introduced was to provide a way to
|
||||
transform the HTML content on pre and post render (e.g. rewrite docs links or
|
||||
modify css).
|
||||
|
||||
[Transformers API docs](https://github.com/spotify/backstage/blob/master/plugins/techdocs/src/reader/transformers/README.md)
|
||||
[Transformers API docs](https://github.com/spotify/backstage/blob/master/plugins/techdocs/src/reader/README.md)
|
||||
|
||||
@@ -6,26 +6,43 @@ sidebar_label: Creating and Publishing Documentation
|
||||
|
||||
This section will guide you through:
|
||||
|
||||
- Creating a basic setup for your documentation
|
||||
- Writing and previewing your documentation in a local Backstage environment
|
||||
- Creating a build ready for publication
|
||||
- Publishing your documentation and making your Backstage instance read your
|
||||
published docs.
|
||||
- [Create a basic documentation setup](#create-a-basic-documentation-setup)
|
||||
- [Use the documentation template](#use-the-documentation-template)
|
||||
- [Manually add documentation setup to already existing repository](#manually-add-documentation-setup-to-already-existing-repository)
|
||||
- [Writing and previewing your documentation](#writing-and-previewing-your-documentation)
|
||||
|
||||
## Prerequisities
|
||||
|
||||
- [Docker](https://docs.docker.com/get-docker/)
|
||||
- Static file hosting
|
||||
- A working Backstage instance with TechDocs installed (see
|
||||
[TechDocs getting started](getting-started.md))
|
||||
|
||||
## Create a basic documentation setup
|
||||
|
||||
In your home directory (also known as `~`), create a directory that contains
|
||||
your documentation (for example, `hello-docs`). Inside this directory, create a
|
||||
file called `mkdocs.yml`. Below is a basic example of how it could look.
|
||||
### Use the documentation template
|
||||
|
||||
The `~/hello-docs/mkdocs.yml` file should have the following content:
|
||||
Your working Backstage instance should by default have a documentation template
|
||||
added. If not, follow these
|
||||
[instructions](../software-templates/installation.md#adding-templates) to add
|
||||
the documentation template.
|
||||
|
||||

|
||||
|
||||
Create an entity from the documentation template and you will get the needed
|
||||
setup for free.
|
||||
|
||||
!!! warning Currently the Backstage Software Templates are limited to create
|
||||
repositories inside GitHub organizations. You also need to generate an personal
|
||||
access token and use as an environment variable. Read more about this
|
||||
[here](../software-templates/installation.md#runtime-dependencies).
|
||||
|
||||
### Manually add documentation setup to already existing repository
|
||||
|
||||
Prerequisities:
|
||||
|
||||
- `catalog-info.yml` file registered to Backstage.
|
||||
|
||||
Create a `mkdocs.yml` file in the root of the repository with the following
|
||||
content:
|
||||
|
||||
```yaml
|
||||
site_name: 'example-docs'
|
||||
@@ -37,7 +54,20 @@ plugins:
|
||||
- techdocs-core
|
||||
```
|
||||
|
||||
The `~/hello-docs/docs/index.md` should have the following content:
|
||||
Update your `catalog-info.yaml` file in the root of the repository with the
|
||||
following content:
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
annotations:
|
||||
backstage.io/techdocs-ref: dir:./
|
||||
```
|
||||
|
||||
Create a `/docs` folder in the root of the project with at least a `index.md`
|
||||
file. _(If you add more markdown files, make sure to update the nav in the
|
||||
mkdocs.yml file to get a proper navigation for your documentation.)_
|
||||
|
||||
The `docs/index.md` can for example have the following content:
|
||||
|
||||
```md
|
||||
# example docs
|
||||
@@ -45,6 +75,9 @@ The `~/hello-docs/docs/index.md` should have the following content:
|
||||
This is a basic example of documentation.
|
||||
```
|
||||
|
||||
Commit your changes, open a pull request and merge. You will now get your
|
||||
updated documentation next time you run Backstage!
|
||||
|
||||
## Writing and previewing your documentation
|
||||
|
||||
Using the `techdocs-cli` you can preview your docs inside a local Backstage
|
||||
@@ -54,83 +87,6 @@ want to write your documentation.
|
||||
To do this you can run:
|
||||
|
||||
```bash
|
||||
cd ~/hello-docs/
|
||||
cd ~/<repository-path>/
|
||||
npx techdocs-cli serve
|
||||
```
|
||||
|
||||
## Build production ready documentation
|
||||
|
||||
To get a build suitable for publication you can build your docs using the
|
||||
`spotify/techdocs` container:
|
||||
|
||||
```bash
|
||||
cd ~/hello-docs/
|
||||
docker run -it -w /content -v $(pwd):/content spotify/techdocs build
|
||||
```
|
||||
|
||||
You should now have a folder called `~/hello-docs/site/`.
|
||||
|
||||
## Deploy to a file server
|
||||
|
||||
In order to serve documentation to TechDocs, our Backstage plugin needs to
|
||||
download the HTML rendered from the previous step. This will likely exist on an
|
||||
external file server, or a storage solution such as Google Cloud Storage.
|
||||
|
||||
When deploying documentation, it should be deployed on that file server/storage
|
||||
solution with the following convention: `{id}/{file}`. For example, if you want
|
||||
to upload the `getting-started/index.html` file for the `backstage`
|
||||
documentation site, we would upload it to our file server as
|
||||
`backstage/getting-started/index.html`.
|
||||
|
||||
To explain further what this would look like for multiple documentation sites,
|
||||
take a look at this example file tree that would be represented on your file
|
||||
server:
|
||||
|
||||
```md
|
||||
/backstage/index.html /backstage/getting-started/index.html
|
||||
/backstage/contributing/index.html /mkdocs/index.html
|
||||
/mkdocs/plugin-development/index.html
|
||||
/mkdocs/plugin-development/debugging/index.html
|
||||
```
|
||||
|
||||
In this file tree, we have two documentation sites available: `backstage` and
|
||||
`mkdocs`. Each of them expose several pages. Let's say both of these are hosted
|
||||
on `http://example.com` as the server URL.
|
||||
|
||||
When you configure the TechDocs plugin in Backstage to use `http://example.com`
|
||||
as the file server/storage solution, it will translate the following URLs to the
|
||||
file server:
|
||||
|
||||
| Backstage URL | File Server URL |
|
||||
| --------------------------------------------------------- | ------------------------------------------------------- |
|
||||
| https://demo.backstage.io/docs/backstage/ | http://example.com/backstage/index.html |
|
||||
| https://demo.backstage.io/docs/mkdocs/plugin-development/ | http://example.com/mkdocs/plugin-development/index.html |
|
||||
|
||||
Then deploying new sites is easy: simply copy over the `site/` folder produced
|
||||
in the [Create documentation](#build-production-ready-documentation) step above
|
||||
to the file server/storage solution under the ID of the documentation site. It
|
||||
will then become immediately available in Backstage under the same ID as you can
|
||||
see in the table above.
|
||||
|
||||
So, if the URL to your file server is `http://example.com/`, your
|
||||
`~/hello-docs/site` folder containing the documentation should be accessible at
|
||||
`http://example.com/hello-docs/`.
|
||||
|
||||
## Configure TechDocs to read from file server
|
||||
|
||||
In order for Backstage to show your documentation, it needs to know where you
|
||||
uploaded it.
|
||||
|
||||
Make sure you have Backstage set up using
|
||||
[TechDocs getting started](getting-started.md).
|
||||
|
||||
To point Backstage to your docs storage, add or change the following lines in
|
||||
your Backstage `app-config.yaml`:
|
||||
|
||||
```yaml
|
||||
techdocs:
|
||||
storageUrl: http://example.com
|
||||
```
|
||||
|
||||
You can now start Backstage using `yarn start` and open up your browser at
|
||||
`http://localhost:3000/docs/hello-docs` to view your docs.
|
||||
|
||||
@@ -3,16 +3,6 @@ id: getting-started
|
||||
title: Getting Started
|
||||
---
|
||||
|
||||
> TechDocs is not yet feature complete - currently you can't set up a complete
|
||||
> end-to-end working TechDocs plugin without customizing the plugin itself.
|
||||
|
||||
> What you can expect from TechDocs V.0 is a demonstration of how to integrate
|
||||
> docs into Backstage. TechDocs can create docs using
|
||||
> [mkdocs](https://www.mkdocs.org/), as well as read published docs. If you
|
||||
> publish generated docs and pass in a `storageUrl` in your `app-config.yaml`,
|
||||
> you can view them in Backstage by going to
|
||||
> `http://localhost:3000/docs/<remote-folder>`.
|
||||
|
||||
TechDocs functions as a plugin to Backstage, so you will need to use Backstage
|
||||
to use TechDocs.
|
||||
|
||||
@@ -38,7 +28,7 @@ installed:
|
||||
To create a new Backstage application for TechDocs, run the following command:
|
||||
|
||||
```bash
|
||||
npx @backstage/cli create-app
|
||||
npx @backstage/create-app
|
||||
```
|
||||
|
||||
You will then be prompted to enter a name for your application. Once that's
|
||||
@@ -48,8 +38,8 @@ containing your new Backstage application.
|
||||
|
||||
## Installing TechDocs
|
||||
|
||||
TechDocs is not provided with the Backstage application by default, so you will
|
||||
now need to set up TechDocs manually. It should take less than a minute.
|
||||
TechDocs is provided with the Backstage application by default. If you want to
|
||||
set up TechDocs manually, keep follow the instructions below.
|
||||
|
||||
### Adding the package
|
||||
|
||||
@@ -84,19 +74,29 @@ export { plugin as TechDocs } from '@backstage/plugin-techdocs';
|
||||
### Setting the configuration
|
||||
|
||||
TechDocs allows for configuration of the docs storage URL through your
|
||||
`app-config` file. The URL provided here is for demo docs to use for testing
|
||||
purposes.
|
||||
`app-config` file.
|
||||
|
||||
To use the demo docs, add the following lines to `app-config.yaml`:
|
||||
The default storage URL:
|
||||
|
||||
```yaml
|
||||
techdocs:
|
||||
storageUrl: https://techdocs-mock-sites.storage.googleapis.com
|
||||
storageUrl: http://localhost:7000/techdocs/static/docs
|
||||
```
|
||||
|
||||
If you want to configure this to point to another storage URL, change the value
|
||||
of `storageUrl`.
|
||||
|
||||
## Run Backstage locally
|
||||
|
||||
Change folder to your Backstage application root and run the following command:
|
||||
Change folder to `<backstage-project-root>/packages/backend` and run the
|
||||
following command:
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
Open a new command line window. Change directory to your Backstage application
|
||||
root and run the following command:
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
|
||||
@@ -10,21 +10,20 @@ title: Other
|
||||
Run the following commands if you have Docker environment
|
||||
|
||||
```bash
|
||||
$ yarn install
|
||||
$ yarn docker-build
|
||||
$ docker run --rm -it -p 80:80 spotify/backstage
|
||||
$ docker run --rm -it -p 7000:7000 -e NODE_ENV=development example-backend:latest
|
||||
```
|
||||
|
||||
Then open http://localhost/ on your browser.
|
||||
|
||||
### Running with `docker-compose`
|
||||
|
||||
Run the following commands if you have docker and docker-compose for a full
|
||||
example, with the example backend also deployed.
|
||||
There is also a `docker-compose.yaml` that you can use to replace the previous
|
||||
`docker run` command:
|
||||
|
||||
```bash
|
||||
$ yarn docker-build:all
|
||||
$ yarn install
|
||||
$ yarn docker-build
|
||||
$ docker-compose up
|
||||
```
|
||||
|
||||
Then open http://localhost:3000 on your browser to see the example app with an
|
||||
example backend.
|
||||
|
||||
@@ -65,6 +65,7 @@ yarn storybook # Start local storybook, useful for working on components in @bac
|
||||
yarn workspace @backstage/plugin-welcome start # Serve welcome plugin only, also supports --check
|
||||
|
||||
yarn tsc # Run typecheck, use --watch for watch mode
|
||||
yarn tsc:full # Run full type checking, for example without skipLibCheck, use in CI
|
||||
|
||||
yarn build # Build published versions of packages, depends on tsc
|
||||
|
||||
@@ -85,7 +86,3 @@ yarn create-plugin # Create a new plugin
|
||||
> See
|
||||
> [package.json](https://github.com/spotify/backstage/blob/master/package.json)
|
||||
> for other yarn commands/options.
|
||||
|
||||
[Next Step - Create a Backstage plugin](../plugins/create-a-plugin.md)
|
||||
|
||||
[Back to Docs](../README.md)
|
||||
|
||||
@@ -3,9 +3,23 @@ id: index
|
||||
title: Running Backstage Locally
|
||||
---
|
||||
|
||||
First make sure you are using NodeJS with an Active LTS Release, currently v12.
|
||||
This is made easy with a version manager such as nvm which allows for version
|
||||
switching.
|
||||
|
||||
```bash
|
||||
# Checking your version
|
||||
node --version
|
||||
> v14.7.0
|
||||
|
||||
# Adding a second node version
|
||||
nvm install 12
|
||||
> Downloading and installing node v12.18.3...
|
||||
> Now using node v12.18.3 (npm v6.14.6)
|
||||
```
|
||||
|
||||
To get up and running with a local Backstage to evaluate it, let's clone it off
|
||||
of GitHub and run an initial build. First make sure that you have at least node
|
||||
version 12 installed locally.
|
||||
of GitHub and run an initial build.
|
||||
|
||||
```bash
|
||||
# Start from your local development folder
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
---
|
||||
id: adopting
|
||||
title: Strategies for adopting
|
||||
---
|
||||
|
||||
This document outlines some general best practices that have been key to
|
||||
Backstage's success inside Spotify. Every organization is different and some of
|
||||
these learnings will therefore not be applicable for your company. We are hoping
|
||||
that this can become a living document, and strongly encourage you to contribute
|
||||
back whatever learnings you gather while adopting Backstage inside your company.
|
||||
|
||||
## Organizational setup
|
||||
|
||||
The true value of Backstage is unlocked when it becomes _THE_ developer portal
|
||||
at your company. As such it is important to recognize that you will need a
|
||||
central team that owns your Backstage deployment and treats it like a product.
|
||||
|
||||
This team will have **four** primary objectives:
|
||||
|
||||
1. Maintain and operate your deployment of Backstage. This includes customer
|
||||
support, infrastructure, CI/CD and, as your Backstage product grows, on-call
|
||||
support.
|
||||
|
||||
2. Drive adoption of customers (developers at your company).
|
||||
|
||||
3. Work with senior tech leadership and architects to ensure your organizations
|
||||
best practices for software development are encoded into a set of
|
||||
[Software Templates](../features/software-templates/index.md).
|
||||
|
||||
4. Evangelize Backstage as a central platform towards other
|
||||
infrastructure/platform teams.
|
||||
|
||||
## Internal evangelization
|
||||
|
||||
The last objective deserves more attention, since it is the least obvious, but
|
||||
also the most critical to successfully creating a consolidated platform. When
|
||||
done right, Backstage acts as a "platform of platforms" or marketplace between
|
||||
infra/platform teams and end-users:
|
||||
|
||||

|
||||
|
||||
While anyone at your company can contribute to the platform, the vast majority
|
||||
of work will be done by teams that also has internal engineers as their
|
||||
customers. The central team should treat these _contributing teams_ as customers
|
||||
of the platform as well.
|
||||
|
||||
These teams should be able to autonomously deliver value directly to their
|
||||
customers. This is done primarily by building [plugins](../plugins/index.md).
|
||||
Contributing teams should themselves treat their plugins as, or part of, the
|
||||
products they maintain.
|
||||
|
||||
> Case study: Inside Spotify we have a team that owns our CI platform. They
|
||||
> don't only maintain the pipelines and build servers, but also expose their
|
||||
> product in Backstage through a plugin. Since they also
|
||||
> [maintain their own API](../plugins/call-existing-api.md), they can improve
|
||||
> their product by iterating on API and UI in lockstep. Because the plugin
|
||||
> follows our [platform design guidelines](../dls/design.md) their customers get
|
||||
> a CI experience that is consistent with other tools on the platform (and users
|
||||
> don't have to become experts in Jenkins).
|
||||
|
||||
### Tactics
|
||||
|
||||
Example of tactics we have used to evangelize Backstage internally:
|
||||
|
||||
- Arrange "Lunch & Learns" and seminars. Frequently offer teams interested in
|
||||
Backstage development to come to a seminar where you show, for example, how to
|
||||
build a plugin from scratch.
|
||||
|
||||
- Embedding. As contributing teams start development of their first plugin it is
|
||||
often very appreciated to have one person from the central team come over and
|
||||
"embed" for a Sprint or two.
|
||||
|
||||
- Hack days. Backstage-focused Hackathons or hack days is a fun way to get
|
||||
people into plugin development.
|
||||
|
||||
- Show & tell meetings. In order to build an internal community around Backstage
|
||||
we have quarterly meetings where anyone working on Backstage is invited to
|
||||
present their work. This is a not only a great way to get early feedback, but
|
||||
also helps coordination between teams that are building overlapping
|
||||
experiences.
|
||||
|
||||
- Provide metrics. Add instrumentation to your Backstage deployment and make
|
||||
metrics available to contributing teams. At Spotify we have even gone so far
|
||||
as sending out weekly digest email showing how usage metrics have changed for
|
||||
individual plugins.
|
||||
|
||||
- Pro-actively identify new plugins. Reach out to teams that own internal UIs or
|
||||
platforms that you think would make sense to consolidate into Backstage.
|
||||
|
||||
## KPIs and metrics
|
||||
|
||||
These are some of the metrics that you can use to verify if Backstage has a
|
||||
successful impact on your software development process:
|
||||
|
||||
- **Onboarding time** Time until new engineers are productive. At Spotify we
|
||||
measure this as the time until the employee has merged their 10th PR (this
|
||||
metric was down 55% two years after deploying Backstage). Even though you may
|
||||
not be onboarding engineers at a rapid pace, this metric is a great proxy for
|
||||
the overall complexity of your ecosystem. Reducing it will therefore benefit
|
||||
your whole engineering organization, not just new joiners.
|
||||
|
||||
- **Number of merges per developer/day** Less time spent jumping between
|
||||
different tools and looking for information means more time to focus on
|
||||
shipping code. A second level of bottlenecks can be identified if you
|
||||
categorize contributions by domain (services, web, data, etc).
|
||||
|
||||
- **Deploys to production** Cousin to the metric above: How many times does an
|
||||
engineer push changes into production.
|
||||
|
||||
- **MTTR** With clear ownership of all the pieces in your micro services
|
||||
ecosystem and all tools integrated into one place, Backstage makes it quicker
|
||||
for teams to find the root cause of failures, and fix them.
|
||||
|
||||
- **Context switching** Reducing context switching can help engineers stay in
|
||||
the "zone". We measure the number of different tools an engineer have to
|
||||
interact with in order to get a certain job done (e.g. push a change, follow
|
||||
it into production and validate it did not break anything).
|
||||
|
||||
- **T-shapedness** A
|
||||
[T-shaped](https://medium.com/@jchyip/why-t-shaped-people-e8706198e437)
|
||||
engineer is someone that is able to contribute to different domains of
|
||||
engineering. Teams with T-shaped people have fewer bottlenecks and can
|
||||
therefore deliver more consistently. Backstage makes it easier to be T-shaped
|
||||
since tools and infrastructure is consistent between domains, and information
|
||||
is available centrally.
|
||||
|
||||
- **eNPS** Surveys asking about how productive people feel, how easy it is to
|
||||
find information and overall satisfaction with internal tools.
|
||||
|
||||
- **Fragmentation** _(Experimental)_ Backstage
|
||||
[Software Templates](../features/software-templates/index.md) helps drive
|
||||
standardization in your software ecosystem. By measuring the variance in
|
||||
technology between different software components it is possible to get a sense
|
||||
of the overall fragmentation in your ecosystem. Examples could include:
|
||||
framework versions, languages, deployment methods and various code quality
|
||||
measurements.
|
||||
|
||||
Additionally, these proxy metrics can be used to validate the success of
|
||||
Backstage as _the_ platform:
|
||||
|
||||
- Nr of teams that have contributed at least one plugin (currently 63 inside
|
||||
Spotify)
|
||||
|
||||
- Nr of total plugins (currently 135 inside Spotify)
|
||||
|
||||
- % of contributions coming from outside the central Backstage team (currently
|
||||
85% inside Spotify)
|
||||
|
||||
- Traditional metrics such as visits (MAU, DAU, etc) and page views. Currently
|
||||
~50% of all Spotifiers use Backstage on a monthly basis, even though the
|
||||
percentage of engineers is below 50%. Most engineers actually use Backstage on
|
||||
a daily basis.
|
||||
|
||||
Again, any feedback is appreciated. Please use the Edit button at the top of the
|
||||
page to make a suggestion.
|
||||
|
||||
_**Note!** It might be tempting to try to optimize Backstage usage and
|
||||
"engagement". Even though you want to consolidate all your tooling and technical
|
||||
documentation in Backstage, it is important to remember that time spent in
|
||||
Backstage is time not spent writing code_ 🙃
|
||||
@@ -171,21 +171,19 @@ The frontend container can be built with a provided command.
|
||||
```bash
|
||||
yarn install
|
||||
yarn tsc
|
||||
yarn build
|
||||
yarn run docker-build
|
||||
yarn run docker-build:app
|
||||
```
|
||||
|
||||
Running this will simply generate a Docker container containing the contents of
|
||||
the UIs `dist` directory. The resulting container will be about 50MB in size.
|
||||
the UIs `dist` directory.
|
||||
|
||||
The backend container can be built by running the following command in the
|
||||
`packages/backend` directory.
|
||||
The backend container can be built by running the following command:
|
||||
|
||||
```bash
|
||||
yarn run build-image
|
||||
yarn run docker-build
|
||||
```
|
||||
|
||||
This will create a ~500MB container called `example-backend`.
|
||||
This will create a container called `example-backend`.
|
||||
|
||||
The lighthouse-audit-service container is already publicly available in Docker
|
||||
Hub and can be downloaded and ran with
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
id: background
|
||||
title: The Spotify Story
|
||||
---
|
||||
|
||||
Backstage was born out of necessity at Spotify. We found that as we grew, our
|
||||
infrastructure was becoming more fragmented, our engineers less productive.
|
||||
|
||||
Instead of building and testing code, teams were spending more time looking for
|
||||
the right information just to get started. “Where’s the API for that service
|
||||
we’re all supposed to be using?” “What version of that framework is everyone
|
||||
on?” “This service isn’t responding, who owns it?” “I can’t find documentation
|
||||
for anything!”
|
||||
|
||||
Context switching and cognitive overload were dragging engineers down, day by
|
||||
day. We needed to make it easier for our engineers to do their work without
|
||||
having to become an expert in every aspect of infrastructure tooling.
|
||||
|
||||
Our idea was to centralize and simplify end-to-end software development with an
|
||||
abstraction layer that sits on top of all of our infrastructure and developer
|
||||
tooling. That’s Backstage.
|
||||
|
||||
It’s a developer portal powered by a centralized service catalog — with a plugin
|
||||
architecture that makes it endlessly extensible and customizable.
|
||||
|
||||
Manage all your services, software, tooling, and testing in Backstage. Start
|
||||
building a new microservice using an automated template in Backstage. Create,
|
||||
maintain, and find the documentation for all that software in Backstage.
|
||||
|
||||
One place for everything. Accessible to everyone.
|
||||
@@ -79,18 +79,26 @@ guidelines to get started.
|
||||
|
||||
- Further improvements to platform documentation
|
||||
|
||||
### Plugins
|
||||
|
||||
Building and maintaining [plugins](https://backstage.io/plugins) is the work of
|
||||
the entire Backstage community.
|
||||
|
||||
A list of plugins that are in development is
|
||||
[available here](https://github.com/spotify/backstage/issues?q=is%3Aissue+is%3Aopen+label%3Aplugin+sort%3Areactions-%2B1-desc).
|
||||
We strongly recommend to upvote 👍 plugins you are interested in. This helps us
|
||||
and the community prioritize what plugins to build.
|
||||
|
||||
Are you missing a plugin for your favorite tool? Please
|
||||
[suggest a new one](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME).
|
||||
Chances are that someone will jump in and help build it.
|
||||
|
||||
### Future work 🔮
|
||||
|
||||
- **[Backstage platform is stable](https://github.com/spotify/backstage/milestone/19)** -
|
||||
The platform APIs and features are stable and can be depended on for
|
||||
production use. After this plugins will require little to no maintenance.
|
||||
|
||||
- **[Plugin marketplace](https://github.com/spotify/backstage/issues/2009)** -
|
||||
As the ecosystem of Backstage plugins continues to grow it is becoming
|
||||
increasingly hard to keep track of what plugins are available. To solve this
|
||||
we imagine a "Plugin marketplace" that helps with discovery and installation
|
||||
of plugins.
|
||||
|
||||
- **Deploy a product demo at `demo.backstage.io`** - Deploy a typical Backstage
|
||||
deployment available publicly so that people can click around and get a feel
|
||||
for the product without having to install anything.
|
||||
@@ -111,6 +119,7 @@ guidelines to get started.
|
||||
|
||||
### Completed milestones ✅
|
||||
|
||||
- [Plugin marketplace](https://backstage.io/plugins)
|
||||
- [Improved and move documentation to backstage.io](https://backstage.io/docs/overview/what-is-backstage)
|
||||
- [Backstage Service Catalog (alpha)](https://backstage.io/blog/2020/06/22/backstage-service-catalog-alpha)
|
||||
- [Backstage Software Templates (alpha)](https://backstage.io/blog/2020/08/05/announcing-backstage-software-templates)
|
||||
|
||||
@@ -18,12 +18,15 @@ Out of the box, Backstage includes:
|
||||
- [Backstage Service Catalog](../features/software-catalog/index.md) for
|
||||
managing all your software (microservices, libraries, data pipelines,
|
||||
websites, ML models, etc.)
|
||||
|
||||
- [Backstage Software Templates](../features/software-templates/index.md) for
|
||||
quickly spinning up new projects and standardizing your tooling with your
|
||||
organization’s best practices
|
||||
|
||||
- [Backstage TechDocs](../features/techdocs/README.md) for making it easy to
|
||||
create, maintain, find, and use technical documentation, using a "docs like
|
||||
code" approach
|
||||
|
||||
- Plus, a growing ecosystem of
|
||||
[open source plugins](https://github.com/spotify/backstage/tree/master/plugins)
|
||||
that further expand Backstage’s customizability and functionality
|
||||
@@ -33,12 +36,15 @@ Out of the box, Backstage includes:
|
||||
- For _engineering managers_, it allows you to maintain standards and best
|
||||
practices across the organization, and can help you manage your whole tech
|
||||
ecosystem, from migrations to test certification.
|
||||
|
||||
- For _end users_ (developers), it makes it fast and simple to build software
|
||||
components in a standardized way, and it provides a central place to manage
|
||||
all projects and documentation.
|
||||
|
||||
- For _platform engineers_, it enables extensibility and scalability by letting
|
||||
you easily integrate new tools and services (via plugins), as well as
|
||||
extending the functionality of existing ones.
|
||||
|
||||
- For _everyone_, it’s a single, consistent experience that ties all your
|
||||
infrastructure tooling, resources, standards, owners, contributors, and
|
||||
administrators together in one place.
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
id: add-to-marketplace
|
||||
title: Add to Marketplace
|
||||
---
|
||||
|
||||
## Adding a Plugin to the Marketplace
|
||||
|
||||
To add a new plugin to the [plugin marketplace](https://backstage.io/plugins)
|
||||
create a file in
|
||||
[`microsite/data/plugins`](https://github.com/spotify/backstage/tree/master/microsite/data/plugins)
|
||||
with your plugin's information. Example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Your Plugin
|
||||
author: Your Name
|
||||
authorUrl: # A link to information about the author E.g. Company url, github user profile, etc
|
||||
category: Monitoring # A single category e.g. CI, Machine Learning, Services, Monitoring
|
||||
description: A brief description of the plugin. # Max 170 characters
|
||||
documentation: # A link to your documentation E.g. Your github README
|
||||
iconUrl: # Used as the src attribute for your logo.
|
||||
# You can provide an external url or add your logo under static/img and provide a path
|
||||
# relative to static/ e.g. img/my-logo.png
|
||||
npmPackageName: # Your npm package name E.g. '@backstage/plugin-<etc>' quotes are required
|
||||
```
|
||||
@@ -1,6 +1,172 @@
|
||||
---
|
||||
id: call-existing-api
|
||||
title: Call existing API
|
||||
title: Call Existing API
|
||||
---
|
||||
|
||||
## TODO
|
||||
This article describes the various options that Backstage frontend plugins have,
|
||||
in communicating with service APIs that already exist. Each section below
|
||||
describes a possible choice, and the circumstances under which it fits.
|
||||
|
||||
In these examples, we will be ultimately requesting data from the fictional
|
||||
FrobsCo API.
|
||||
|
||||
## Issuing Requests Directly
|
||||
|
||||
The most basic choice available is to issue requests directly from the plugin
|
||||
frontend code to the FrobsCo API, using for example `fetch` or a support library
|
||||
such as `axios`.
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
// Inside your component
|
||||
fetch('https://api.frobsco.com/v1/list')
|
||||
.then(response => response.json())
|
||||
.then(payload => setFrobs(payload as Frob[]));
|
||||
```
|
||||
|
||||
Internally at Spotify, this has not been a very common choice. Third party APIs
|
||||
are sometimes accessed like this. Just a handful of internal APIs also went
|
||||
through the trouble of exposing themselves in a way that is useful directly from
|
||||
a browser, but even then, often not from the public internet but only supporting
|
||||
users that are already on the company VPN.
|
||||
|
||||
This can be used when:
|
||||
|
||||
- The API already does/exposes exactly what you need.
|
||||
- The request/response patterns of the API match real world usage needs in
|
||||
Backstage frontend plugins. For example, if the end use case is to show a
|
||||
small summary in Backstage, but the only available API endpoint gives a 30
|
||||
megabyte blob with large amounts of redundant information, it would hurt the
|
||||
end user experience. Particularly on mobile. The same goes for cases where you
|
||||
want to show many individual pieces of information: if a common use case is to
|
||||
show large tables where one API request per cell is necessary, the browser
|
||||
will quickly become swamped and you may want to consider performing
|
||||
aggregation elsewhere instead.
|
||||
- The API can maintain interactive request/response times at your required peak
|
||||
request rates. The end user experience will be degraded if they spend a lot of
|
||||
time waiting for the data to arrive.
|
||||
- The API endpoint is highly available. The browser does not have builtin
|
||||
facilities for load balancing, service discovery, retries, health checks,
|
||||
circuit breaking and similar. If the endpoint is occasionally down even for
|
||||
short periods of time (e.g. during deploys), end users will quickly notice.
|
||||
- The API is exposed over HTTPS (not just HTTP), and properly handles
|
||||
[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). These are
|
||||
requirements that the user's browser will impose for security reasons, and the
|
||||
requests will be rejected otherwise.
|
||||
- The API endpoint is easily reachable, in terms of network conditions, by end
|
||||
users. This may be particularly relevant if your end users are outside of your
|
||||
perimeter.
|
||||
- The requests do not require secrets to be passed. This limitation does not
|
||||
apply to OAuth tokens, which the frontend can negotiate and make proper use
|
||||
of.
|
||||
|
||||
## Using The Backstage Proxy
|
||||
|
||||
Backstage has an optional proxy plugin for the backend, that can be used to
|
||||
easily add proxy routes to downstream APIs.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
# In app-config.yaml
|
||||
proxy:
|
||||
'/frobs': http://api.frobsco.com/v1
|
||||
```
|
||||
|
||||
```ts
|
||||
// Inside your component
|
||||
const backendUrl = config.getString('backend.baseUrl');
|
||||
fetch(`${backendUrl}/proxy/frobs/list`)
|
||||
.then(response => response.json())
|
||||
.then(payload => setFrobs(payload as Frob[]));
|
||||
```
|
||||
|
||||
The proxy is powered by the `http-proxy-middleware` package. See
|
||||
[Proxying](proxying.md) for a full description of its configuration options.
|
||||
|
||||
Internally at Spotify, the proxy option has been the overwhelmingly most popular
|
||||
choice for plugin makers. Since we have DNS based service discovery in place and
|
||||
a microservices framework that made it trivial to expose plain HTTP, it has been
|
||||
a matter of just adding a few lines of Backstage config to get the benefit of
|
||||
being easily and robustly reachable from users' web browsers as well.
|
||||
|
||||
This may be used instead of direct requests, when:
|
||||
|
||||
- You need to perform HTTPS termination and/or CORS handling, because the API
|
||||
itself is not supplying those.
|
||||
- You need to inject a simple static secret into the requests, e.g. an
|
||||
Authorization header that gets added to the request headers.
|
||||
- You want to make use of other proxy facilities, such as retries, failover,
|
||||
health checks, routing, request logging, rewrites, etc.
|
||||
- You already have the Backstage backend itself exposed through your perimeter
|
||||
and find it practical to have only one entry point to deal with, governing
|
||||
ingress with just the Backstage config.
|
||||
|
||||
## Creating a Backstage Backend Plugin
|
||||
|
||||
Much like the Backstage frontend, the Backstage backend also has a plugin
|
||||
system. The above mentioned proxy is actually one such plugin. If you were in
|
||||
need of a more involved integration than just direct access to the FrobsCo API,
|
||||
or if you needed to hold state, you may want to make such a plugin.
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
// Inside your component
|
||||
const backendUrl = config.getString('backend.baseUrl');
|
||||
fetch(`${backendUrl}/frobs-aggregator/summary`)
|
||||
.then(response => response.json())
|
||||
.then(payload => setSummary(payload as FrobSummary));
|
||||
```
|
||||
|
||||
```ts
|
||||
// Inside a new frobs-aggregator backend plugin
|
||||
router.use('/summary', async (req, res) => {
|
||||
const agg = await Promise.all([
|
||||
fetch('https://api.frobsco.com/v1/list'),
|
||||
fetch('http://flerps.partnercompany.com:8080/flerp-batch'),
|
||||
database.currentThunk(),
|
||||
]).then(async ([frobs, flerps, thunk]) => {
|
||||
return computeAggregate(await frobs.json(), await flerps.json(), thunk);
|
||||
});
|
||||
res.status(200).send(agg);
|
||||
});
|
||||
```
|
||||
|
||||
For a more detailed example, see
|
||||
[the lighthouse plugin](https://github.com/spotify/backstage/tree/master/plugins/lighthouse)
|
||||
that stores some state in a database and adds new capabilities to the underlying
|
||||
API.
|
||||
|
||||
Internally at Spotify, this has been a fairly popular choice for different
|
||||
reasons. Commonly, the backend has been used as a caching and data massaging
|
||||
layer for slow APIs or APIs whose request/response shapes or speeds were not
|
||||
acceptable for direct use by frontends. For example, this has made it possible
|
||||
to issue efficient batch queries from the frontend, e.g. in big lists or tables
|
||||
that want to resolve a lot of sparse data from the larger list that an
|
||||
underlying service supplies.
|
||||
|
||||
This may be used instead of the above, when:
|
||||
|
||||
- You need to perform complex model conversion, or protocol translation beyond
|
||||
what the proxy handles.
|
||||
- You want to perform aggregations or summaries on the backend instead of on the
|
||||
frontend.
|
||||
- You want to enable batching or caching of slower or more unreliable APIs.
|
||||
- You need to maintain state for your plugin, perhaps using the builtin database
|
||||
support in the backend.
|
||||
- You need to inject secrets or in other ways negotiate with other parts of the
|
||||
API or other services in order to perform your work.
|
||||
- You want to enforce end user authentication / authorization for operations on
|
||||
behalf of the API, have session handling, or similar.
|
||||
|
||||
There is a balance to strike regarding when to make an entirely separate backend
|
||||
for a purpose, and when to make a Backstage backend plugin that adapts something
|
||||
that already exists. General advice is not easy to give, but contact us on
|
||||
Discord if you have any questions, and we may be able to offer guidance.
|
||||
|
||||
## Extending the GraphQL Model
|
||||
|
||||
The extensible GraphQL backend layer is not built yet. This section will be
|
||||
expanded when that happens. Stay tuned!
|
||||
|
||||
@@ -15,20 +15,16 @@ dependencies, then run the following on your command line (invoking the
|
||||
yarn create-plugin
|
||||
```
|
||||
|
||||
<p align='center'>
|
||||
<img src='https://github.com/spotify/backstage/raw/master/docs/getting-started/create-plugin_output.png' width='600' alt='create plugin'>
|
||||
</p>
|
||||

|
||||
|
||||
This will create a new Backstage Plugin based on the ID that was provided. It
|
||||
will be built and added to the Backstage App automatically.
|
||||
|
||||
_If `yarn start` is already running you should be able to see the default page
|
||||
for your new plugin directly by navigating to
|
||||
`http://localhost:3000/my-plugin`._
|
||||
> If `yarn start` is already running you should be able to see the default page
|
||||
> for your new plugin directly by navigating to
|
||||
> `http://localhost:3000/my-plugin`.
|
||||
|
||||
<p align='center'>
|
||||
<img src='https://github.com/spotify/backstage/raw/master/docs/plugins/my-plugin_screenshot.png' width='600' alt='my plugin'>
|
||||
</p>
|
||||

|
||||
|
||||
You can also serve the plugin in isolation by running `yarn start` in the plugin
|
||||
directory. Or by using the yarn workspace command, for example:
|
||||
@@ -40,7 +36,3 @@ yarn workspace @backstage/plugin-welcome start # Also supports --check
|
||||
This method of serving the plugin provides quicker iteration speed and a faster
|
||||
startup and hot reloads. It is only meant for local development, and the setup
|
||||
for it can be found inside the plugin's `dev/` directory.
|
||||
|
||||
[Next Step - Structure of a plugin](structure-of-a-plugin.md)
|
||||
|
||||
[Back to Getting Started](../README.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
id: index
|
||||
title: Intro
|
||||
title: Intro to plugins
|
||||
---
|
||||
|
||||
Backstage is a single-page application composed of a set of plugins.
|
||||
@@ -21,8 +21,15 @@ To create a plugin, follow the steps outlined [here](create-a-plugin.md).
|
||||
|
||||
If you start developing a plugin that you aim to release as open source, we
|
||||
suggest that you create a new
|
||||
[new Issue](https://github.com/spotify/backstage/issues/new?template=plugin_template.md).
|
||||
[new Issue](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME).
|
||||
This helps the community know what plugins are in development.
|
||||
|
||||
You can also use this process if you have an idea for a good plugin but you hope
|
||||
that someone else will pick up the work.
|
||||
|
||||
## Integrate into the Service Catalog
|
||||
|
||||
If your plugin isn't supposed to live as a standalone page, but rather needs to
|
||||
be presented as a part of a Service Catalog (e.g. a separate tab or a card on an
|
||||
"Overview" tab), then check out
|
||||
[the instruction](integrating-plugin-into-service-catalog.md). on how to do it.
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
---
|
||||
id: integrating-plugin-into-service-catalog
|
||||
title: Integrate into the Service Catalog
|
||||
---
|
||||
|
||||
> This is an advanced use case and currently is an experimental feature. Expect
|
||||
> API to change over time
|
||||
|
||||
## Steps
|
||||
|
||||
1. [Create a plugin](#create-a-plugin)
|
||||
1. [Export a router with relative routes](#export-a-router)
|
||||
1. [Import and use router in the APP](#import-and-use-router-in-the-app)
|
||||
|
||||
### Create a plugin
|
||||
|
||||
Follow the [same process](create-a-plugin.md) as for standalone plugin. You
|
||||
should have a separate package in a folder, which represents your plugin.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
$ yarn create-plugin
|
||||
> ? Enter an ID for the plugin [required] my-plugin
|
||||
> ? Enter the owner(s) of the plugin. If specified, this will be added to CODEOWNERS for the plugin path. [optional]
|
||||
|
||||
Creating the plugin...
|
||||
```
|
||||
|
||||
### Export a router
|
||||
|
||||
Now in the plugin you have a `Router.tsx` file in the `src` folder. By default
|
||||
it contains only one example route. Create a routing structure needed for your
|
||||
plugin, keeping in mind that the whole set of routes defined here are going to
|
||||
be mounted under some different route in the App.
|
||||
|
||||
Example:
|
||||
|
||||
`my-plugin` consists of 2 different views - `/me` and `/about`. I envision
|
||||
people integrating it into plugin catalog as a tab named "MyPlugin". Then, my
|
||||
`Routes.tsx` for the plugin is going to look like:
|
||||
|
||||
```tsx
|
||||
<Routes>
|
||||
<Route path="/me" element={<MePage />} />
|
||||
<Route path="/about" element={<AboutPage />} />
|
||||
</Routes>
|
||||
```
|
||||
|
||||
(where MePage and AboutPage are 2 components defined in your plugin and imported
|
||||
accordingly inside `Router.tsx`)
|
||||
|
||||
> Pay attention, if your `MePage` references the `AboutPage` it needs to do it
|
||||
> through link to `about`, not `/about`. This allows react-router v6 to enable
|
||||
> its relative routing mechanism. Read more -
|
||||
> https://reacttraining.com/blog/react-router-v6-pre/#relative-route-path-and-link-to
|
||||
|
||||
### Import and use router in the APP
|
||||
|
||||
In the `app/src/components/catalog/EntityPage.tsx` (app === your folder,
|
||||
containing backstage app) import your created Router:
|
||||
|
||||
```tsx
|
||||
import { Router as MyPluginRouter } from '@backstage/plugin-my-plugin;
|
||||
```
|
||||
|
||||
Now, you need to mount `MyPluginRouter` onto some route, for example if you had:
|
||||
|
||||
```tsx
|
||||
const DefaultEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/"
|
||||
title="Overview"
|
||||
element={<OverviewPage entity={entity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
```
|
||||
|
||||
after you add your code it becomes:
|
||||
|
||||
```tsx
|
||||
const DefaultEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
<EntityPageLayout>
|
||||
<EntityPageLayout.Content
|
||||
path="/"
|
||||
title="Overview"
|
||||
element={<OverviewPage entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/my-plugin"
|
||||
title="My Plugin"
|
||||
element={<MyPluginRouter entity={entity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
```
|
||||
|
||||
All of magic happens thanks to the `EntityPageLayout` component, which comes as
|
||||
an export from `@backstage/plugin-catalog` package.
|
||||
|
||||
```tsx
|
||||
type EntityPageLayoutContentProps = {
|
||||
/**
|
||||
* Going to be transformed into react-router v6
|
||||
* path under the hood. Read more at https://reacttraining.com/blog/react-router-v6-pre
|
||||
*/
|
||||
path: string;
|
||||
/**
|
||||
* Gets transformed into the title for the tab
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* Element that is rendered when the location
|
||||
* matches the path provided
|
||||
*/
|
||||
element: JSX.Element;
|
||||
};
|
||||
```
|
||||
|
||||
> You can either pass the entity from App to the plugin's router as a prop or
|
||||
> use `useEntity` hook from `@backstage/plugin-catalog` directly inside your
|
||||
> plugin.
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
id: plugin-development
|
||||
title: Plugin Development in Backstage
|
||||
title: Plugin Development
|
||||
---
|
||||
|
||||
Backstage plugins provide features to a Backstage App.
|
||||
@@ -10,28 +10,12 @@ type of content. Plugins all use a common set of platform APIs and reusable UI
|
||||
components. Plugins can fetch data from external sources using the regular
|
||||
browser APIs or by depending on external modules to do the work.
|
||||
|
||||
<!-- MOVED TO create-a-plugin.md ## Creating a new plugin
|
||||
On your command line, invoke the `backstage-cli` to create a new plugin:
|
||||
```bash
|
||||
yarn create-plugin
|
||||
```
|
||||
|
||||

|
||||
|
||||
This will create a new Backstage Plugin based on the ID that was provided. It will be built and
|
||||
added to the Backstage App automatically.
|
||||
|
||||
*If `yarn start` is already running you should be able to see the default page for your new
|
||||
plugin directly by navigating to `http://localhost:3000/my-plugin`.*
|
||||
|
||||
 -->
|
||||
|
||||
## Developing guidelines
|
||||
|
||||
- Consider writing plugins in `TypeScript`.
|
||||
- Plan the directory structure of your plugin so that it becomes easy to manage.
|
||||
- Prefer using the Backstage components, otherwise go with
|
||||
[Material-UI](https://material-ui.com/).
|
||||
- Prefer using the [Backstage components](https://backstage.io/storybook),
|
||||
otherwise go with [Material-UI](https://material-ui.com/).
|
||||
- Check out the shared Backstage APIs before building a new one.
|
||||
|
||||
## Plugin concepts / API
|
||||
|
||||
@@ -3,4 +3,73 @@ id: proxying
|
||||
title: Proxying
|
||||
---
|
||||
|
||||
## TODO
|
||||
## Overview
|
||||
|
||||
The Backstage backend comes packaged with a basic HTTP proxy, that can aid in
|
||||
reaching backend service APIs from frontend plugin code. See
|
||||
[Call Existing API](call-existing-api.md) for a description of when the proxy
|
||||
can be the best choice for communicating with an API.
|
||||
|
||||
## Getting Started
|
||||
|
||||
The plugin is already added to a default Backstage project.
|
||||
|
||||
In `packages/backend/src/index.ts`:
|
||||
|
||||
```ts
|
||||
const proxyEnv = useHotMemoize(module, () => createEnv('proxy'));
|
||||
|
||||
const service = createServiceBuilder(module)
|
||||
.loadConfig(configReader)
|
||||
/** ... other routers ... */
|
||||
.addRouter('/proxy', await proxy(proxyEnv, '/proxy'));
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration for the proxy plugin lives under a `proxy` root key of your
|
||||
`app-config.yaml` file.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
# in app-config.yaml
|
||||
proxy:
|
||||
'/simple-example': http://simple.example.com:8080
|
||||
'/larger-example/v1':
|
||||
target: http://larger.example.com:8080/svc.v1
|
||||
headers:
|
||||
Authorization:
|
||||
$secret:
|
||||
env: EXAMPLE_AUTH_HEADER
|
||||
```
|
||||
|
||||
Each key under the proxy configuration entry is a route to match, below the
|
||||
prefix that the proxy plugin is mounted on. It must start with a slash. For
|
||||
example, if the backend mounts the proxy plugin as `/proxy`, the above
|
||||
configuration will lead to the proxy acting on backend requests to
|
||||
`/proxy/simple-example/...` and `/proxy/larger-example/v1/...`.
|
||||
|
||||
The value inside each route is either a simple URL string, or an object on the
|
||||
format accepted by
|
||||
[http-proxy-middleware](https://www.npmjs.com/package/http-proxy-middleware).
|
||||
|
||||
If the value is a string, it is assumed to correspond to:
|
||||
|
||||
```yaml
|
||||
target: <the string>
|
||||
changeOrigin: true
|
||||
pathRewrite:
|
||||
'^<url prefix><the string>/': '/'
|
||||
```
|
||||
|
||||
When the target is an object, it is given verbatim to `http-proxy-middleware`
|
||||
except with the following caveats for convenience:
|
||||
|
||||
- If `changeOrigin` is not specified, it is set to `true`. This is the most
|
||||
commonly useful value.
|
||||
- If `pathRewrite` is not specified, it is set to a single rewrite that removes
|
||||
the entire prefix and route. In the above example, a rewrite of
|
||||
`'^/proxy/larger-example/v1/': '/'` is added. That means that a request to
|
||||
`/proxy/larger-example/v1/some/path` will be translated to a request to
|
||||
`http://larger.example.com:8080/svc.v1/some/path`.
|
||||
|
||||
@@ -39,4 +39,18 @@ $ git push origin -u new-release
|
||||
And then create a PR. Once the PR is approved and merged into master, the master
|
||||
build will publish new versions of all bumped packages.
|
||||
|
||||
### Include new changes in existing release PR
|
||||
|
||||
If you want to include some last minute changes to an existing release PR,
|
||||
follow these instructions:
|
||||
|
||||
```sh
|
||||
$ git checkout master
|
||||
$ git pull
|
||||
$ git checkout new-release
|
||||
$ git reset --hard master
|
||||
$ yarn release
|
||||
$ git push --force
|
||||
```
|
||||
|
||||
[Back to Docs](../README.md)
|
||||
|
||||
@@ -37,5 +37,3 @@ const myPluginRouteRef = createRouteRef({
|
||||
title: 'My Plugin',
|
||||
});
|
||||
```
|
||||
|
||||
[Back to References](../README.md)
|
||||
|
||||
@@ -55,7 +55,7 @@ ApiRef:
|
||||
|
||||
## githubAuth
|
||||
|
||||
Provides authentication towards Github APIs
|
||||
Provides authentication towards GitHub APIs
|
||||
|
||||
Implemented types: [OAuthApi](./OAuthApi.md),
|
||||
[ProfileInfoApi](./ProfileInfoApi.md),
|
||||
@@ -67,7 +67,7 @@ ApiRef:
|
||||
|
||||
## gitlabAuth
|
||||
|
||||
Provides authentication towards Gitlab APIs
|
||||
Provides authentication towards GitLab APIs
|
||||
|
||||
Implemented types: [OAuthApi](./OAuthApi.md),
|
||||
[ProfileInfoApi](./ProfileInfoApi.md),
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
id: index
|
||||
title: Overview
|
||||
---
|
||||
|
||||
## Coming soon!
|
||||
@@ -1,12 +1,15 @@
|
||||
# Purpose
|
||||
---
|
||||
id: journey
|
||||
title: Future developer journey
|
||||
---
|
||||
|
||||
This RFC describes a possible journey of a future Backstage plugin developer as
|
||||
they build a plugin that touches many different aspects of a Backstage. The
|
||||
story invents many new things that are not part of Backstage today, but are
|
||||
things that I'm suggesting we should add as long term or north star goals. The
|
||||
idea is to discuss what parts of the story makes sense to aim for, and what we'd
|
||||
want to do differently or not at all. The "chapters" are numbered to make it a
|
||||
bit easier to comment on parts of the story.
|
||||
> This document describes a possible journey of a **_future_** Backstage plugin
|
||||
> developer as they build a plugin that touches many different aspects of a
|
||||
> Backstage. The story invents many new things that are not part of Backstage
|
||||
> today, but are things that I'm suggesting we should add as long term or north
|
||||
> star goals. The idea is to discuss what parts of the story makes sense to aim
|
||||
> for, and what we'd want to do differently or not at all. The "chapters" are
|
||||
> numbered to make it a bit easier to comment on parts of the story.
|
||||
|
||||
# The Protagonist
|
||||
|
||||
@@ -18,10 +18,10 @@ spec:
|
||||
component: frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: spotify/backstage:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: app
|
||||
protocol: TCP
|
||||
- name: app
|
||||
image: spotify/backstage:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: app
|
||||
protocol: TCP
|
||||
|
||||
@@ -18,10 +18,10 @@ spec:
|
||||
component: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: backend
|
||||
image: spotify/backstage-backend:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 7000
|
||||
name: backend
|
||||
protocol: TCP
|
||||
- name: backend
|
||||
image: spotify/backstage-backend:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 7000
|
||||
name: backend
|
||||
protocol: TCP
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
apiVersion: v1
|
||||
appVersion: "1.0"
|
||||
appVersion: '1.0'
|
||||
description: A Helm chart for Spotify Backstage
|
||||
name: backstage
|
||||
version: 0.1.1-alpha.12
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
| app.resources | Kubernetes Pod resource requests/limits | `{}` |
|
||||
| app.nodeSelector | Node selectors for scheduling app/frontend pods | `{}` |
|
||||
| app.tolerations | Tolerations for scheduling app/frontend pods | `{}` |
|
||||
| app.affinity | Affinity setttings for scheduling app/frontend pods | `{}` |
|
||||
| app.affinity | Affinity settings for scheduling app/frontend pods | `{}` |
|
||||
|
||||
## Backend Values
|
||||
|
||||
@@ -48,4 +48,4 @@
|
||||
| backend.resources | Kubernetes Pod resource requests/limits | `{}` |
|
||||
| backend.nodeSelector | Node selectors for scheduling backend pods | `{}` |
|
||||
| backend.tolerations | Tolerations for scheduling backend pods | `{}` |
|
||||
| backend.affinity | Affinity setttings for scheduling backend pods | `{}` |
|
||||
| backend.affinity | Affinity settings for scheduling backend pods | `{}` |
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
app:
|
||||
enabled: true
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
nameOverride: ''
|
||||
fullnameOverride: ''
|
||||
replicaCount: 1
|
||||
serviceAccount:
|
||||
create: false
|
||||
Name: ""
|
||||
image:
|
||||
Name: ''
|
||||
image:
|
||||
repository: spotify/backstage
|
||||
tag: latest
|
||||
pullPolicy: Always
|
||||
@@ -15,20 +15,23 @@ app:
|
||||
port: 80
|
||||
ingress:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
annotations:
|
||||
{}
|
||||
# kubernetes.io/ingress.class: "nginx"
|
||||
hosts:
|
||||
- host: backstage.local
|
||||
paths:
|
||||
- /
|
||||
- host: backstage.local
|
||||
paths:
|
||||
- /
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
imagePullSecrets: []
|
||||
podSecurityContext: {}
|
||||
podSecurityContext:
|
||||
{}
|
||||
# fsGroup: 2000
|
||||
securityContext: {}
|
||||
securityContext:
|
||||
{}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
@@ -48,12 +51,12 @@ app:
|
||||
|
||||
backend:
|
||||
enabled: false
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
nameOverride: ''
|
||||
fullnameOverride: ''
|
||||
replicaCount: 1
|
||||
serviceAccount:
|
||||
create: false
|
||||
Name: ""
|
||||
Name: ''
|
||||
image:
|
||||
repository: spotify/backstage-backend
|
||||
tag: latest
|
||||
@@ -63,20 +66,23 @@ backend:
|
||||
port: 7000
|
||||
ingress:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
annotations:
|
||||
{}
|
||||
# kubernetes.io/ingress.class: "nginx"
|
||||
hosts:
|
||||
- host: backstage.local
|
||||
paths:
|
||||
- /backend
|
||||
- host: backstage.local
|
||||
paths:
|
||||
- /backend
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
imagePullSecrets: []
|
||||
podSecurityContext: {}
|
||||
podSecurityContext:
|
||||
{}
|
||||
# fsGroup: 2000
|
||||
securityContext: {}
|
||||
securityContext:
|
||||
{}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
|
||||
@@ -7,14 +7,14 @@ metadata:
|
||||
component: ingress
|
||||
spec:
|
||||
rules:
|
||||
- host: <HOSTNAME>
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: backstage
|
||||
servicePort: frontend
|
||||
path: /
|
||||
- backend:
|
||||
serviceName: backstage-backend
|
||||
servicePort: backend
|
||||
path: /backend
|
||||
- host: <HOSTNAME>
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: backstage
|
||||
servicePort: frontend
|
||||
path: /
|
||||
- backend:
|
||||
serviceName: backstage-backend
|
||||
servicePort: backend
|
||||
path: /backend
|
||||
|
||||
@@ -11,10 +11,10 @@ spec:
|
||||
app: backstage
|
||||
component: frontend
|
||||
ports:
|
||||
- name: frontend
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: app
|
||||
- name: frontend
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: app
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
@@ -29,7 +29,7 @@ spec:
|
||||
app: backstage
|
||||
component: backend
|
||||
ports:
|
||||
- name: backend
|
||||
port: 7000
|
||||
protocol: TCP
|
||||
targetPort: backend
|
||||
- name: backend
|
||||
port: 7000
|
||||
protocol: TCP
|
||||
targetPort: backend
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
"packages": ["packages/*", "plugins/*"],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.1.1-alpha.18"
|
||||
"version": "0.1.1-alpha.20"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
# Build output
|
||||
build
|
||||
i18n
|
||||
@@ -2,12 +2,36 @@ This website was created with [Docusaurus](https://docusaurus.io/).
|
||||
|
||||
# What's In This Document
|
||||
|
||||
- [Get Started in 5 Minutes](#get-started-in-5-minutes)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Directory Structure](#directory-structure)
|
||||
- [Editing Content](#editing-content)
|
||||
- [Adding Content](#adding-content)
|
||||
- [Full Documentation](#full-documentation)
|
||||
|
||||
# Getting Started
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ yarn install
|
||||
```
|
||||
|
||||
## Local Development
|
||||
|
||||
```
|
||||
$ yarn start
|
||||
```
|
||||
|
||||
This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
## Build
|
||||
|
||||
```
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
This command generates static content into the `build` directory, which is what will be deployed to GitHub pages from the master branch.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
Your project file structure should look something like this
|
||||
|
||||
@@ -13,7 +13,7 @@ Two days ago, we released the open source version of [Backstage](https://backsta
|
||||
|
||||
## What’s the big infrastructure problem?
|
||||
|
||||
As companies grow, their infrastructure systems get messier. Consider a team that wants to deploy something to the cloud. While Spotify has many awesome engineers, not every engineer is well-versed in our chosen cloud-provider tooling. Yet everyone is required to know and understand Terraform, GCP/AWS/Azure CLIs, Gitlab CI, Prometheus, Kubernetes, Docker, various monitoring and alerting tools, and much, much more. Once other resources come into play (databases, queueing, etc.), each engineer requires even more tools and domain-specific knowledge (or “disciplines”), from backend to machine learning, to mobile and data.
|
||||
As companies grow, their infrastructure systems get messier. Consider a team that wants to deploy something to the cloud. While Spotify has many awesome engineers, not every engineer is well-versed in our chosen cloud-provider tooling. Yet everyone is required to know and understand Terraform, GCP/AWS/Azure CLIs, GitLab CI, Prometheus, Kubernetes, Docker, various monitoring and alerting tools, and much, much more. Once other resources come into play (databases, queueing, etc.), each engineer requires even more tools and domain-specific knowledge (or “disciplines”), from backend to machine learning, to mobile and data.
|
||||
|
||||
## What’s the fix?
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ You get to take full advantage of a platform that we at Spotify have been using
|
||||
Just run the backstage-cli:
|
||||
|
||||
```bash
|
||||
npx @backstage/cli create-app
|
||||
npx @backstage/create-app
|
||||
```
|
||||
|
||||
Name your app, and we will create everything you need:
|
||||
@@ -50,7 +50,7 @@ yarn start
|
||||
|
||||
And you are good to go! 👍
|
||||
|
||||
Read the full documentation on how to [create an app](/docs/getting-started/create-an-app.md) on GitHub.
|
||||
Read the full documentation on how to [create an app](/docs/getting-started/create-an-app) on GitHub.
|
||||
|
||||
## What do I get? (Let's get technical...)
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ class Footer extends React.Component {
|
||||
<div>
|
||||
<h5>Community</h5>
|
||||
<a href="https://discord.gg/MUpMjP2">Support chatroom</a>
|
||||
<a href="https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md">
|
||||
Contributing
|
||||
</a>
|
||||
<a href="https://mailchi.mp/spotify/backstage-community">
|
||||
Subscribe to our newsletter
|
||||
</a>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: API Docs
|
||||
author: SDA SE
|
||||
authorUrl: https://sda.se/
|
||||
category: Discovery
|
||||
description: Components to discover and display API entities as an extension to the catalog plugin.
|
||||
documentation: https://github.com/spotify/backstage/blob/master/plugins/api-docs/README.md
|
||||
iconUrl: https://thecoders.io/wp-content/uploads/2019/11/tech-swagger.svg
|
||||
npmPackageName: '@backstage/plugin-api-docs'
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: CircleCI
|
||||
author: Spotify
|
||||
authorUrl: https://github.com/spotify
|
||||
category: CI
|
||||
description: Automate your development process with CI hosted in the cloud or on a private server.
|
||||
documentation: https://github.com/spotify/backstage/tree/master/plugins/circleci
|
||||
iconUrl: https://www.saaves.com/storage/brochure/logo-circleci-icon1583764538.png
|
||||
npmPackageName: '@backstage/plugin-circleci'
|
||||
tags:
|
||||
- ci
|
||||
- cd
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: GitHub Actions
|
||||
author: Spotify
|
||||
authorUrl: https://github.com/spotify
|
||||
category: CI
|
||||
description: GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub.
|
||||
documentation: https://github.com/spotify/backstage/tree/master/plugins/github-actions
|
||||
iconUrl: https://avatars2.githubusercontent.com/u/44036562?s=400&v=4
|
||||
npmPackageName: '@backstage/plugin-github-actions'
|
||||
tags:
|
||||
- ci
|
||||
- cd
|
||||
- github
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: GitHub Pull Requests
|
||||
author: roadie.io
|
||||
authorUrl: https://roadie.io/
|
||||
category: CI
|
||||
description: View GitHub pull requests for your service in Backstage.
|
||||
documentation: https://roadie.io/backstage/plugins/github-pull-requests
|
||||
iconUrl: https://roadie.io/static/7f13bb8d861d8dedc5112fb939d215f9/351f2/GitHub-Mark-Light-120px-plus.png
|
||||
npmPackageName: '@roadiehq/backstage-plugin-github-pull-requests'
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: GitOps Clusters
|
||||
author: Weaveworks
|
||||
authorUrl: https://www.weave.works/
|
||||
category: Kubernetes
|
||||
description: Create GitOps-managed Kubernetes clusters. Currently, it supports provisioning EKS clusters on GitHub via GitHub Actions.
|
||||
documentation: https://github.com/spotify/backstage/tree/master/plugins/gitops-profiles
|
||||
iconUrl: https://res-5.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_256,w_256,f_auto,q_auto:eco/v1462316670/i9d3delzvx1erzjhmcws.png
|
||||
npmPackageName: '@backstage/plugin-gitops-profiles'
|
||||
tags:
|
||||
- kubernetes
|
||||
- gitops
|
||||
- github
|
||||
- eks
|
||||