Merge branch 'backstage:master' into feat/techdocs-azurite-support

This commit is contained in:
Aswath S
2023-08-16 10:44:01 +05:30
committed by GitHub
866 changed files with 28990 additions and 6897 deletions
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core-app-api': patch
---
Fixed a bug that could cause `navigate` analytics events to be misattributed to the plugin mounted on the root route (e.g. the `home` plugin at `/`) when the route that was navigated to wasn't associated with a routable extension.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-graph': patch
---
Propagate entity spec to EntityNode so that spec info such as type can be used for graph node customization
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-playlist': patch
---
Displaying an alert popup each time the Playlist is created or deleted
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/create-app': patch
---
Bumped create-app version.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/backend-openapi-utils': patch
---
Add a new `createRouter` method for generating an `express` router that validates against your spec. Also fixes a bug with the query parameters type resolution.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-backend-module-gitlab': patch
---
Added option to skip forked repos in GitlabDiscoveryEntityProvider
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-linguist-backend': patch
---
Fixed bug in LinguistBackendClient.ts file where if the linguistJsOptions is specified and sent over to the linguist-js package it would get changed (another attribute would be added) causing future entities of the batch to fail with an error
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Reload the frontend when app config changes
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-home-react': patch
---
Make `title` optional when defining the `createCardExtension`
-8
View File
@@ -1,8 +0,0 @@
---
'@backstage/core-components': patch
'@backstage/plugin-splunk-on-call': patch
'@backstage/plugin-xcmetrics': patch
'@backstage/plugin-catalog': patch
---
Prefer simple `theme.spacing` without string interpolation
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-backend-module-unprocessed': minor
---
**BREAKING**: Fixing typo in exported module. You will have to rename the import to the correct spelling. `UnprocessedEntites` -> `UnprocessedEntities`
-254
View File
@@ -1,254 +0,0 @@
{
"mode": "pre",
"tag": "next",
"initialVersions": {
"example-app": "0.2.85",
"@backstage/app-defaults": "1.4.1",
"example-backend": "0.2.85",
"@backstage/backend-app-api": "0.4.5",
"@backstage/backend-common": "0.19.1",
"@backstage/backend-defaults": "0.1.12",
"@backstage/backend-dev-utils": "0.1.1",
"example-backend-next": "0.0.13",
"@backstage/backend-openapi-utils": "0.0.2",
"@backstage/backend-plugin-api": "0.5.4",
"@backstage/backend-tasks": "0.5.4",
"@backstage/backend-test-utils": "0.1.39",
"@backstage/catalog-client": "1.4.3",
"@backstage/catalog-model": "1.4.1",
"@backstage/cli": "0.22.9",
"@backstage/cli-common": "0.1.12",
"@backstage/cli-node": "0.1.2",
"@backstage/codemods": "0.1.45",
"@backstage/config": "1.0.8",
"@backstage/config-loader": "1.3.2",
"@backstage/core-app-api": "1.9.0",
"@backstage/core-components": "0.13.3",
"@backstage/core-plugin-api": "1.5.3",
"@backstage/create-app": "0.5.3",
"@backstage/dev-utils": "1.0.17",
"e2e-test": "0.2.5",
"@backstage/errors": "1.2.1",
"@backstage/eslint-plugin": "0.1.3",
"@backstage/integration": "1.5.1",
"@backstage/integration-aws-node": "0.1.5",
"@backstage/integration-react": "1.1.15",
"@backstage/release-manifests": "0.0.9",
"@backstage/repo-tools": "0.3.2",
"@techdocs/cli": "1.4.4",
"techdocs-cli-embedded-app": "0.2.84",
"@backstage/test-utils": "1.4.1",
"@backstage/theme": "0.4.1",
"@backstage/types": "1.1.0",
"@backstage/version-bridge": "1.0.4",
"@backstage/plugin-adr": "0.6.3",
"@backstage/plugin-adr-backend": "0.3.5",
"@backstage/plugin-adr-common": "0.2.11",
"@backstage/plugin-airbrake": "0.3.20",
"@backstage/plugin-airbrake-backend": "0.2.20",
"@backstage/plugin-allure": "0.1.36",
"@backstage/plugin-analytics-module-ga": "0.1.31",
"@backstage/plugin-analytics-module-ga4": "0.1.2",
"@backstage/plugin-apache-airflow": "0.2.13",
"@backstage/plugin-api-docs": "0.9.6",
"@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.2",
"@backstage/plugin-apollo-explorer": "0.1.13",
"@backstage/plugin-app-backend": "0.3.47",
"@backstage/plugin-auth-backend": "0.18.5",
"@backstage/plugin-auth-node": "0.2.16",
"@backstage/plugin-azure-devops": "0.3.2",
"@backstage/plugin-azure-devops-backend": "0.3.26",
"@backstage/plugin-azure-devops-common": "0.3.0",
"@backstage/plugin-azure-sites": "0.1.9",
"@backstage/plugin-azure-sites-backend": "0.1.9",
"@backstage/plugin-azure-sites-common": "0.1.0",
"@backstage/plugin-badges": "0.2.44",
"@backstage/plugin-badges-backend": "0.2.2",
"@backstage/plugin-bazaar": "0.2.11",
"@backstage/plugin-bazaar-backend": "0.2.10",
"@backstage/plugin-bitbucket-cloud-common": "0.2.8",
"@backstage/plugin-bitrise": "0.1.47",
"@backstage/plugin-catalog": "1.12.0",
"@backstage/plugin-catalog-backend": "1.11.0",
"@backstage/plugin-catalog-backend-module-aws": "0.2.2",
"@backstage/plugin-catalog-backend-module-azure": "0.1.18",
"@backstage/plugin-catalog-backend-module-bitbucket": "0.2.14",
"@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.14",
"@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.12",
"@backstage/plugin-catalog-backend-module-gerrit": "0.1.15",
"@backstage/plugin-catalog-backend-module-github": "0.3.2",
"@backstage/plugin-catalog-backend-module-gitlab": "0.2.3",
"@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.4.0",
"@backstage/plugin-catalog-backend-module-ldap": "0.5.14",
"@backstage/plugin-catalog-backend-module-msgraph": "0.5.6",
"@backstage/plugin-catalog-backend-module-openapi": "0.1.13",
"@backstage/plugin-catalog-backend-module-puppetdb": "0.1.4",
"@backstage/plugin-catalog-backend-module-unprocessed": "0.1.1",
"@backstage/plugin-catalog-common": "1.0.15",
"@internal/plugin-catalog-customized": "0.0.12",
"@backstage/plugin-catalog-graph": "0.2.32",
"@backstage/plugin-catalog-graphql": "0.3.22",
"@backstage/plugin-catalog-import": "0.9.10",
"@backstage/plugin-catalog-node": "1.4.0",
"@backstage/plugin-catalog-react": "1.8.0",
"@backstage/plugin-catalog-unprocessed-entities": "0.1.1",
"@backstage/plugin-cicd-statistics": "0.1.22",
"@backstage/plugin-cicd-statistics-module-gitlab": "0.1.16",
"@backstage/plugin-circleci": "0.3.20",
"@backstage/plugin-cloudbuild": "0.3.20",
"@backstage/plugin-code-climate": "0.1.20",
"@backstage/plugin-code-coverage": "0.2.13",
"@backstage/plugin-code-coverage-backend": "0.2.13",
"@backstage/plugin-codescene": "0.1.15",
"@backstage/plugin-config-schema": "0.1.43",
"@backstage/plugin-cost-insights": "0.12.9",
"@backstage/plugin-cost-insights-common": "0.1.1",
"@backstage/plugin-devtools": "0.1.2",
"@backstage/plugin-devtools-backend": "0.1.2",
"@backstage/plugin-devtools-common": "0.1.2",
"@backstage/plugin-dynatrace": "7.0.0",
"@backstage/plugin-entity-feedback": "0.2.3",
"@backstage/plugin-entity-feedback-backend": "0.1.5",
"@backstage/plugin-entity-feedback-common": "0.1.1",
"@backstage/plugin-entity-validation": "0.1.5",
"@backstage/plugin-events-backend": "0.2.8",
"@backstage/plugin-events-backend-module-aws-sqs": "0.2.2",
"@backstage/plugin-events-backend-module-azure": "0.1.9",
"@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.9",
"@backstage/plugin-events-backend-module-gerrit": "0.1.9",
"@backstage/plugin-events-backend-module-github": "0.1.9",
"@backstage/plugin-events-backend-module-gitlab": "0.1.9",
"@backstage/plugin-events-backend-test-utils": "0.1.9",
"@backstage/plugin-events-node": "0.2.8",
"@internal/plugin-todo-list": "1.0.15",
"@internal/plugin-todo-list-backend": "1.0.15",
"@internal/plugin-todo-list-common": "1.0.12",
"@backstage/plugin-explore": "0.4.6",
"@backstage/plugin-explore-backend": "0.0.9",
"@backstage/plugin-explore-common": "0.0.1",
"@backstage/plugin-explore-react": "0.0.30",
"@backstage/plugin-firehydrant": "0.2.4",
"@backstage/plugin-fossa": "0.2.52",
"@backstage/plugin-gcalendar": "0.3.16",
"@backstage/plugin-gcp-projects": "0.3.39",
"@backstage/plugin-git-release-manager": "0.3.33",
"@backstage/plugin-github-actions": "0.6.1",
"@backstage/plugin-github-deployments": "0.1.51",
"@backstage/plugin-github-issues": "0.2.9",
"@backstage/plugin-github-pull-requests-board": "0.1.14",
"@backstage/plugin-gitops-profiles": "0.3.38",
"@backstage/plugin-gocd": "0.1.26",
"@backstage/plugin-graphiql": "0.2.52",
"@backstage/plugin-graphql-backend": "0.1.37",
"@backstage/plugin-graphql-voyager": "0.1.5",
"@backstage/plugin-home": "0.5.4",
"@backstage/plugin-home-react": "0.1.1",
"@backstage/plugin-ilert": "0.2.9",
"@backstage/plugin-jenkins": "0.8.2",
"@backstage/plugin-jenkins-backend": "0.2.2",
"@backstage/plugin-jenkins-common": "0.1.17",
"@backstage/plugin-kafka": "0.3.20",
"@backstage/plugin-kafka-backend": "0.2.40",
"@backstage/plugin-kubernetes": "0.9.3",
"@backstage/plugin-kubernetes-backend": "0.11.2",
"@backstage/plugin-kubernetes-common": "0.6.5",
"@backstage/plugin-lighthouse": "0.4.5",
"@backstage/plugin-lighthouse-backend": "0.2.3",
"@backstage/plugin-lighthouse-common": "0.1.2",
"@backstage/plugin-linguist": "0.1.5",
"@backstage/plugin-linguist-backend": "0.3.1",
"@backstage/plugin-linguist-common": "0.1.0",
"@backstage/plugin-microsoft-calendar": "0.1.5",
"@backstage/plugin-newrelic": "0.3.38",
"@backstage/plugin-newrelic-dashboard": "0.2.13",
"@backstage/plugin-nomad": "0.1.1",
"@backstage/plugin-nomad-backend": "0.1.1",
"@backstage/plugin-octopus-deploy": "0.2.2",
"@backstage/plugin-org": "0.6.10",
"@backstage/plugin-org-react": "0.1.9",
"@backstage/plugin-pagerduty": "0.6.1",
"@backstage/plugin-periskop": "0.1.18",
"@backstage/plugin-periskop-backend": "0.1.18",
"@backstage/plugin-permission-backend": "0.5.22",
"@backstage/plugin-permission-common": "0.7.7",
"@backstage/plugin-permission-node": "0.7.10",
"@backstage/plugin-permission-react": "0.4.14",
"@backstage/plugin-playlist": "0.1.12",
"@backstage/plugin-playlist-backend": "0.3.3",
"@backstage/plugin-playlist-common": "0.1.8",
"@backstage/plugin-proxy-backend": "0.2.41",
"@backstage/plugin-puppetdb": "0.1.3",
"@backstage/plugin-rollbar": "0.4.20",
"@backstage/plugin-rollbar-backend": "0.1.44",
"@backstage/plugin-scaffolder": "1.14.1",
"@backstage/plugin-scaffolder-backend": "1.15.1",
"@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.2.0",
"@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.23",
"@backstage/plugin-scaffolder-backend-module-gitlab": "0.2.2",
"@backstage/plugin-scaffolder-backend-module-rails": "0.4.16",
"@backstage/plugin-scaffolder-backend-module-sentry": "0.1.7",
"@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.20",
"@backstage/plugin-scaffolder-common": "1.3.2",
"@backstage/plugin-scaffolder-node": "0.1.5",
"@backstage/plugin-scaffolder-react": "1.5.1",
"@backstage/plugin-search": "1.3.3",
"@backstage/plugin-search-backend": "1.3.3",
"@backstage/plugin-search-backend-module-catalog": "0.1.3",
"@backstage/plugin-search-backend-module-elasticsearch": "1.3.2",
"@backstage/plugin-search-backend-module-explore": "0.1.3",
"@backstage/plugin-search-backend-module-pg": "0.5.8",
"@backstage/plugin-search-backend-module-techdocs": "0.1.3",
"@backstage/plugin-search-backend-node": "1.2.3",
"@backstage/plugin-search-common": "1.2.5",
"@backstage/plugin-search-react": "1.6.3",
"@backstage/plugin-sentry": "0.5.5",
"@backstage/plugin-shortcuts": "0.3.12",
"@backstage/plugin-sonarqube": "0.7.1",
"@backstage/plugin-sonarqube-backend": "0.2.1",
"@backstage/plugin-sonarqube-react": "0.1.7",
"@backstage/plugin-splunk-on-call": "0.4.9",
"@backstage/plugin-stack-overflow": "0.1.18",
"@backstage/plugin-stack-overflow-backend": "0.2.3",
"@backstage/plugin-stackstorm": "0.1.4",
"@backstage/plugin-tech-insights": "0.3.12",
"@backstage/plugin-tech-insights-backend": "0.5.13",
"@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.31",
"@backstage/plugin-tech-insights-common": "0.2.11",
"@backstage/plugin-tech-insights-node": "0.4.5",
"@backstage/plugin-tech-radar": "0.6.6",
"@backstage/plugin-techdocs": "1.6.5",
"@backstage/plugin-techdocs-addons-test-utils": "1.0.16",
"@backstage/plugin-techdocs-backend": "1.6.4",
"@backstage/plugin-techdocs-module-addons-contrib": "1.0.15",
"@backstage/plugin-techdocs-node": "1.7.3",
"@backstage/plugin-techdocs-react": "1.1.8",
"@backstage/plugin-todo": "0.2.22",
"@backstage/plugin-todo-backend": "0.1.44",
"@backstage/plugin-user-settings": "0.7.5",
"@backstage/plugin-user-settings-backend": "0.1.11",
"@backstage/plugin-vault": "0.1.14",
"@backstage/plugin-vault-backend": "0.3.3",
"@backstage/plugin-xcmetrics": "0.2.40",
"@backstage/plugin-analytics-module-newrelic-browser": "0.0.0"
},
"changesets": [
"analytics-millenial-whoop",
"chatty-foxes-buy",
"create-app-1690284535",
"gorgeous-months-doubt",
"large-experts-poke",
"loud-garlics-press",
"mean-squids-relax",
"neat-lamps-press",
"pink-squids-nail",
"quiet-starfishes-kick",
"rare-pens-exist",
"rude-feet-sparkle",
"search-donuts-wash",
"selfish-coats-shout",
"serious-bats-repair",
"smart-pandas-applaud",
"stupid-berries-run",
"ten-otters-appear"
]
}
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-home': patch
---
Now, user can provide a language (optional) as input to receive a greeting in that specific language. Example: `<WelcomeTitle language={['English', 'Spanish']} />`
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Enable to print the config schema not merged with the `--no-merge` flag
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-analytics-module-newrelic-browser': patch
---
Introduced the New Relic Browser analytics module. Check out the plugins [README.md](https://github.com/backstage/backstage/tree/master/plugins/analytics-module-newrelic-browser) for more details!
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-search-backend-node': patch
---
Fix Lunr search engine highlight by ignoring invalid metadata positions.
-55
View File
@@ -1,55 +0,0 @@
---
'@backstage/config-loader': minor
---
Adds a new `deepVisibility` schema keyword that sets child visibility recursively to the defined value, respecting preexisting values or child `deepVisibility`.
Example usage:
```ts
export interface Config {
/**
* Enforces a default of `secret` instead of `backend` for this object.
* @deepVisibility secret
*/
mySecretProperty: {
type: 'object';
properties: {
secretValue: {
type: 'string';
};
verySecretProperty: {
type: 'string';
};
};
};
}
```
Example of a schema that would not be allowed:
```ts
export interface Config {
/**
* Set the top level property to secret, enforcing a default of `secret` instead of `backend` for this object.
* @deepVisibility secret
*/
mySecretProperty: {
type: 'object';
properties: {
frontendUrl: {
/**
* We can NOT override the visibility to reveal a property to the front end.
* @visibility frontend
*/
type: 'string';
};
verySecretProperty: {
type: 'string';
};
};
};
}
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/repo-tools': patch
---
Update `schema openapi generate` command to now create a default router that can be imported and used directly.
-7
View File
@@ -1,7 +0,0 @@
---
'@backstage/plugin-todo-backend': minor
'@backstage/plugin-catalog-backend': minor
'@backstage/plugin-search-backend': minor
---
Now performs request validation based on OpenAPI schema through `@backstage/backend-openapi-utils`. Error responses for invalid input, like `"a"` instead of a number, may have changed.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-home': patch
---
Make sure the widget name is never empty in the `AddWidgetDialog`. If the title was set to "", the entry would contain an empty string. Use the name as a fallback
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-scaffolder-react': patch
---
Fixed bug in Workflow component by passing a prop `templateName` down to Stepper component.
+9
View File
@@ -0,0 +1,9 @@
# CLOMonitor metadata file
# This file must be located at the root of the repository
# https://clomonitor.io/projects/cncf/backstage
# Checks exemptions
exemptions:
- check: trademark_disclaimer # Check identifier (see https://github.com/cncf/clomonitor/blob/main/docs/checks.md#exemptions)
# Justification of this exemption (mandatory, it will be displayed on the UI)
reason: 'The Linux Foundation trademark disclaimer and link are contained within the project web site at https://backstage.io in the copyright footer. However, because the site is delivered dynamically via React through JavaScript, the check cannot currently identify it.'
+2
View File
@@ -24,6 +24,8 @@ documentation:
- docs/**/*
microsite:
- microsite/**/*
storybook:
- storybook/**/*
auth:
- plugins/auth-backend/**/*
- packages/core-app-api/src/apis/implementations/auth/**/*
@@ -56,72 +56,73 @@ catalog:
- allow: [Template]
proxy:
'/circleci/api':
target: https://circleci.com/api/v1.1
headers:
Circle-Token: ${CIRCLECI_AUTH_TOKEN}
endpoints:
'/circleci/api':
target: https://circleci.com/api/v1.1
headers:
Circle-Token: ${CIRCLECI_AUTH_TOKEN}
'/jenkins/api':
target: http://localhost:8080
headers:
Authorization: ${JENKINS_BASIC_AUTH_HEADER}
'/jenkins/api':
target: http://localhost:8080
headers:
Authorization: ${JENKINS_BASIC_AUTH_HEADER}
'/travisci/api':
target: https://api.travis-ci.com
changeOrigin: true
headers:
Authorization: ${TRAVISCI_AUTH_TOKEN}
travis-api-version: '3'
'/travisci/api':
target: https://api.travis-ci.com
changeOrigin: true
headers:
Authorization: ${TRAVISCI_AUTH_TOKEN}
travis-api-version: '3'
'/newrelic/apm/api':
target: https://api.newrelic.com/v2
headers:
X-Api-Key: ${NEW_RELIC_REST_API_KEY}
'/newrelic/apm/api':
target: https://api.newrelic.com/v2
headers:
X-Api-Key: ${NEW_RELIC_REST_API_KEY}
'/newrelic/api':
target: https://api.newrelic.com
headers:
X-Api-Key: ${NEW_RELIC_USER_KEY}
'/newrelic/api':
target: https://api.newrelic.com
headers:
X-Api-Key: ${NEW_RELIC_USER_KEY}
'/pagerduty':
target: https://api.pagerduty.com
headers:
Authorization: Token token=${PAGERDUTY_TOKEN}
'/pagerduty':
target: https://api.pagerduty.com
headers:
Authorization: Token token=${PAGERDUTY_TOKEN}
'/buildkite/api':
target: https://api.buildkite.com/v2/
headers:
Authorization: ${BUILDKITE_TOKEN}
'/buildkite/api':
target: https://api.buildkite.com/v2/
headers:
Authorization: ${BUILDKITE_TOKEN}
'/sentry/api':
target: https://sentry.io/api/
allowedMethods: ['GET']
headers:
Authorization: ${SENTRY_TOKEN}
'/sentry/api':
target: https://sentry.io/api/
allowedMethods: ['GET']
headers:
Authorization: ${SENTRY_TOKEN}
'/ilert':
target: https://api.ilert.com
allowedMethods: ['GET', 'POST', 'PUT']
allowedHeaders: ['Authorization']
headers:
Authorization: ${ILERT_AUTH_HEADER}
'/ilert':
target: https://api.ilert.com
allowedMethods: ['GET', 'POST', 'PUT']
allowedHeaders: ['Authorization']
headers:
Authorization: ${ILERT_AUTH_HEADER}
'/airflow':
target: https://your.airflow.instance.com/api/v1
headers:
Authorization: ${AIRFLOW_BASIC_AUTH_HEADER}
'/airflow':
target: https://your.airflow.instance.com/api/v1
headers:
Authorization: ${AIRFLOW_BASIC_AUTH_HEADER}
'/gocd':
target: https://your.gocd.instance.com/go/api
allowedMethods: ['GET']
allowedHeaders: ['Authorization']
headers:
Authorization: Basic ${GOCD_AUTH_CREDENTIALS}
'/gocd':
target: https://your.gocd.instance.com/go/api
allowedMethods: ['GET']
allowedHeaders: ['Authorization']
headers:
Authorization: Basic ${GOCD_AUTH_CREDENTIALS}
'/dynatrace':
target: https://your.dynatrace.instance.com/api/v2
headers:
Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}'
'/dynatrace':
target: https://your.dynatrace.instance.com/api/v2
headers:
Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}'
techdocs:
builder: 'local' # Alternatives - 'external'
+6
View File
@@ -123,8 +123,11 @@ FireHydrant
Firekube
Firestore
Fiverr
Flightcontrol
flightcontrol
Francesco
Frontside
Gaurav
gerrit
Gerrit
gitbeaker
@@ -164,6 +167,7 @@ inlined
inlinehilite
integrator's
interop
iterable
JaCoCo
JavaScript
jenkins
@@ -257,6 +261,7 @@ padding
paddings
pagerduty
pageview
Pandey
parallelization
parseable
Patrik
@@ -405,6 +410,7 @@ unbreak
Unconference
unicode
unmanaged
unmount
unregister
unregistering
unregistration
+66
View File
@@ -0,0 +1,66 @@
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
# branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '41 8 * * 6'
push:
branches: ['master']
# Declare default permissions as read only.
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
steps:
- name: 'Checkout code'
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
persist-credentials: false
- name: 'Run analysis'
uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: 'Upload artifact'
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4
with:
sarif_file: results.sarif
@@ -6,7 +6,7 @@ on:
pull_request:
paths-ignore:
- 'yarn.lock'
- '.github/workflows/verify_kubernetes.yml'
- '.github/workflows/verify_e2e-kubernetes.yml'
- 'packages/backend-common/src/**'
jobs:
+2 -2
View File
@@ -4,7 +4,7 @@ on:
pull_request:
paths:
- 'yarn.lock'
- '.github/workflows/verify_kubernetes.yml'
- '.github/workflows/verify_e2e-kubernetes.yml'
- 'packages/backend-common/src/**'
jobs:
@@ -35,7 +35,7 @@ jobs:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
- name: bootstrap kind
uses: helm/kind-action@v1.7.0
uses: helm/kind-action@v1.8.0
- name: kubernetes test
working-directory: packages/backend-common
+4 -1
View File
@@ -43,7 +43,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/
| [MavTek](https://www.mavtek.com/) | [@fgascon](https://github.com/fgascon) | Developer portal focused on standardizing practices, centralizing documentation and streamlining developer practices. |
| [QuintoAndar](https://www.quintoandar.com.br/) | [@quintoandar](https://github.com/quintoandar) | Developer portal, services catalog and centralization of service metrics. |
| [empathy.co](https://empathy.co/) | [@guillermotti](https://github.com/guillermotti) | Developer portal for tech docs, service catalog, plugin discovery and much more. |
| [creditas.com](https://creditas.com/) | [@aureliosaraiva](https://github.com/aureliosaraiva) [@Creditas](https://github.com/creditas) | Centralization of all services, standards, documentation, etc. We started the deployment process. |
| [creditas.com](https://creditas.com/) | [@rebender](https://github.com/rebender) [@Creditas](https://github.com/creditas) | Centralization of all services, standards, documentation, etc. We started the deployment process. |
| [Prisjakt](https://www.prisjakt.nu) / [PriceSpy](https://pricespy.co.uk) | [@kennylindahl](https://github.com/kennylindahl) | Internal developer portal - Documentation, scaffolding, software catalog, TechRadar, Gitlab org data integration |
| [Powerspike](https://powerspike.tv/) | [@trelore](https://github.com/trelore) | Developer portal for documentation of core libraries and repositories. |
| [2U](https://2u.com) | [@danielleEriksen](https://github.com/danielleEriksen), [@sbhatia](https://github.com/sbhatia) | Development team home-base, promoting service discoverability, resource dependencies, and tech radar |
@@ -254,3 +254,6 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/
| [Celonis](https://celonis.com) | [@georgeyord](https://github.com/georgeyord), [@LauraMoraB](https://github.com/LauraMoraB), [@mariosant](https://github.com/mariosant), [@Rbillon59](https://github.com/Rbillon59) | Internal developer and product portal implementation. |
| [Rabobank](https://www.rabobank.com) | [Willem Dekker](https://github.com/wdekker), [Sridhar Gnanasekaran](https://github.com/srid99), [Ruben Ernst](https://github.com/Ruben-E) | At Rabobank, our mission is to make life better for engineers. After exploring various options in the market, we've discovered that Backstage provides the perfect foundation for creating a platform that meets our engineers' needs and helps us achieve our goals. We want to make our engineers happy by offering standardized services, freeing them up to focus on delivering value. Our vision is to create a one-stop platform where engineers can find everything related to software and services. In practice, we're excited about using all the cool features in Backstage, and we're even planning to build our own plugins. |
| [JB Hi-Fi](https://www.jbhifi.com.au) | [@bahman](https://github.com/bahman-jb/) | We use Backstage as a central place for all of our components/apis across multiple teams. It helps us to quickly identify the ownership of a component/api, find the related links and have a quick access to CI/CD pipelines. |
| [Zenklub](https://www.zenklub.com.br) | [@zenklub](https://github.com/zenklub), [@gioufop](https://github.com/gioufop) | Developer portal, services catalog and centralization of metrics from Grafana Stack and AWS. Furthermore, centralization of documentation and infra details like Tools, Network services and so on. |
| [Platzi](https://platzi.com/) | [@juancarestre](https://github.com/juancarestre/), [Engineering at Platzi](https://github.com/PlatziDev/) | Backstage allow our developers to get easily engaged with all the internal components, technical documentations and software templates. All new developers reduce its onboarding time via Backstage, and after a couple of integrations it allowed us to create new components with in a couple of clicks. |
| [idealo](https://idealo.de) | [Wanis Fahmy](https://github.com/wanisfahmyDE), [Sajjad Pervaiz](https://github.com/sjvaiz), [Tim Heurich](https://github.com/theurichde) | Backstage is our Internal developer portal. Along with other plugins, We use the software catalog, TechDocs and explore plugins to manage, discover and document our software components and platform products. |
+1
View File
@@ -42,6 +42,7 @@ Scope: Discoverability within Backstage, including the home page, information ar
| Emma Indal | Spotify | BUX | [emmaindal](http://github.com/emmaindal) | emmaindal#7503 |
| Raghunandan Balachandran | Spotify | BUX | [soapraj](http://github.com/soapraj) | raghunandanb#1114 |
| Renan Mendes Carvalho | Spotify | BUX | [aitherios](http://github.com/aitherios) | aitherios#0593 |
| Bailey Brooks | Spotify | BUX | [bailey](http://github.com/bailey) | \_bailey4 |
### Helm Charts
+2 -2
View File
@@ -10,8 +10,8 @@
[![Codecov](https://img.shields.io/codecov/c/github/backstage/backstage)](https://codecov.io/gh/backstage/backstage)
[![](https://img.shields.io/github/v/release/backstage/backstage)](https://github.com/backstage/backstage/releases)
[![Uffizzi](https://img.shields.io/endpoint?url=https%3A%2F%2Fapp.uffizzi.com%2Fapi%2Fv1%2Fpublic%2Fshields%2Fgithub.com%2Fbackstage%2Fbackstage)](https://app.uffizzi.com/ephemeral-environments/backstage/backstage)
> 🏖️ The week beginning the 26th of June, some of the maintainers will be taking a well earned Summer Holiday break. We will be slower to respond to issues and PRs during this time. Releases will continue to be shipped weekly. Normal service will resume on the 24th of July. 🏝️
[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7678/badge)](https://bestpractices.coreinfrastructure.org/projects/7678)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/backstage/backstage/badge)](https://securityscorecards.dev/viewer/?uri=github.com/backstage/backstage)
## What is Backstage?
+70 -65
View File
@@ -20,6 +20,8 @@ app:
- url: https://discord.gg/backstage-687207715902193673
title: '#backstage'
packageName: example-app
backend:
# Used for enabling authentication, secret is shared by all backend plugins
# See https://backstage.io/docs/auth/service-to-service-auth for
@@ -49,80 +51,83 @@ backend:
# See README.md in the proxy-backend plugin for information on the configuration format
proxy:
'/circleci/api':
target: https://circleci.com/api/v1.1
headers:
Circle-Token: ${CIRCLECI_AUTH_TOKEN}
endpoints:
'/circleci/api':
target: https://circleci.com/api/v1.1
headers:
Circle-Token: ${CIRCLECI_AUTH_TOKEN}
'/jenkins/api':
target: http://localhost:8080
headers:
Authorization: ${JENKINS_BASIC_AUTH_HEADER}
'/jenkins/api':
target: http://localhost:8080
headers:
Authorization: ${JENKINS_BASIC_AUTH_HEADER}
'/travisci/api':
target: https://api.travis-ci.com
changeOrigin: true
headers:
Authorization: ${TRAVISCI_AUTH_TOKEN}
travis-api-version: '3'
'/travisci/api':
target: https://api.travis-ci.com
changeOrigin: true
headers:
Authorization: ${TRAVISCI_AUTH_TOKEN}
travis-api-version: '3'
'/newrelic/apm/api':
target: https://api.newrelic.com/v2
headers:
X-Api-Key: ${NEW_RELIC_REST_API_KEY}
'/newrelic/apm/api':
target: https://api.newrelic.com/v2
headers:
X-Api-Key: ${NEW_RELIC_REST_API_KEY}
allowedHeaders:
- link
'/newrelic/api':
target: https://api.newrelic.com
headers:
X-Api-Key: ${NEW_RELIC_USER_KEY}
'/newrelic/api':
target: https://api.newrelic.com
headers:
X-Api-Key: ${NEW_RELIC_USER_KEY}
'/pagerduty':
target: https://api.pagerduty.com
headers:
Authorization: Token token=${PAGERDUTY_TOKEN}
'/pagerduty':
target: https://api.pagerduty.com
headers:
Authorization: Token token=${PAGERDUTY_TOKEN}
'/buildkite/api':
target: https://api.buildkite.com/v2/
headers:
Authorization: ${BUILDKITE_TOKEN}
'/buildkite/api':
target: https://api.buildkite.com/v2/
headers:
Authorization: ${BUILDKITE_TOKEN}
'/sentry/api':
target: https://sentry.io/api/
allowedMethods: ['GET']
headers:
Authorization: ${SENTRY_TOKEN}
'/sentry/api':
target: https://sentry.io/api/
allowedMethods: ['GET']
headers:
Authorization: ${SENTRY_TOKEN}
'/ilert':
target: https://api.ilert.com
allowedMethods: ['GET', 'POST', 'PUT']
allowedHeaders: ['Authorization']
headers:
Authorization: ${ILERT_AUTH_HEADER}
'/ilert':
target: https://api.ilert.com
allowedMethods: ['GET', 'POST', 'PUT']
allowedHeaders: ['Authorization']
headers:
Authorization: ${ILERT_AUTH_HEADER}
'/airflow':
target: https://your.airflow.instance.com/api/v1
headers:
Authorization: ${AIRFLOW_BASIC_AUTH_HEADER}
'/airflow':
target: https://your.airflow.instance.com/api/v1
headers:
Authorization: ${AIRFLOW_BASIC_AUTH_HEADER}
'/gocd':
target: https://your.gocd.instance.com/go/api
allowedMethods: ['GET']
allowedHeaders: ['Authorization']
headers:
Authorization: Basic ${GOCD_AUTH_CREDENTIALS}
'/gocd':
target: https://your.gocd.instance.com/go/api
allowedMethods: ['GET']
allowedHeaders: ['Authorization']
headers:
Authorization: Basic ${GOCD_AUTH_CREDENTIALS}
'/dynatrace':
target: https://your.dynatrace.instance.com/api/v2
headers:
Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}'
'/dynatrace':
target: https://your.dynatrace.instance.com/api/v2
headers:
Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}'
'/stackstorm':
target: https://your.stackstorm.instance.com/api
headers:
St2-Api-Key: ${ST2_API_KEY}
'/stackstorm':
target: https://your.stackstorm.instance.com/api
headers:
St2-Api-Key: ${ST2_API_KEY}
'/puppetdb':
target: https://your.puppetdb.instance.com
'/puppetdb':
target: https://your.puppetdb.instance.com
organization:
name: My Company
@@ -211,7 +216,7 @@ integrations:
# clientEmail: 'example@example.com'
# privateKey: ${GCS_PRIVATE_KEY}
awsS3:
- host: amazonaws.com
- endpoint: ${AWS_S3_ENDPOINT}
accessKeyId: ${AWS_ACCESS_KEY_ID}
secretAccessKey: ${AWS_SECRET_ACCESS_KEY}
@@ -352,8 +357,6 @@ auth:
metadataUrl: ${AUTH_OIDC_METADATA_URL}
clientId: ${AUTH_OIDC_CLIENT_ID}
clientSecret: ${AUTH_OIDC_CLIENT_SECRET}
authorizationUrl: ${AUTH_OIDC_AUTH_URL}
tokenUrl: ${AUTH_OIDC_TOKEN_URL}
tokenEndpointAuthMethod: ${AUTH_OIDC_TOKEN_ENDPOINT_AUTH_METHOD} # default='client_secret_basic'
tokenSignedResponseAlg: ${AUTH_OIDC_TOKEN_SIGNED_RESPONSE_ALG} # default='RS256'
scope: ${AUTH_OIDC_SCOPE} # default='openid profile email'
@@ -434,8 +437,10 @@ costInsights:
kind: 'PINTS_OF_ICE_CREAM'
unit: 'ice cream pint'
rate: 5.5
pagerduty:
pagerDuty:
eventsBaseUrl: 'https://events.pagerduty.com/v2'
jenkins:
instances:
- name: default
+23 -16
View File
@@ -58,6 +58,7 @@ When using ALB authentication Backstage will only be loaded once the user has su
import React from 'react';
import { UserIdentity } from '@backstage/core-components';
import { SignInPageProps } from '@backstage/core-app-api';
import { useApi, configApiRef } from '@backstage/core-plugin-api';
const SampleSignInComponent: any = (props: SignInPageProps) => {
const [error, setError] = React.useState<string | undefined>();
@@ -90,8 +91,8 @@ const SampleSignInComponent: any = (props: SignInPageProps) => {
},
}),
);
} catch (err) {
setError(err.message);
} catch (err: any) {
setError(err.message as string);
}
}
}, [config]);
@@ -135,12 +136,14 @@ export default async function createPlugin({
database,
config,
discovery,
tokenManager,
}: PluginEnvironment): Promise<Router> {
return await createRouter({
logger,
config,
database,
discovery,
tokenManager,
providerFactories: {
awsalb: providers.awsAlb.create({
authHandler: async ({ fullProfile }) => {
@@ -168,25 +171,29 @@ export default async function createPlugin({
};
},
signIn: {
resolver: async ({ profile: { email } }, ctx) => {
const [id] = email?.split('@') ?? '';
// Fetch from an external system that returns entity claims like:
// ['user:default/breanna.davison', ...]
const userEntityRef = stringifyEntityRef({
resolver: async ({ profile }, ctx) => {
if (!profile.email) {
throw new Error('Profile contained no email');
}
const [id] = profile.email.split('@');
if (!id) {
throw new Error('Invalid email format');
}
const userRef = stringifyEntityRef({
kind: 'User',
namespace: DEFAULT_NAMESPACE,
name: id,
namespace: DEFAULT_NAMESPACE,
});
// Resolve group membership from the Backstage catalog
const fullEnt =
await ctx.catalogIdentityClient.resolveCatalogMembership({
entityRefs: [id].concat([userEntityRef]),
logger: ctx.logger,
});
const token = await ctx.tokenIssuer.issueToken({
claims: { sub: userEntityRef, ent: fullEnt },
const { token } = await ctx.issueToken({
claims: {
sub: userRef,
ent: [userRef],
},
});
return { id, token };
},
},
+6 -2
View File
@@ -41,14 +41,18 @@ auth:
secret: ${AUTH_SESSION_SECRET}
```
The Auth0 provider is a structure with three configuration keys:
The Auth0 provider is a structure with these configuration keys:
- `clientId`: The Application client ID, found on the Auth0 Application page
- `clientSecret`: The Application client secret, found on the Auth0 Application
page
- `domain`: The Application domain, found on the Auth0 Application page
Because Auth0 requires a session you need to give the session a secret key.
It additionally relies on the following configuration to function:
- `session.secret`: The session secret is a key used for signing and/or encrypting cookies set by the application to maintain session state. In this case, 'your session secret' should be replaced with a long, complex, and unique string that only your application knows.
Auth0 requires a session, so you need to give the session a secret key.
## Optional Configuration
+5 -1
View File
@@ -20,8 +20,10 @@ The provider configuration can be added to your `app-config.yaml` under the root
```yaml title="app-config.yaml"
auth:
environment: development
providers:
oauth2Proxy: {}
oauth2Proxy:
development: {}
```
Right now no configuration options are supported, but the empty object is needed
@@ -58,6 +60,8 @@ providerFactories: {
},
```
[An example on how to sign a user in without a matching user](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/auth.ts)
## Adding the provider to the Backstage frontend
It is recommended to use the `ProxiedSignInPage` for this provider, which is
+1 -1
View File
@@ -59,7 +59,7 @@ Just like plugins, modules also have access to services and can depend on their
A detailed explanation of the package architecture can be found in the
[Backstage Architecture
Overview](../../overview/architecture-overview.md#package-architecture). The
Overview](../../overview/architecture-overview/#package-architecture). The
most important packages to consider for this system are the following:
- `plugin-<pluginId>-backend` houses the implementation of the backend plugins
@@ -37,4 +37,4 @@ At a high level, when you call `createBackend`, it will create a new backend ins
Underneath the hood, `createBackend` calls `createSpecializedBackend` from `@backstage/backend-app-api` which is responsible for actually creating the backend instance, but with no services or no features. You can think of `createBackend` more of a 'batteries included' approach, and `createSpecializedBackend` a little more low level.
As mentioned previously there's also the ability to create multiple of these backends in your project so that you can split apart your backend and deploy different backends that can scale independently of each other. For instance you might choose to deploy a backend with only the catalog plugin enabled, and one with just the scaffolder plugin enabled. We've provided some tools to be able to share services and defaults across your backend system, and you can find out more about that in the [shared environments docs](../building-backends/01-index.md#shared-environments).
As mentioned previously there's also the ability to create multiple of these backends in your project so that you can split apart your backend and deploy different backends that can scale independently of each other. For instance you might choose to deploy a backend with only the catalog plugin enabled, and one with just the scaffolder plugin enabled.
@@ -61,11 +61,11 @@ All of these services can be replaced with your own implementations if you need
For example, let's say we want to customize the core configuration service to enable remote configuration loading. That would look something like this:
```ts
import { configServiceFactory } from '@backstage/backend-app-api';
import { rootConfigServiceFactory } from '@backstage/backend-app-api';
const backend = createBackend({
services: [
configServiceFactory({
rootConfigServiceFactory({
remote: { reloadIntervalSeconds: 60 },
}),
],
@@ -148,35 +148,3 @@ backend.start();
```
We've now split the backend into two separate deployments, but we still need to make sure that they can communicate with each other. This is the hard and somewhat tedious part, as Backstage currently doesn't provide an out of the box solution that solves this. You'll need to manually configure the two backends with custom implementations of the `DiscoveryService` and have them return the correct URLs for each other. Likewise, you'll also need to provide a custom implementation of the `DiscoveryApi` in the frontend, unless you surface the two backends via a proxy that handles the routing instead.
### Shared Environments
To make it a bit easier to manage multiple backends, it's possible to create a shared environment that can be used across multiple backends. You would typically house it in a separate package that can be referenced by backends in your monorepo, or published to a package registry for broader use.
A shared environment contains a set of service implementations that should be used across all backends. These services will override the default ones, but if a service is provided directly to the backend, it will override the one in the shared environment.
A shared environment is defined using `createSharedEnvironment`. In this example we place it in a new and separate package called `backend-env`:
```ts
// packages/backend-env/src/index.ts
import { createSharedEnvironment } from '@backstage/backend-plugin-api';
import { customDiscoveryServiceFactory } from './customDiscoveryServiceFactory';
export const env = createSharedEnvironment({
services: [
customDiscoveryServiceFactory(), // custom DiscoveryService implementation
],
});
```
And passed on to backends using the `env` option:
```ts
// packages/backend-b/src/index.ts, imports omitted
import { env } from '@internal/backend-env';
const backend = createBackend({ env });
backend.add(scaffolderPlugin());
backend.start();
```
@@ -37,7 +37,7 @@ describe('myPlugin', () => {
const { server } = await startTestBackend({
features: [myPlugin()],
services: [mockServices.config.factory({ data: fakeConfig })],
services: [mockServices.rootConfig.factory({ data: fakeConfig })],
});
const response = await request(server).get('/api/example/get-value');
@@ -183,11 +183,11 @@ There's additional configuration that you can optionally pass to setup the `conf
You can configure these additional options by adding an override for the core service when calling `createBackend` like follows:
```ts
import { configServiceFactory } from '@backstage/backend-app-api';
import { rootConfigServiceFactory } from '@backstage/backend-app-api';
const backend = createBackend({
services: [
configServiceFactory({
rootConfigServiceFactory({
argv: [
'--config',
'/backstage/app-config.development.yaml',
+78
View File
@@ -0,0 +1,78 @@
---
id: flightcontrol
title: Deploying with Flightcontrol
sidebar_label: AWS Fargate via Flightcontrol
description: Deploying Backstage to AWS Fargate via Flightcontrol
---
This guide explains how to deploy Backstage to [Flightcontrol](https://www.flightcontrol.dev?ref=backstage), a platform that fully automates deployments to Amazon Web Services (AWS). Flightcontrol supports git-driven and image registry deployments.
Before you begin, make sure you have a [Flightcontrol account](https://app.flightcontrol.dev/signup?ref=backstage) and a [Github account](https://github.com/login) to follow this guide.
# Deployment Via Dashboard
1. Create a new project from the Flightcontrol Dashboard
2. Select the GitHub repo for your Backstage project
3. Select `GUI` as the config type:
4. Then, choose `+ Add Web Server (Fargate)` under Services before entering the following server information:
| Field Name | Value |
| ----------------- | ----------------- |
| Build Type | Custom Dockerfile |
| Health Check Path | /catalog |
| Port | 7007 |
5. Click `Create Project` and complete any required steps (like linking your AWS account).
# Deployment via Code
1. Create a new project from the Flightcontrol Dashboard
2. Select the GitHub repo for your Backstage project
3. Select the `flightcontrol.json` Config Type.
```json filename="flightcontrol.json"
{
"$schema": "https://app.flightcontrol.dev/schema.json",
"environments": [
{
"id": "backstage",
"name": "Backstage",
"region": "us-west-2",
"source": {
"branch": "main"
},
"services": [
{
"id": "backstage",
"name": "Backstage",
"type": "fargate",
"buildType": "docker",
"dockerfilePath": "Dockerfile",
"dockerContext": ".",
"healthCheckPath": "/catalog",
"cpu": 0.5,
"memory": 1,
"domain": "backstage.yourapp.com",
"port": 7007,
"minInstances": 1,
"maxInstances": 1
}
]
}
]
}
```
# Databases and Redis
If you need a database or Redis for your Backstage plugins, you can easily add those to your Flightcontrol deployment. For more information, see [the flightcontrol docs](https://www.flightcontrol.dev/docs/guides/flightcontrol/using-code?ref=backstage#redis).
## Troubleshooting
- [Flightcontrol Documentation](https://www.flightcontrol.dev/docs?ref=backstage)
- [Troubleshooting](https://www.flightcontrol.dev/docs/troubleshooting?ref=backstage)
+3 -3
View File
@@ -51,7 +51,7 @@ The TechDocs plugin has supported integrations to Search, meaning that it
provides a default collator factory ready to be used.
The purpose of this guide is to walk you through how to register the
[DefaultTechDocsCollatorFactory](https://github.com/backstage/backstage/blob/de294ce5c410c9eb56da6870a1fab795268f60e3/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts)
[DefaultTechDocsCollatorFactory](https://github.com/backstage/backstage/blob/1adc2c7/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts)
in your App, so that you can get TechDocs documents indexed.
If you have been through the
@@ -61,10 +61,10 @@ so, you can go ahead and follow this guide - if not, start by going through the
getting started guide.
1. Import the `DefaultTechDocsCollatorFactory` from
`@backstage/plugin-techdocs-backend`.
`@backstage/plugin-search-backend-module-techdocs`.
```typescript
import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend';
import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-search-backend-module-techdocs';
```
2. If there isn't an existing schedule you'd like to run the collator on, be
@@ -64,7 +64,7 @@ The recommended approach would be to represent information in catalog-info files
**Naming strategies:**
- Ldap: Internal ldap usernames as entity names. e.g., owner: user:myuser or user: my-team-name.
- Ldap: Internal ldap usernames as entity names. e.g., owner: user:my-user or user: my-team-name.
**Ownership strategies:**
@@ -978,9 +978,9 @@ way.
The entries of this array are
[entity references](https://backstage.io/docs/features/software-catalog/references).
| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type |
| --------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------- |
| [`Group`](#kind-group) (default) | Same as this entity, typically `default` | [`hasMember`, and reverse `memberOf`](well-known-relations.md#memberof-and-hasmember) |
| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type |
| --------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------- |
| [`Group`](#kind-group) (default) | Same as this entity, typically `default` | [`parentOf`, and reverse `childOf`](well-known-relations.md#parentof-and-childof) |
### `spec.members` [optional]
@@ -207,5 +207,9 @@ scaffolder backend:
| Azure Pipeline Actions | [scaffolder-backend-module-azure-pipelines](https://www.npmjs.com/package/@parfuemerie-douglas/scaffolder-backend-module-azure-pipelines) | [Parfümerie Douglas](https://github.com/Parfuemerie-Douglas) |
| Azure Repository Actions | [scaffolder-backend-module-azure-repositories](https://www.npmjs.com/package/@parfuemerie-douglas/scaffolder-backend-module-azure-repositories) | [Parfümerie Douglas](https://github.com/Parfuemerie-Douglas) |
| Snyk Import Project | [plugin-scaffolder-backend-module-snyk](https://www.npmjs.com/package/@ma11hewthomas/plugin-scaffolder-backend-module-snyk) | [Matthew Thomas](https://github.com/Ma11hewThomas) |
| JSON Merge Actions | [plugin-scaffolder-json-merge-actions](https://www.npmjs.com/package/@mdude2314/backstage-plugin-scaffolder-json-merge-actions) | [Drew Hill](https://github.com/arhill05) |
| NPM Actions | [plugin-scaffolder-npm-actions](https://www.npmjs.com/package/@mdude2314/backstage-plugin-scaffolder-npm-actions) | [Drew Hill](https://github.com/arhill05) |
| Slack Actions | [plugin-scaffolder-backend-module-slack](https://www.npmjs.com/package/@mdude2314/backstage-plugin-scaffolder-backend-module-slack) | [Drew Hill](https://github.com/arhill05) |
| Microsoft Teams Actions | [plugin-scaffolder-backend-module-ms-teams](https://www.npmjs.com/package/@grvpandey11/backstage-plugin-scaffolder-backend-module-ms-teams) | [Gaurav Pandey](https://github.com/grvpandey11) |
Have fun! 🚀
@@ -89,10 +89,8 @@ export const validateKebabCaseValidation = (
then please use `scaffolderPlugin.provide` from there instead and export it part of your `plugin.ts` rather than re-using the `scaffolder.plugin`.
*/
import {
scaffolderPlugin,
createScaffolderFieldExtension,
} from '@backstage/plugin-scaffolder';
import { scaffolderPlugin } from '@backstage/plugin-scaffolder';
import { createScaffolderFieldExtension } from '@backstage/plugin-scaffolder-react';
import {
ValidateKebabCase,
validateKebabCaseValidation,
@@ -133,7 +131,7 @@ Should look something like this instead:
```tsx
import { ValidateKebabCaseFieldExtension } from './scaffolder/ValidateKebabCase';
import { ScaffolderFieldExtensions } from '@backstage/plugin-scaffolder';
import { ScaffolderFieldExtensions } from '@backstage/plugin-scaffolder-react';
const routes = (
<FlatRoutes>
@@ -4,7 +4,7 @@ title: Writing custom step layouts
description: How to override the default step form layout
---
Every form in each step rendered in the frontend uses the default form layout from [react-json-schema-form](https://react-jsonschema-form.readthedocs.io/). It is possible to override this behaviour by supplying a `ui:ObjectFieldTemplate` property for a particular step:
Every form in each step rendered in the frontend uses the default form layout from [react-jsonschema-form](https://rjsf-team.github.io/react-jsonschema-form/docs/). It is possible to override this behaviour by supplying a `ui:ObjectFieldTemplate` property for a particular step:
```yaml
parameters:
@@ -12,7 +12,7 @@ parameters:
ui:ObjectFieldTemplate: TwoColumn
```
This is the same [field](https://react-jsonschema-form.readthedocs.io/en/latest/advanced-customization/custom-templates/#objectfieldtemplate) used by [react-json-schema-form](https://react-jsonschema-form.readthedocs.io/) but we need to add a couple of steps to ensure that the string value of `TwoColumn` above is resolved to a react component.
This is the same [field](https://rjsf-team.github.io/react-jsonschema-form/docs/advanced-customization/custom-templates#objectfieldtemplate) used by [react-jsonschema-form](https://rjsf-team.github.io/react-jsonschema-form/docs/) but we need to add a couple of steps to ensure that the string value of `TwoColumn` above is resolved to a react component.
## Registering a React component as a custom step layout
@@ -499,6 +499,7 @@ template. These follow the same standard format:
- id: fetch-base # A unique id for the step
name: Fetch Base # A title displayed in the frontend
if: ${{ parameters.name }} # Optional condition, skip the step if not truthy
each: ${{ parameters.iterable }} # Optional iterable, run the same step multiple times
action: fetch:template # An action to call
input: # Input that is passed as arguments to the action handler
url: ./template
@@ -510,6 +511,27 @@ By default we ship some [built in actions](./builtin-actions.md) that you can
take a look at, or you can
[create your own custom actions](./writing-custom-actions.md).
When `each` is provided, the current iteration value is available in the `${{ each }}` input.
Examples:
```yaml
each: ['apples', 'oranges']
input:
values:
fruit: ${{ each.value }}
```
```yaml
each: [{ name: 'apple', count: 3 }, { name: 'orange', count: 1 }]
input:
values:
fruit: ${{ each.value.name }}
count: ${{ each.value.count }}
```
When `each` is used, the outputs of a repeated step are returned as an array of outputs from each iteration.
## Outputs
Each individual step can output some variables that can be used in the
+2 -5
View File
@@ -188,15 +188,12 @@ import {
} from '@backstage/plugin-techdocs';
import { Entity } from '@backstage/catalog-model';
import {
EntityListDocsGrid,
DocsGroupConfig,
} from '@backstage/plugin-techdocs';
import { EntityListDocsGrid } from '@backstage/plugin-techdocs';
export type CustomTechDocsHomeProps = {
groups?: Array<{
title: React.ReactNode;
filterPredicate: (entity: Entity) => boolean;
filterPredicate: ((entity: Entity) => boolean) | string;
}>;
};
+12 -12
View File
@@ -2,25 +2,25 @@
id: glossary
title: Backstage Glossary
# prettier-ignore
description: List of all the terms, abbreviations, and phrases used in Backstage, together with their explanations.
description: List of terms, abbreviations, and phrases used in Backstage, together with their explanations.
---
The Backstage Glossary lists all the terms, abbreviations, and phrases used in
The Backstage Glossary lists terms, abbreviations, and phrases used in
Backstage, together with their explanations. We encourage you to use the
terminology below for clarity and consistency when discussing Backstage.
### Authentication Glossary
This [page](../auth/glossary.md) directs to the terms and phrases related to
authentication and identity section of Backstage.
See also [Authentication Glossary](../auth/glossary.md), a separate glossary of terms and phrases
specifically related to the authentication and identity section of Backstage.
### Backstage User Profiles
There are three main user profiles for Backstage: the integrator, the
contributor, and the software engineer.
contributor, and the end user (typically a software engineer).
| Term | Explanation |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Integrator | The **integrator** hosts the Backstage app and configures which plugins are available to use in the app. |
| Contributor | The **contributor** adds functionality to the app by writing plugins. |
| Software Engineer | The **software engineer** uses the app's functionality and interacts with its plugins. In practice, this profile covers the various roles that help deliver software, from the Software Engineer themselves, to Designers, Data Scientists, Product Owners, Engineering Managers, etc. |
| Term | Explanation |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Integrator | The **integrator** hosts the Backstage app and configures which plugins are available to use in the app. |
| Contributor | The **contributor** adds functionality to the app by writing plugins. |
| End user | The **end user** uses the app's functionality and interacts with its plugins. This profile covers the various roles that help deliver software. The typical end user is a **software engineer**, but users might also consider themselves _designers_, _data scientists_, _product owners_, _engineering managers_, _technical writers_, and so on. |
| Software engineer | The **software engineer** is an **end user** who uses the app's functionality and interacts with its plugins in the course of writing and documenting code. This user is more likely to embed documentation in the code files they produce, and create rough drafts of conceptual pages in collaboration with a **technical writer** or _technical editor_. |
| Technical writer | The **technical writer** is an **end user** who uses the app's functionality and interacts with its plugins in the course of writing and editing documentation. This user is more likely to produce and customize templates and produce conceptual pages to supplement documentation embedded in code files. |
+1 -1
View File
@@ -36,7 +36,7 @@ Example:
```yaml
# in app-config.yaml
proxy:
simple-example: http://simple.example.com:8080
/simple-example: http://simple.example.com:8080
'/larger-example/v1':
target: http://larger.example.com:8080/svc.v1
headers:
+1 -1
View File
@@ -84,4 +84,4 @@ Below you can find a list of links and references to help you learn about and st
- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.16.0-changelog.md)
- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins)
Sign up for our [newsletter](https://mailchi.mp/spotify/backstage-community) if you want to be informed about what is happening in the world of Backstage.
Sign up for our [newsletter](https://info.backstage.spotify.com/newsletter_subscribe) if you want to be informed about what is happening in the world of Backstage.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+72
View File
@@ -0,0 +1,72 @@
---
id: v1.17.0
title: v1.17.0
description: Backstage Release v1.17.0
---
These are the release notes for the v1.17.0 release of [Backstage](https://backstage.io/).
A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done.
## Highlights
### Changes to the New Backend System
For this release we had another look at the new backend system, in particular how well it fits together with the concept of plugin installation without code modification, and we identified a number of breaking changes that we wanted to make.
We have removed the ability to define options for plugins and modules, and force them to be optional for services. Options have been moved either to static configuration or extension points, and modules now also have the ability to register extension points.
Service factories are now considered `BackendFeature`s and are installed via `backend.add(...)` rather than via the `services` option, which has been removed.
The configuration service has also been renamed to `rootConfig` in order to match other root-scoped services and make space for a potential plugin-scoped configuration service in the future.
The shared environments concept has been removed. We are still interested in having some way to define reusable presets in the new system, but shared environments were too limited.
We expect these to be the last broad breaking changes to the new backend system, and are likely to start encouraging use of it in the next release.
### Catalog Telemetry with Processing Tracing
The Catalog has been instrumented with some simple OpenTelemetry Spans so you can now dig into the processing loop and see it in action using tracing.
Contributed by [@mikebryant](https://github.com/mikebryant) in [#17534](https://github.com/backstage/backstage/pull/17534)
### New `each` property for Scaffolder Actions
You can now define an `each` iterable in the `steps` for a template, which will run a given action for each entry in the iterable.
Contributed by [@alexef](https://github.com/alexef) in [#18157](https://github.com/backstage/backstage/pull/18157)
### Updated proxy configuration
The shape of the proxy plugin configuration has been changed in order to make space for additional keys. Rather than defining the proxy endpoints directly under `proxy`, they should now be defined at `proxy.endpoints` instead.
### OpenAPI Support for Backend Plugins
You can now use OpenAPI specs to generate typed routers for your backend plugins with request validation using `createOpenApiRouter()`. Theres been some movement to support this for some of the plugins in the monorepo like `todo`, `search` and `catalog`.
Contributed by [@sennyeya](https://github.com/sennyeya) in [#17875](https://github.com/backstage/backstage/pull/17875)
### New plugin: `@backstage/plugin-catalog-backend-module-gcp`
Allows ingestion of GKE Clusters as Resources into the Catalog. Contributed by [@mclarke47](https://github.com/mclarke47) in [#18759](https://github.com/backstage/backstage/pull/18759)
## Security Fixes
This release does not contain any security fixes.
## Upgrade path
We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated).
## Links and References
Below you can find a list of links and references to help you learn about and start using this new release.
- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/)
- [GitHub repository](https://github.com/backstage/backstage)
- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy)
- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support
- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.17.0-changelog.md)
- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins)
Sign up for our [newsletter](https://info.backstage.spotify.com/newsletter_subscribe) if you want to be informed about what is happening in the world of Backstage.
@@ -26,7 +26,6 @@ When we set out on this project, we had a few primary goals. First, we intended
- Make it easier to create and maintain backend installations.
- Align how plugins provide points of customization and how those customizations are installed.
- Make it much easier to maintain plugins, in particular keeping the API stable.
- Simplify the process of splitting plugins out into separate deployments with shared environments.
- Improve the local development and testing experience.
Prioritizing simplicity is often a guiding principle that we use for designs that span multiple ownership roles. We decide on which parts of the system that we think are the most important to have as simple as possible, or, viewed from the opposite end, where in the system we put necessary complexity. In this case, we optimized for keeping the backend setup as simple as possible, followed by modules and plugins, then libraries, and lastly the framework itself. What this guidance means in practice is that when there is complexity that needs to be added to implement a certain feature, we place as much of it as possible within the framework itself, then libraries, plugins and modules, and if absolutely needed, the backend setup.
@@ -0,0 +1,51 @@
---
# prettier-ignore
title: "Five common traits of successful Backstage adopters"
author: Taras Mankovski, CXO, Frontside
---
![backstage header](assets/2023-07-28/header.png)
At [Frontside](https://frontside.com/), our goal is to help cloud-native teams create cohesive development experiences. We've been at the Backstage party since the beginning helping companies adopt and extend Backstage to fit the needs of their unique ecosystems.
Through our experience, we've uncovered five common traits of organizations that have improved developer experience through successful Backstage implementation and adoption. In this blog, we'll dive into these traits with some thoughts on how you can follow their blueprint.
{/* truncate */}
## **1) They take a product-centric approach**
The biggest factor for successful adopters of Backstage is their approach. There is a high correlation of success within organizations that approach building a developer portal like they're building a product. Some organizations will jump straight into solutioning instead of taking their time to identify what the problems are, how they affect users, and how those issues can be addressed.
The team building out Backstage should assess or work from existing insights on the core challenges that developers are facing in their organization — both qualitative and quantitative data counts here — and connect those issues to a product roadmap with initial use cases and adoption milestones marked. By doing their research in advance, successful orgs have a clear vision of what they want to accomplish with their Backstage instance. They know exactly what goals need to be met and have pressure-tested potential issues and barriers.
If you've already started your Backstage adoption journey but haven't mapped a Product Requirements Document (or PRD), don't panic! There is always time to do the foundational knowledge-building necessary to deploy something successful.
## **2) They tie Backstage to a larger platform journey**
Platform engineering has emerged in response to the growing complexity of cloud-native software architecture. Backstage has a huge role to play in implementing a platform strategy but its part of a larger story. Having buy-in from both higher ups and the teams tasked with platform goals is an essential step in successful Backstage adoption. Without the support at the top, it can be difficult to implement platforming as a priority within your organization.
And by "the top", we don't necessarily mean your CTO needs to rubber stamp your Backstage POC. But it's important that higher-level Platform goals have been set among VPs and directors with the understanding that a well-constructed developer portal can be the catalyst to achieving not only better developer experience but broader cultural shifts.
Having this kind of executive buy-in means more than just getting stakeholders on board with a portal build or clearing pathways towards Backstage adoption; it also means ensuring they understand the realities of your organization's journey.
## **3) They prioritize developer experience**
Having a dedicated developer experience or DevOps team tasked not only with building out a Backstage instance — but with leading adoption — is another big factor to success.
Competing platforms are very common at big companies, with many teams doing different things or serving different parts of a business. But developer experience teams usually have a very clear mandate and are often one of the only commonalities between these competing teams. This team should have the bandwidth available to oversee the adoption process from start to finish, and partner with the right folks (research, design, internal comms and marketing) to create an effective adoption plan tailored specifically for a company's needs.
If you don't have established developer experience resources in place, then the questions the team leading the Backstage work needs to ask are "what are the common problems to be solved at a platform level?" and "once we've proved our initial use cases, how are we internally evangelizing this amongst our competing teams?"
## **4) They collaborate with other platform teams**
A developer experience team can not single-handedly transform an organization's development structures, processes, and culture. It requires collaboration with teams responsible for other aspects of the platform. Successful adopters collaborate with other teams to bring them along on the journey of improving developer experience. They use Backstage as an opportunity to foster their inner-source contribution practice by allowing multiple platform teams to contribute plugins to their portal.
The developer experience team takes on the role of host in that collaborative process. They support other teams in integrating their features into the portal, provide guidance on best practices, and advocate for the needs of developers.
## **5) They engage, learn, and grow with the community**
One of the key benefits of building a developer platform based off an open source framework is leveraging the contributions and best practices from the community. The Backstage community is the largest gathering of developer experience practitioners in the world. There are now [thousands of adopters](https://github.com/backstage/backstage/blob/63aa3a65ec05f638ba76c06878d6635194620b34/ADOPTERS.md#L4) with a wealth of experience and best practices to learn from — and they are excited to share!
By participating in the community, developer experience leaders can learn from their peers at other companies about strategies that work and can keep up with the latest features of the ever-evolving Backstage platform. They're aware of what solutions exist within the open source framework and plugin marketplace as well as what they may need to build in-house.
In short, successful Backstage adopters engage within the Backstage community and their peer group to find solutions that fit their common challenges as well as their unique needs.
Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

+1 -1
View File
@@ -5,6 +5,6 @@ authorUrl: https://redhat.com
category: Discovery
description: Synchronize 3scale content into the Backstage catalog.
documentation: https://janus-idp.io/plugins/3scale
iconUrl: http://janus-idp.io/images/plugins/3scale.svg
iconUrl: https://janus-idp.io/images/plugins/3scale.svg
npmPackageName: '@janus-idp/backstage-plugin-3scale-backend'
addedDate: '2023-05-15'
@@ -0,0 +1,10 @@
---
title: API SDK Generator
author: Konfig
authorUrl: https://konfigthis.com/
category: Development
description: Generate SDKs for your REST API to accelerate integration
documentation: https://github.com/konfig-dev/backstage-plugin-konfig/tree/main/plugins/backstage-plugin-konfig
iconUrl: https://raw.githubusercontent.com/konfig-dev/backstage-plugin-konfig/main/plugins/backstage-plugin-konfig/docs/logo.png
npmPackageName: 'backstage-plugin-konfig'
addedDate: '2023-08-07'
@@ -0,0 +1,13 @@
---
title: JFrog Artifactory Libs plugin
author: Vity
authorUrl: https://github.com/Vity01
category: Discovery
description:
frontend plugin provides a simple way to display generated artifact (library) details like
- group, artifact, repository, what is the latest version, and it simply
allows to copy library definition for the package managers.
documentation: https://github.com/Vity01/backstage-jfrog-artifactory-libs
iconUrl: https://raw.githubusercontent.com/Vity01/backstage-jfrog-artifactory-libs/main/doc/artifactory.svg
npmPackageName: 'backstage-plugin-jfrog-artifactory-libs'
addedDate: '2023-08-14'
@@ -5,6 +5,6 @@ authorUrl: https://redhat.com
category: Image
description: View container image details from JFrog Artifactory in Backstage.
documentation: https://janus-idp.io/plugins/jfrog-artifactory
iconUrl: http://janus-idp.io/images/plugins/jfrog-artifactory.svg
iconUrl: https://janus-idp.io/images/plugins/jfrog-artifactory.svg
npmPackageName: '@janus-idp/backstage-plugin-jfrog-artifactory'
addedDate: '2023-05-15'
+1 -1
View File
@@ -5,6 +5,6 @@ authorUrl: https://redhat.com
category: Authentication/Authorization
description: Load users and groups from Keycloak, enabling use of multiple authentication providers to be applied to Backstage entities.
documentation: https://janus-idp.io/plugins/keycloak
iconUrl: http://janus-idp.io/images/plugins/keycloak.svg
iconUrl: https://janus-idp.io/images/plugins/keycloak.svg
npmPackageName: '@janus-idp/backstage-plugin-keycloak-backend'
addedDate: '2023-05-15'
+10
View File
@@ -0,0 +1,10 @@
---
title: Kiali Service Mesh
author: Red Hat
authorUrl: https://redhat.com
category: Istio
description: Configure, visualize, validate and troubleshoot your mesh with Istio
documentation: https://janus-idp.io/plugins/kiali
iconUrl: https://janus-idp.io/images/plugins/kiali.svg
npmPackageName: '@janus-idp/backstage-plugin-kiali'
addedDate: '2023-07-25'
+1 -1
View File
@@ -5,6 +5,6 @@ authorUrl: https://redhat.com
category: Infrastructure
description: View clusters from OCM's MultiClusterHub and MultiCluster Engine in Backstage.
documentation: https://janus-idp.io/plugins/ocm
iconUrl: http://janus-idp.io/images/plugins/ocm.svg
iconUrl: https://janus-idp.io/images/plugins/ocm.svg
npmPackageName: '@janus-idp/backstage-plugin-ocm'
addedDate: '2023-05-15'
+1 -1
View File
@@ -5,6 +5,6 @@ authorUrl: https://redhat.com
category: Image
description: View container image details from Quay in Backstage.
documentation: https://janus-idp.io/plugins/quay
iconUrl: http://janus-idp.io/images/plugins/quay.svg
iconUrl: https://janus-idp.io/images/plugins/quay.svg
npmPackageName: '@janus-idp/backstage-plugin-quay'
addedDate: '2023-05-15'
@@ -0,0 +1,9 @@
---
title: Microsoft Teams Scaffolder Actions
author: Gaurav Pandey
authorUrl: https://github.com/grvpandey11
category: Scaffolder
description: Interact with Microsoft Teams from Scaffolder templates
documentation: https://github.com/grvpandey11/backstage-plugin-scaffolder-backend-module-ms-teams/tree/main#readme
npmPackageName: '@grvpandey11/backstage-plugin-scaffolder-backend-module-ms-teams'
addedDate: '2023-08-11'
@@ -0,0 +1,10 @@
---
title: Slack Scaffolder Actions
author: Drew Hill
authorUrl: https://github.com/arhill05
category: Scaffolder
description: Interact with Slack from scaffolder templates
documentation: https://github.com/arhill05/backstage-plugin-scaffolder-backend-module-slack#readme
iconUrl: img/Slack-mark-RGB.png
npmPackageName: '@mdude2314/backstage-plugin-scaffolder-backend-module-slack'
addedDate: '2023-08-04'
+1 -1
View File
@@ -5,6 +5,6 @@ authorUrl: https://redhat.com
category: CI/CD
description: Easily view Tekton PipelineRun status for your services in Backstage.
documentation: https://janus-idp.io/plugins/tekton
iconUrl: http://janus-idp.io/images/plugins/tekton.svg
iconUrl: https://janus-idp.io/images/plugins/tekton.svg
npmPackageName: '@janus-idp/backstage-plugin-tekton'
addedDate: '2023-05-15'
+1 -1
View File
@@ -5,6 +5,6 @@ authorUrl: https://redhat.com
category: Kubernetes
description: Visualize the deployment status and related resources of your applications deployed on any Kubernetes cluster.
documentation: https://janus-idp.io/plugins/topology
iconUrl: http://janus-idp.io/images/plugins/topology.svg
iconUrl: https://janus-idp.io/images/plugins/topology.svg
npmPackageName: '@janus-idp/backstage-plugin-topology'
addedDate: '2023-05-15'
+1 -1
View File
@@ -177,7 +177,7 @@ module.exports = {
position: 'left',
},
{
to: 'docs/releases/v1.16.0',
to: 'docs/releases/v1.17.0',
label: 'Releases',
position: 'left',
},
+2
View File
@@ -1,6 +1,7 @@
{
"releases": {
"Release Notes": [
"releases/v1.17.0",
"releases/v1.16.0",
"releases/v1.15.0",
"releases/v1.14.0",
@@ -331,6 +332,7 @@
"deployment/k8s",
"deployment/heroku",
"deployment/koyeb",
"deployment/flightcontrol",
{
"type": "category",
"label": "Using Backstage Deploy (alpha)",
-21
View File
@@ -32,27 +32,6 @@ const HomePage = () => {
<BannerSectionGrid
header={
<>
<div
className={clsx(
'card',
'padding--md',
homeStyles.newsletterBanner,
)}
>
<div className="text--left bannerContent">
CFP is now open for BackstageCon 2023 🚀
</div>
<div>
<a
className="button button--outline button--secondary"
href="https://bit.ly/BackstageConCFP"
rel="noopener noreferrer"
target="_blank"
>
Submit a talk
</a>
</div>
</div>
{!hiddenNewsletterBanner && (
<div
className={clsx(
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

+2 -2
View File
@@ -47,7 +47,7 @@
"@types/react": "^17",
"@types/react-dom": "^17"
},
"version": "1.17.0-next.0",
"version": "1.17.0",
"dependencies": {
"@backstage/errors": "workspace:^",
"@manypkg/get-packages": "^1.1.3"
@@ -65,7 +65,7 @@
"@types/node": "^16.11.26",
"@types/webpack": "^5.28.0",
"command-exists": "^1.2.9",
"concurrently": "^7.0.0",
"concurrently": "^8.0.0",
"cross-env": "^7.0.0",
"e2e-test": "workspace:*",
"eslint": "^8.6.0",
+11
View File
@@ -1,5 +1,16 @@
# @backstage/app-defaults
## 1.4.2
### Patch Changes
- Updated dependencies
- @backstage/core-app-api@1.9.1
- @backstage/core-components@0.13.4
- @backstage/core-plugin-api@1.5.3
- @backstage/theme@0.4.1
- @backstage/plugin-permission-react@0.4.14
## 1.4.2-next.0
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/app-defaults",
"description": "Provides the default wiring of a Backstage App",
"version": "1.4.2-next.0",
"version": "1.4.2",
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
+213
View File
@@ -1,5 +1,218 @@
# example-app
## 0.2.86
### Patch Changes
- Updated dependencies
- @backstage/core-app-api@1.9.1
- @backstage/plugin-catalog-graph@0.2.33
- @backstage/plugin-playlist@0.1.13
- @backstage/plugin-pagerduty@0.6.2
- @backstage/plugin-scaffolder@1.14.2
- @backstage/plugin-explore@0.4.7
- @backstage/plugin-org@0.6.11
- @backstage/integration-react@1.1.16
- @backstage/plugin-microsoft-calendar@0.1.6
- @backstage/plugin-newrelic-dashboard@0.2.14
- @backstage/plugin-entity-feedback@0.2.4
- @backstage/plugin-linguist-common@0.1.1
- @backstage/plugin-apache-airflow@0.2.14
- @backstage/plugin-octopus-deploy@0.2.3
- @backstage/plugin-stack-overflow@0.1.19
- @backstage/plugin-code-coverage@0.2.14
- @backstage/plugin-tech-insights@0.3.13
- @backstage/plugin-dynatrace@7.0.1
- @backstage/plugin-gcalendar@0.3.17
- @backstage/plugin-shortcuts@0.3.13
- @backstage/plugin-airbrake@0.3.21
- @backstage/plugin-kafka@0.3.21
- @backstage/plugin-nomad@0.1.2
- @backstage/plugin-adr@0.6.4
- @backstage/plugin-newrelic@0.3.39
- @backstage/cli@0.22.10
- @backstage/plugin-kubernetes@0.10.0
- @backstage/core-components@0.13.4
- @backstage/plugin-home@0.5.5
- @backstage/plugin-catalog-react@1.8.1
- @backstage/plugin-scaffolder-react@1.5.2
- @backstage/plugin-devtools@0.1.3
- @backstage/app-defaults@1.4.2
- @backstage/core-plugin-api@1.5.3
- @backstage/plugin-api-docs@0.9.7
- @backstage/plugin-azure-devops@0.3.3
- @backstage/plugin-azure-sites@0.1.10
- @backstage/plugin-badges@0.2.45
- @backstage/plugin-catalog-import@0.9.11
- @backstage/plugin-catalog-unprocessed-entities@0.1.2
- @backstage/plugin-circleci@0.3.21
- @backstage/plugin-cloudbuild@0.3.21
- @backstage/plugin-cost-insights@0.12.10
- @backstage/plugin-gcp-projects@0.3.40
- @backstage/plugin-github-actions@0.6.2
- @backstage/plugin-gocd@0.1.27
- @backstage/plugin-graphiql@0.2.53
- @backstage/plugin-jenkins@0.8.3
- @backstage/plugin-lighthouse@0.4.6
- @backstage/plugin-linguist@0.1.6
- @backstage/plugin-puppetdb@0.1.4
- @backstage/plugin-rollbar@0.4.21
- @backstage/plugin-search@1.3.4
- @backstage/plugin-search-react@1.6.4
- @backstage/plugin-sentry@0.5.6
- @backstage/plugin-stackstorm@0.1.5
- @backstage/plugin-tech-radar@0.6.7
- @backstage/plugin-techdocs@1.6.6
- @backstage/plugin-techdocs-module-addons-contrib@1.0.16
- @backstage/plugin-todo@0.2.23
- @backstage/plugin-user-settings@0.7.6
- @backstage/catalog-model@1.4.1
- @backstage/config@1.0.8
- @backstage/theme@0.4.1
- @backstage/plugin-catalog-common@1.0.15
- @backstage/plugin-permission-react@0.4.14
- @backstage/plugin-search-common@1.2.5
- @backstage/plugin-techdocs-react@1.1.9
- @internal/plugin-catalog-customized@0.0.13
## 0.2.86-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-graph@0.2.33-next.2
- @backstage/plugin-linguist-common@0.1.1-next.1
- @backstage/plugin-catalog-react@1.8.1-next.1
- @backstage/plugin-linguist@0.1.6-next.2
- @backstage/plugin-adr@0.6.4-next.2
- @backstage/plugin-airbrake@0.3.21-next.2
- @backstage/plugin-api-docs@0.9.7-next.2
- @backstage/plugin-azure-devops@0.3.3-next.1
- @backstage/plugin-azure-sites@0.1.10-next.1
- @backstage/plugin-badges@0.2.45-next.1
- @internal/plugin-catalog-customized@0.0.13-next.2
- @backstage/plugin-catalog-import@0.9.11-next.2
- @backstage/plugin-circleci@0.3.21-next.1
- @backstage/plugin-cloudbuild@0.3.21-next.1
- @backstage/plugin-code-coverage@0.2.14-next.2
- @backstage/plugin-cost-insights@0.12.10-next.1
- @backstage/plugin-dynatrace@7.0.1-next.2
- @backstage/plugin-entity-feedback@0.2.4-next.2
- @backstage/plugin-explore@0.4.7-next.1
- @backstage/plugin-github-actions@0.6.2-next.2
- @backstage/plugin-gocd@0.1.27-next.1
- @backstage/plugin-home@0.5.5-next.1
- @backstage/plugin-jenkins@0.8.3-next.2
- @backstage/plugin-kafka@0.3.21-next.2
- @backstage/plugin-kubernetes@0.9.4-next.1
- @backstage/plugin-lighthouse@0.4.6-next.1
- @backstage/plugin-newrelic-dashboard@0.2.14-next.2
- @backstage/plugin-nomad@0.1.2-next.2
- @backstage/plugin-octopus-deploy@0.2.3-next.2
- @backstage/plugin-org@0.6.11-next.2
- @backstage/plugin-pagerduty@0.6.2-next.1
- @backstage/plugin-playlist@0.1.13-next.2
- @backstage/plugin-puppetdb@0.1.4-next.1
- @backstage/plugin-rollbar@0.4.21-next.1
- @backstage/plugin-scaffolder@1.14.2-next.2
- @backstage/plugin-scaffolder-react@1.5.2-next.1
- @backstage/plugin-search@1.3.4-next.1
- @backstage/plugin-sentry@0.5.6-next.1
- @backstage/plugin-tech-insights@0.3.13-next.2
- @backstage/plugin-techdocs@1.6.6-next.2
- @backstage/plugin-todo@0.2.23-next.1
- @backstage/plugin-user-settings@0.7.6-next.1
- @backstage/cli@0.22.10-next.1
- @backstage/integration-react@1.1.16-next.1
- @backstage/plugin-apache-airflow@0.2.14-next.1
- @backstage/plugin-catalog-unprocessed-entities@0.1.2-next.0
- @backstage/plugin-devtools@0.1.3-next.1
- @backstage/plugin-gcalendar@0.3.17-next.1
- @backstage/plugin-gcp-projects@0.3.40-next.0
- @backstage/plugin-graphiql@0.2.53-next.0
- @backstage/plugin-microsoft-calendar@0.1.6-next.1
- @backstage/plugin-newrelic@0.3.39-next.0
- @backstage/plugin-shortcuts@0.3.13-next.1
- @backstage/plugin-stack-overflow@0.1.19-next.1
- @backstage/plugin-stackstorm@0.1.5-next.0
- @backstage/plugin-tech-radar@0.6.7-next.0
- @backstage/plugin-techdocs-module-addons-contrib@1.0.16-next.1
## 0.2.86-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-playlist@0.1.13-next.1
- @backstage/plugin-scaffolder@1.14.2-next.1
- @backstage/integration-react@1.1.16-next.1
- @backstage/plugin-microsoft-calendar@0.1.6-next.1
- @backstage/plugin-newrelic-dashboard@0.2.14-next.1
- @backstage/plugin-entity-feedback@0.2.4-next.1
- @backstage/plugin-linguist-common@0.1.1-next.0
- @backstage/plugin-apache-airflow@0.2.14-next.1
- @backstage/plugin-octopus-deploy@0.2.3-next.1
- @backstage/plugin-stack-overflow@0.1.19-next.1
- @backstage/plugin-catalog-graph@0.2.33-next.1
- @backstage/plugin-code-coverage@0.2.14-next.1
- @backstage/plugin-tech-insights@0.3.13-next.1
- @backstage/plugin-dynatrace@7.0.1-next.1
- @backstage/plugin-gcalendar@0.3.17-next.1
- @backstage/plugin-shortcuts@0.3.13-next.1
- @backstage/plugin-airbrake@0.3.21-next.1
- @backstage/plugin-kafka@0.3.21-next.1
- @backstage/plugin-nomad@0.1.2-next.1
- @backstage/plugin-adr@0.6.4-next.1
- @backstage/plugin-org@0.6.11-next.1
- @backstage/plugin-devtools@0.1.3-next.1
- @backstage/cli@0.22.10-next.1
- @backstage/plugin-catalog-import@0.9.11-next.1
- @backstage/plugin-github-actions@0.6.2-next.1
- @backstage/plugin-techdocs@1.6.6-next.1
- @backstage/plugin-techdocs-module-addons-contrib@1.0.16-next.1
- @backstage/plugin-linguist@0.1.6-next.1
- @backstage/plugin-jenkins@0.8.3-next.1
- @backstage/app-defaults@1.4.2-next.0
- @backstage/catalog-model@1.4.1
- @backstage/config@1.0.8
- @backstage/core-app-api@1.9.1-next.0
- @backstage/core-components@0.13.4-next.0
- @backstage/core-plugin-api@1.5.3
- @backstage/theme@0.4.1
- @backstage/plugin-api-docs@0.9.7-next.1
- @backstage/plugin-azure-devops@0.3.3-next.0
- @backstage/plugin-azure-sites@0.1.10-next.0
- @backstage/plugin-badges@0.2.45-next.0
- @backstage/plugin-catalog-common@1.0.15
- @backstage/plugin-catalog-react@1.8.1-next.0
- @backstage/plugin-catalog-unprocessed-entities@0.1.2-next.0
- @backstage/plugin-circleci@0.3.21-next.0
- @backstage/plugin-cloudbuild@0.3.21-next.0
- @backstage/plugin-cost-insights@0.12.10-next.0
- @backstage/plugin-explore@0.4.7-next.0
- @backstage/plugin-gcp-projects@0.3.40-next.0
- @backstage/plugin-gocd@0.1.27-next.0
- @backstage/plugin-graphiql@0.2.53-next.0
- @backstage/plugin-home@0.5.5-next.0
- @backstage/plugin-kubernetes@0.9.4-next.0
- @backstage/plugin-lighthouse@0.4.6-next.0
- @backstage/plugin-newrelic@0.3.39-next.0
- @backstage/plugin-pagerduty@0.6.2-next.0
- @backstage/plugin-permission-react@0.4.14
- @backstage/plugin-puppetdb@0.1.4-next.0
- @backstage/plugin-rollbar@0.4.21-next.0
- @backstage/plugin-scaffolder-react@1.5.2-next.0
- @backstage/plugin-search@1.3.4-next.0
- @backstage/plugin-search-common@1.2.5
- @backstage/plugin-search-react@1.6.4-next.0
- @backstage/plugin-sentry@0.5.6-next.0
- @backstage/plugin-stackstorm@0.1.5-next.0
- @backstage/plugin-tech-radar@0.6.7-next.0
- @backstage/plugin-techdocs-react@1.1.9-next.0
- @backstage/plugin-todo@0.2.23-next.0
- @backstage/plugin-user-settings@0.7.6-next.0
- @internal/plugin-catalog-customized@0.0.13-next.1
## 0.2.86-next.0
### Patch Changes
+7 -1
View File
@@ -1,11 +1,17 @@
{
"name": "example-app",
"version": "0.2.86-next.0",
"version": "0.2.86",
"private": true,
"backstage": {
"role": "frontend"
},
"bundled": true,
"homepage": "https://backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "packages/app"
},
"dependencies": {
"@backstage/app-defaults": "workspace:^",
"@backstage/catalog-model": "workspace:^",
+71
View File
@@ -1,5 +1,76 @@
# @backstage/backend-app-api
## 0.5.0
### Minor Changes
- b9c57a4f857e: **BREAKING**: Renamed `configServiceFactory` to `rootConfigServiceFactory`.
- a6d7983f349c: **BREAKING**: Removed the `services` option from `createBackend`. Service factories are now `BackendFeature`s and should be installed with `backend.add(...)` instead. The following should be migrated:
```ts
const backend = createBackend({ services: [myCustomServiceFactory] });
```
To instead pass the service factory via `backend.add(...)`:
```ts
const backend = createBackend();
backend.add(customRootLoggerServiceFactory);
```
### Patch Changes
- e65c4896f755: Do not throw in backend.stop, if start failed
- c7aa4ff1793c: Allow modules to register extension points.
- 57a10c6c69cc: Add validation to make sure that extension points do not cross plugin boundaries.
- cc9256a33bcc: Added new experimental `featureDiscoveryServiceFactory`, available as an `/alpha` export.
- Updated dependencies
- @backstage/backend-common@0.19.2
- @backstage/config-loader@1.4.0
- @backstage/backend-plugin-api@0.6.0
- @backstage/cli-node@0.1.3
- @backstage/plugin-auth-node@0.2.17
- @backstage/backend-tasks@0.5.5
- @backstage/plugin-permission-node@0.7.11
- @backstage/cli-common@0.1.12
- @backstage/config@1.0.8
- @backstage/errors@1.2.1
- @backstage/types@1.1.0
## 0.5.0-next.2
### Patch Changes
- e65c4896f755: Do not throw in backend.stop, if start failed
- cc9256a33bcc: Added new experimental `featureDiscoveryServiceFactory`, available as an `/alpha` export.
- Updated dependencies
- @backstage/backend-plugin-api@0.6.0-next.2
- @backstage/backend-tasks@0.5.5-next.2
- @backstage/backend-common@0.19.2-next.2
- @backstage/plugin-permission-node@0.7.11-next.2
- @backstage/plugin-auth-node@0.2.17-next.2
- @backstage/config-loader@1.4.0-next.1
## 0.5.0-next.1
### Minor Changes
- b9c57a4f857e: **BREAKING**: Renamed `configServiceFactory` to `rootConfigServiceFactory`.
### Patch Changes
- Updated dependencies
- @backstage/backend-common@0.19.2-next.1
- @backstage/config-loader@1.4.0-next.1
- @backstage/plugin-auth-node@0.2.17-next.1
- @backstage/backend-plugin-api@0.6.0-next.1
- @backstage/backend-tasks@0.5.5-next.1
- @backstage/plugin-permission-node@0.7.11-next.1
- @backstage/cli-common@0.1.12
- @backstage/config@1.0.8
- @backstage/errors@1.2.1
- @backstage/types@1.1.0
## 0.4.6-next.0
### Patch Changes
@@ -0,0 +1,16 @@
## API Report File for "@backstage/backend-app-api"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { FeatureDiscoveryService } from '@backstage/backend-plugin-api/alpha';
import { ServiceFactory } from '@backstage/backend-plugin-api';
// @alpha (undocumented)
export const featureDiscoveryServiceFactory: () => ServiceFactory<
FeatureDiscoveryService,
'root'
>;
// (No @packageDocumentation comment for this package)
```
+16 -16
View File
@@ -9,7 +9,6 @@ import type { AppConfig } from '@backstage/config';
import { BackendFeature } from '@backstage/backend-plugin-api';
import { CacheClient } from '@backstage/backend-common';
import { Config } from '@backstage/config';
import { ConfigService } from '@backstage/backend-plugin-api';
import { CorsOptions } from 'cors';
import { ErrorRequestHandler } from 'express';
import { Express as Express_2 } from 'express';
@@ -30,6 +29,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common';
import { RemoteConfigSourceOptions } from '@backstage/config-loader';
import { RequestHandler } from 'express';
import { RequestListener } from 'http';
import { RootConfigService } from '@backstage/backend-plugin-api';
import { RootHttpRouterService } from '@backstage/backend-plugin-api';
import { RootLifecycleService } from '@backstage/backend-plugin-api';
import { RootLoggerService } from '@backstage/backend-plugin-api';
@@ -43,7 +43,7 @@ import { UrlReader } from '@backstage/backend-common';
// @public (undocumented)
export interface Backend {
// (undocumented)
add(feature: BackendFeature): void;
add(feature: BackendFeature | (() => BackendFeature)): void;
// (undocumented)
start(): Promise<void>;
// (undocumented)
@@ -53,17 +53,6 @@ export interface Backend {
// @public (undocumented)
export const cacheServiceFactory: () => ServiceFactory<CacheClient, 'plugin'>;
// @public (undocumented)
export interface ConfigFactoryOptions {
argv?: string[];
remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>;
}
// @public (undocumented)
export const configServiceFactory: (
options?: ConfigFactoryOptions | undefined,
) => ServiceFactory<ConfigService, 'root'>;
// @public (undocumented)
export function createConfigSecretEnumerator(options: {
logger: LoggerService;
@@ -92,7 +81,7 @@ export function createSpecializedBackend(
// @public (undocumented)
export interface CreateSpecializedBackendOptions {
// (undocumented)
services: ServiceFactoryOrFunction[];
defaultServiceFactories: ServiceFactoryOrFunction[];
}
// @public (undocumented)
@@ -224,7 +213,7 @@ export interface MiddlewareFactoryErrorOptions {
// @public
export interface MiddlewareFactoryOptions {
// (undocumented)
config: ConfigService;
config: RootConfigService;
// (undocumented)
logger: LoggerService;
}
@@ -244,12 +233,23 @@ export function readHelmetOptions(config?: Config): HelmetOptions;
// @public
export function readHttpServerOptions(config?: Config): HttpServerOptions;
// @public (undocumented)
export interface RootConfigFactoryOptions {
argv?: string[];
remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>;
}
// @public (undocumented)
export const rootConfigServiceFactory: (
options?: RootConfigFactoryOptions | undefined,
) => ServiceFactory<RootConfigService, 'root'>;
// @public (undocumented)
export interface RootHttpRouterConfigureContext {
// (undocumented)
app: Express_2;
// (undocumented)
config: ConfigService;
config: RootConfigService;
// (undocumented)
lifecycle: LifecycleService;
// (undocumented)
+19 -4
View File
@@ -1,17 +1,30 @@
{
"name": "@backstage/backend-app-api",
"description": "Core API used by Backstage backend apps",
"version": "0.4.6-next.0",
"version": "0.5.0",
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
"access": "public"
},
"backstage": {
"role": "node-library"
},
"exports": {
".": "./src/index.ts",
"./alpha": "./src/alpha.ts",
"./package.json": "./package.json"
},
"typesVersions": {
"*": {
"alpha": [
"src/alpha.ts"
],
"package.json": [
"package.json"
]
}
},
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -36,6 +49,7 @@
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/backend-tasks": "workspace:^",
"@backstage/cli-common": "workspace:^",
"@backstage/cli-node": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/config-loader": "workspace:^",
"@backstage/errors": "workspace:^",
@@ -73,6 +87,7 @@
"@types/node-forge": "^1.3.0",
"@types/stoppable": "^1.1.0",
"http-errors": "^2.0.0",
"mock-fs": "^5.2.0",
"supertest": "^6.1.3"
},
"files": [
+17
View File
@@ -0,0 +1,17 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { featureDiscoveryServiceFactory } from './alpha/featureDiscoveryServiceFactory';
@@ -0,0 +1,114 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import mockFs from 'mock-fs';
import { resolve as resolvePath, dirname } from 'path';
import { startTestBackend, mockServices } from '@backstage/backend-test-utils';
import { featureDiscoveryServiceFactory } from './featureDiscoveryServiceFactory';
import {
coreServices,
createServiceFactory,
} from '@backstage/backend-plugin-api';
const rootDir = dirname(process.argv[1]);
describe('featureDiscoveryServiceFactory', () => {
beforeEach(() => {
mockFs({
[rootDir]: {
'package.json': JSON.stringify({
name: 'example-app',
dependencies: {
'detected-plugin': '0.0.0',
'detected-module': '0.0.0',
},
}),
},
[resolvePath(rootDir, 'node_modules/detected-plugin')]: {
'package.json': JSON.stringify({
name: 'detected-plugin',
main: 'index.js',
backstage: {
role: 'backend-plugin',
},
}),
'index.js': `
const { createBackendPlugin, coreServices } = require('@backstage/backend-plugin-api');
exports.detectedPlugin = createBackendPlugin({
pluginId: 'detected',
register(env) {
env.registerInit({
deps: { identity: coreServices.identity },
async init({ identity }) {
identity.getIdentity('detected-plugin');
},
});
},
});
`,
},
[resolvePath(rootDir, 'node_modules/detected-module')]: {
'package.json': JSON.stringify({
name: 'detected-module',
main: 'index.js',
backstage: {
role: 'backend-module',
},
}),
'index.js': `
const { createBackendModule, coreServices } = require('@backstage/backend-plugin-api');
exports.detectedModuleDerp = createBackendModule({
pluginId: 'detected',
moduleId: 'derp',
register(env) {
env.registerInit({
deps: { identity: coreServices.identity },
async init({ identity }) {
identity.getIdentity('detected-module');
},
});
},
});
`,
},
});
});
afterEach(() => {
mockFs.restore();
});
it('should detect plugin and module packages', async () => {
const fn = jest.fn().mockResolvedValue({});
await startTestBackend({
features: [
createServiceFactory({
service: coreServices.identity,
deps: {},
factory: () => ({ getIdentity: fn }),
}),
featureDiscoveryServiceFactory(),
mockServices.rootConfig.factory({
data: { backend: { packages: 'all' } },
}),
],
});
expect(fn).toHaveBeenCalledWith('detected-plugin');
expect(fn).toHaveBeenCalledWith('detected-module');
});
});
@@ -0,0 +1,129 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
BackendFeature,
RootConfigService,
coreServices,
createServiceFactory,
} from '@backstage/backend-plugin-api';
import {
featureDiscoveryServiceRef,
FeatureDiscoveryService,
} from '@backstage/backend-plugin-api/alpha';
import { resolve as resolvePath, dirname } from 'path';
import fs from 'fs-extra';
import { BackstagePackageJson } from '@backstage/cli-node';
const LOADED_PACKAGE_ROLES = ['backend-plugin', 'backend-module'];
/** @internal */
async function findClosestPackageDir(
searchDir: string,
): Promise<string | undefined> {
let path = searchDir;
// Some confidence check to avoid infinite loop
for (let i = 0; i < 1000; i++) {
const packagePath = resolvePath(path, 'package.json');
const exists = await fs.pathExists(packagePath);
if (exists) {
return path;
}
const newPath = dirname(path);
if (newPath === path) {
return undefined;
}
path = newPath;
}
throw new Error(
`Iteration limit reached when searching for root package.json at ${searchDir}`,
);
}
/** @internal */
class PackageDiscoveryService implements FeatureDiscoveryService {
constructor(private readonly config: RootConfigService) {}
async getBackendFeatures(): Promise<{ features: Array<BackendFeature> }> {
if (this.config.getOptionalString('backend.packages') !== 'all') {
return { features: [] };
}
const packageDir = await findClosestPackageDir(process.argv[1]);
if (!packageDir) {
throw new Error('Package discovery failed to find package.json');
}
const { dependencies } = require(resolvePath(
packageDir,
'package.json',
)) as BackstagePackageJson;
const dependencyNames = Object.keys(dependencies || {});
const features: BackendFeature[] = [];
for (const name of dependencyNames) {
const depPkg = require(require.resolve(`${name}/package.json`, {
paths: [packageDir],
})) as BackstagePackageJson;
if (!LOADED_PACKAGE_ROLES.includes(depPkg?.backstage?.role ?? '')) {
continue;
}
const depModule = require(require.resolve(name, { paths: [packageDir] }));
for (const exportValue of Object.values(depModule)) {
if (isBackendFeature(exportValue)) {
features.push(exportValue);
}
if (isBackendFeatureFactory(exportValue)) {
features.push(exportValue());
}
}
}
return { features };
}
}
/** @alpha */
export const featureDiscoveryServiceFactory = createServiceFactory({
service: featureDiscoveryServiceRef,
deps: {
config: coreServices.rootConfig,
},
factory({ config }) {
return new PackageDiscoveryService(config);
},
});
function isBackendFeature(value: unknown): value is BackendFeature {
return (
!!value &&
typeof value === 'object' &&
(value as BackendFeature).$$type === '@backstage/BackendFeature'
);
}
function isBackendFeatureFactory(
value: unknown,
): value is () => BackendFeature {
return (
!!value &&
typeof value === 'function' &&
(value as any).$$type === '@backstage/BackendFeatureFactory'
);
}
@@ -14,12 +14,11 @@
* limitations under the License.
*/
import { ConfigService } from '@backstage/backend-plugin-api';
import { ConfigReader } from '@backstage/config';
import { Config, ConfigReader } from '@backstage/config';
import { JsonValue } from '@backstage/types';
export class ObservableConfigProxy implements ConfigService {
private config: ConfigService = new ConfigReader({});
export class ObservableConfigProxy implements Config {
private config: Config = new ConfigReader({});
private readonly subscribers: (() => void)[] = [];
@@ -32,7 +31,7 @@ export class ObservableConfigProxy implements ConfigService {
}
}
setConfig(config: ConfigService) {
setConfig(config: Config) {
if (this.parent) {
throw new Error('immutable');
}
@@ -62,9 +61,9 @@ export class ObservableConfigProxy implements ConfigService {
};
}
private select(required: true): ConfigService;
private select(required: false): ConfigService | undefined;
private select(required: boolean): ConfigService | undefined {
private select(required: true): Config;
private select(required: false): Config | undefined;
private select(required: boolean): Config | undefined {
if (this.parent && this.parentKey) {
if (required) {
return this.parent.select(true).getConfig(this.parentKey);
@@ -87,19 +86,19 @@ export class ObservableConfigProxy implements ConfigService {
getOptional<T = JsonValue>(key?: string): T | undefined {
return this.select(false)?.getOptional(key);
}
getConfig(key: string): ConfigService {
getConfig(key: string): Config {
return new ObservableConfigProxy(this, key);
}
getOptionalConfig(key: string): ConfigService | undefined {
getOptionalConfig(key: string): Config | undefined {
if (this.select(false)?.has(key)) {
return new ObservableConfigProxy(this, key);
}
return undefined;
}
getConfigArray(key: string): ConfigService[] {
getConfigArray(key: string): Config[] {
return this.select(true).getConfigArray(key);
}
getOptionalConfigArray(key: string): ConfigService[] | undefined {
getOptionalConfigArray(key: string): Config[] | undefined {
return this.select(false)?.getOptionalConfigArray(key);
}
getNumber(key: string): number {
@@ -14,7 +14,10 @@
* limitations under the License.
*/
import { ConfigService, LoggerService } from '@backstage/backend-plugin-api';
import {
RootConfigService,
LoggerService,
} from '@backstage/backend-plugin-api';
import {
Request,
Response,
@@ -47,7 +50,7 @@ import { NotImplementedError } from '@backstage/errors';
* @public
*/
export interface MiddlewareFactoryOptions {
config: ConfigService;
config: RootConfigService;
logger: LoggerService;
}
@@ -78,7 +81,7 @@ export interface MiddlewareFactoryErrorOptions {
* @public
*/
export class MiddlewareFactory {
#config: ConfigService;
#config: RootConfigService;
#logger: LoggerService;
/**
@@ -0,0 +1,245 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DependencyGraph } from './DependencyGraph';
describe('DependencyGraph', () => {
it('should be empty', async () => {
const empty = DependencyGraph.fromMap({});
expect(empty.findUnsatisfiedDeps()).toEqual([]);
expect(empty.detectCircularDependency()).toBeUndefined();
await expect(
empty.parallelTopologicalTraversal(async id => id),
).resolves.toEqual([]);
});
describe('detectCircularDependency', () => {
it('should return undefined with not deps', () => {
expect(
DependencyGraph.fromMap({
1: {},
2: {},
3: {},
4: {},
}).detectCircularDependency(),
).toBeUndefined();
});
it('should return undefined with no circular deps', async () => {
expect(
DependencyGraph.fromMap({
1: { provides: ['a'] },
2: { consumes: ['a'], provides: ['b', 'c'] },
3: { consumes: ['b'] },
4: { consumes: ['c'] },
}).detectCircularDependency(),
).toBeUndefined();
});
it('should detect an immediate circular dep', async () => {
expect(
DependencyGraph.fromMap({
1: { provides: ['a'], consumes: ['a'] },
}).detectCircularDependency(),
).toEqual(['1', '1']);
});
it('should detect a small circular dep', async () => {
expect(
DependencyGraph.fromMap({
1: { provides: ['a'], consumes: ['b'] },
2: { provides: ['b'], consumes: ['a'] },
}).detectCircularDependency(),
).toEqual(['1', '2', '1']);
});
it('should detect a larger distant circular dep', async () => {
expect(
DependencyGraph.fromMap({
1: { provides: ['a'] },
2: { provides: ['b'], consumes: ['a', 'e'] },
3: { provides: ['c'], consumes: ['b'] },
4: { provides: ['d', 'e'], consumes: ['c', 'a'] },
}).detectCircularDependency(),
).toEqual(['2', '3', '4', '2']);
});
});
describe('findUnsatisfiedDeps', () => {
it('should return nothing with no deps', () => {
expect(
DependencyGraph.fromMap({
1: {},
2: {},
3: {},
4: {},
}).findUnsatisfiedDeps(),
).toEqual([]);
});
it('should return nothing when all deps are satisfied', async () => {
expect(
DependencyGraph.fromMap({
1: { provides: ['a'] },
2: { consumes: ['a'], provides: ['b', 'c'] },
3: { consumes: ['b'] },
4: { consumes: ['c'] },
}).findUnsatisfiedDeps(),
).toEqual([]);
});
it('should find a single unsatisfied dep', async () => {
expect(
DependencyGraph.fromMap({
1: { consumes: ['a'] },
}).findUnsatisfiedDeps(),
).toEqual([{ value: '1', unsatisfied: ['a'] }]);
});
it('should handle circular dependencies', async () => {
expect(
DependencyGraph.fromMap({
1: { consumes: ['a'], provides: ['a'] },
}).findUnsatisfiedDeps(),
).toEqual([]);
expect(
DependencyGraph.fromMap({
1: { consumes: ['a'], provides: ['b'] },
2: { consumes: ['b'], provides: ['a'] },
}).findUnsatisfiedDeps(),
).toEqual([]);
expect(
DependencyGraph.fromMap({
1: { consumes: ['a'] },
2: { consumes: ['b'], provides: ['c'] },
3: { consumes: ['c'], provides: ['a', 'b'] },
}).findUnsatisfiedDeps(),
).toEqual([]);
});
it('should find multiple unsatisfied deps for one node', async () => {
expect(
DependencyGraph.fromMap({
1: { provides: ['a'], consumes: ['b'] },
2: { provides: ['b'], consumes: ['a', 'd', 'e'] },
}).findUnsatisfiedDeps(),
).toEqual([{ value: '2', unsatisfied: ['d', 'e'] }]);
});
it('should find multiple unsatisfied deps for multiple nodes', async () => {
expect(
DependencyGraph.fromMap({
1: { provides: ['a'] },
2: { provides: ['b'], consumes: ['a', 'd', 'e'] },
3: { provides: [], consumes: ['b'] },
4: { provides: [], consumes: ['c', 'a'] },
}).findUnsatisfiedDeps(),
).toEqual([
{ value: '2', unsatisfied: ['d', 'e'] },
{ value: '4', unsatisfied: ['c'] },
]);
});
});
describe('parallelTopologicalTraversal', () => {
it('should traverse with no deps', async () => {
await expect(
DependencyGraph.fromMap({
1: {},
2: {},
3: {},
4: {},
}).parallelTopologicalTraversal(async id => id),
).resolves.toEqual(['1', '2', '3', '4']);
});
it('should traverse with a few deps', async () => {
await expect(
DependencyGraph.fromMap({
1: { provides: ['a'] },
2: { consumes: ['a'], provides: ['b', 'c'] },
3: { consumes: ['b'] },
4: { consumes: ['c'] },
}).parallelTopologicalTraversal(async id => id),
).resolves.toEqual(['1', '2', '3', '4']);
});
it('should traverse in reverse', async () => {
await expect(
DependencyGraph.fromMap({
1: { consumes: ['c'] },
2: { provides: ['c'], consumes: ['b'] },
3: { provides: ['b'], consumes: ['a'] },
4: { provides: ['a'] },
}).parallelTopologicalTraversal(async id => id),
).resolves.toEqual(['4', '3', '2', '1']);
});
it('should execute in parallel', async () => {
await expect(
DependencyGraph.fromMap({
1: { provides: ['a'] },
2: { provides: ['b'], consumes: ['a'] },
3: { provides: ['c'], consumes: ['a'] },
4: { consumes: ['b'] },
5: { consumes: ['c'] },
}).parallelTopologicalTraversal(async id => id),
).resolves.toEqual(['1', '2', '3', '4', '5']);
// Same as above, but with 2 being delayed
await expect(
DependencyGraph.fromMap({
1: { provides: ['a'] },
2: { provides: ['b'], consumes: ['a'] },
3: { provides: ['c'], consumes: ['a'] },
4: { consumes: ['b'] },
5: { consumes: ['c'] },
}).parallelTopologicalTraversal(async id => {
// When delaying 2 we expect 3 and 5 to complete before 2 and 4
if (id === '2') {
await new Promise(resolve => setTimeout(resolve, 100));
}
return id;
}),
).resolves.toEqual(['1', '3', '5', '2', '4']);
});
it('should detect circular dependencies', async () => {
await expect(
DependencyGraph.fromMap({
1: { provides: ['a'], consumes: ['a'] },
}).parallelTopologicalTraversal(async id => id),
).rejects.toThrow('Circular dependency detected');
await expect(
DependencyGraph.fromMap({
1: { provides: ['a'], consumes: ['b'] },
2: { provides: ['b'], consumes: ['a'] },
}).parallelTopologicalTraversal(async id => id),
).rejects.toThrow('Circular dependency detected');
await expect(
DependencyGraph.fromMap({
1: { provides: ['a'] },
2: { provides: ['c'], consumes: ['a', 'b'] },
3: { provides: ['b'], consumes: ['a', 'c'] },
}).parallelTopologicalTraversal(async id => id),
).rejects.toThrow('Circular dependency detected');
});
});
});
@@ -0,0 +1,197 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
interface NodeInput<T> {
value: T;
consumes?: Iterable<string>;
provides?: Iterable<string>;
}
/** @internal */
class Node<T> {
static from<T>(input: NodeInput<T>) {
return new Node<T>(
input.value,
input.consumes ? new Set(input.consumes) : new Set(),
input.provides ? new Set(input.provides) : new Set(),
);
}
private constructor(
readonly value: T,
readonly consumes: Set<string>,
readonly provides: Set<string>,
) {}
}
/**
* Internal helper to help validate and traverse a dependency graph.
* @internal
*/
export class DependencyGraph<T> {
static fromMap(
nodes: Record<string, Omit<NodeInput<unknown>, 'value'>>,
): DependencyGraph<string> {
return this.fromIterable(
Object.entries(nodes).map(([key, node]) => ({
value: String(key),
...node,
})),
);
}
static fromIterable<T>(
nodeInputs: Iterable<NodeInput<T>>,
): DependencyGraph<T> {
const nodes = new Array<Node<T>>();
for (const nodeInput of nodeInputs) {
nodes.push(Node.from(nodeInput));
}
return new DependencyGraph(nodes);
}
#nodes: Array<Node<T>>;
#allProvided: Set<string>;
private constructor(nodes: Array<Node<T>>) {
this.#nodes = nodes;
this.#allProvided = new Set();
for (const node of this.#nodes.values()) {
for (const produced of node.provides) {
this.#allProvided.add(produced);
}
}
}
// Find all nodes that consume dependencies that are not provided by any other node
findUnsatisfiedDeps(): Array<{ value: T; unsatisfied: string[] }> {
const unsatisfiedDependencies = [];
for (const node of this.#nodes.values()) {
const unsatisfied = Array.from(node.consumes).filter(
id => !this.#allProvided.has(id),
);
if (unsatisfied.length > 0) {
unsatisfiedDependencies.push({ value: node.value, unsatisfied });
}
}
return unsatisfiedDependencies;
}
// Detect circular dependencies within the graph, returning the path of nodes that
// form a cycle, with the same node as the first and last element of the array.
detectCircularDependency(): T[] | undefined {
for (const startNode of this.#nodes) {
const visited = new Set<Node<T>>();
const stack = new Array<[node: Node<T>, path: T[]]>([
startNode,
[startNode.value],
]);
while (stack.length > 0) {
const [node, path] = stack.pop()!;
if (visited.has(node)) {
continue;
}
visited.add(node);
for (const produced of node.provides) {
const consumerNodes = this.#nodes.filter(other =>
other.consumes.has(produced),
);
for (const consumer of consumerNodes) {
if (consumer === startNode) {
return [...path, startNode.value];
}
if (!visited.has(consumer)) {
stack.push([consumer, [...path, consumer.value]]);
}
}
}
}
}
return undefined;
}
/**
* Traverses the dependency graph in topological order, calling the provided
* function for each node and waiting for it to resolve.
*
* The nodes are traversed in parallel, but in such a way that no node is
* visited before all of its dependencies.
*
* Dependencies of nodes that are not produced by any other nodes will be ignored.
*/
async parallelTopologicalTraversal<TResult>(
fn: (value: T) => Promise<TResult>,
): Promise<TResult[]> {
const allProvided = this.#allProvided;
const producedSoFar = new Set<string>();
const waiting = new Set(this.#nodes.values());
const visited = new Set<Node<T>>();
const results = new Array<TResult>();
let inFlight = 0; // Keep track of how many callbacks are in flight, so that we know if we got stuck
// Find all nodes that have no dependencies that have not already been produced by visited nodes
async function processMoreNodes() {
if (waiting.size === 0) {
return;
}
const nodesToProcess = [];
for (const node of waiting) {
let ready = true;
for (const consumed of node.consumes) {
if (allProvided.has(consumed) && !producedSoFar.has(consumed)) {
ready = false;
continue;
}
}
if (ready) {
nodesToProcess.push(node);
}
}
for (const node of nodesToProcess) {
waiting.delete(node);
}
if (nodesToProcess.length === 0 && inFlight === 0) {
// We expect the caller to check for circular dependencies before
// traversal, so this error should never happen
throw new Error('Circular dependency detected');
}
await Promise.all(nodesToProcess.map(processNode));
}
// Process an individual node, and then add its produced dependencies to the set of available products
async function processNode(node: Node<T>) {
visited.add(node);
inFlight += 1;
const result = await fn(node.value);
results.push(result);
node.provides.forEach(produced => producedSoFar.add(produced));
inFlight -= 1;
await processMoreNodes();
}
await processMoreNodes();
return results;
}
}
@@ -24,7 +24,7 @@ import {
export const cacheServiceFactory = createServiceFactory({
service: coreServices.cache,
deps: {
config: coreServices.config,
config: coreServices.rootConfig,
plugin: coreServices.pluginMetadata,
},
async createRootContext({ config }) {
@@ -14,5 +14,5 @@
* limitations under the License.
*/
export { configServiceFactory } from './configServiceFactory';
export type { ConfigFactoryOptions } from './configServiceFactory';
export { rootConfigServiceFactory } from './rootConfigServiceFactory';
export type { RootConfigFactoryOptions } from './rootConfigServiceFactory';
@@ -24,7 +24,7 @@ import {
} from '@backstage/config-loader';
/** @public */
export interface ConfigFactoryOptions {
export interface RootConfigFactoryOptions {
/**
* Process arguments to use instead of the default `process.argv()`.
*/
@@ -37,9 +37,9 @@ export interface ConfigFactoryOptions {
}
/** @public */
export const configServiceFactory = createServiceFactory(
(options?: ConfigFactoryOptions) => ({
service: coreServices.config,
export const rootConfigServiceFactory = createServiceFactory(
(options?: RootConfigFactoryOptions) => ({
service: coreServices.rootConfig,
deps: {},
async factory() {
const source = ConfigSources.default({
@@ -25,7 +25,7 @@ import { ConfigReader } from '@backstage/config';
export const databaseServiceFactory = createServiceFactory({
service: coreServices.database,
deps: {
config: coreServices.config,
config: coreServices.rootConfig,
lifecycle: coreServices.lifecycle,
pluginMetadata: coreServices.pluginMetadata,
},
@@ -24,7 +24,7 @@ import {
export const discoveryServiceFactory = createServiceFactory({
service: coreServices.discovery,
deps: {
config: coreServices.config,
config: coreServices.rootConfig,
},
async factory({ config }) {
return HostDiscovery.fromConfig(config);
@@ -24,7 +24,7 @@ import { ServerPermissionClient } from '@backstage/plugin-permission-node';
export const permissionsServiceFactory = createServiceFactory({
service: coreServices.permissions,
deps: {
config: coreServices.config,
config: coreServices.rootConfig,
discovery: coreServices.discovery,
tokenManager: coreServices.tokenManager,
},
@@ -15,7 +15,7 @@
*/
import {
ConfigService,
RootConfigService,
coreServices,
createServiceFactory,
LifecycleService,
@@ -36,7 +36,7 @@ export interface RootHttpRouterConfigureContext {
app: Express;
middleware: MiddlewareFactory;
routes: RequestHandler;
config: ConfigService;
config: RootConfigService;
logger: LoggerService;
lifecycle: LifecycleService;
}
@@ -70,7 +70,7 @@ export const rootHttpRouterServiceFactory = createServiceFactory(
(options?: RootHttpRouterFactoryOptions) => ({
service: coreServices.rootHttpRouter,
deps: {
config: coreServices.config,
config: coreServices.rootConfig,
rootLogger: coreServices.rootLogger,
lifecycle: coreServices.rootLifecycle,
},
@@ -26,7 +26,7 @@ import { createConfigSecretEnumerator } from '../../../config';
export const rootLoggerServiceFactory = createServiceFactory({
service: coreServices.rootLogger,
deps: {
config: coreServices.config,
config: coreServices.rootConfig,
},
async factory({ config }) {
const logger = WinstonLogger.create({
@@ -61,8 +61,7 @@ describe('schedulerFactory', () => {
});
await startTestBackend({
features: [plugin()],
services: [subject],
features: [plugin(), subject],
});
});
});

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