Merge branch 'master' into scalable-sidebar-new-implementation
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes': patch
|
||||
---
|
||||
|
||||
The Kubernetes plugin will now re-fetch the kubernetes objects every ten seconds (not current configurable), this allows users to track the progress of deployments without refreshing the browser.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-sentry': patch
|
||||
---
|
||||
|
||||
feature: sentry-plugin allows passing search query for listing issues
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
'@backstage/test-utils': patch
|
||||
'@backstage/test-utils-core': patch
|
||||
---
|
||||
|
||||
Migrates all utility methods from `test-utils-core` into `test-utils` and delete exports from the old package.
|
||||
This should have no impact since this package is considered internal and have no usages outside core packages.
|
||||
|
||||
Notable changes are that the testing tool `msw.setupDefaultHandlers()` have been deprecated in favour of `setupRequestMockHandlers()`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
Reader will now scroll to the top of the page when navigating between pages
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Surfacing all components of the ScaffolderPage outside of the plugin so you can customize the page
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
'@backstage/plugin-azure-devops': patch
|
||||
---
|
||||
|
||||
Azure DevOps frontend refactoring items from issue #7641
|
||||
|
||||
- Remove backend setup documentation and linked to the Azure DevOps backend plugin for these instructions
|
||||
- Improved documentation to be easier to expand with new features in the future
|
||||
- Removed Router based on feedback from maintainers
|
||||
- Added tests for `getBuildResultComponent` and `getBuildStateComponent` from the BuildTable
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Scaffolder: Enable back Template action buttons if template fails to execute
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-graphiql': patch
|
||||
---
|
||||
|
||||
Add experimental `experimentalInstallationRecipe` to `package.json`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
add a --from <location> option to the plugin install command
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-azure-devops-backend': patch
|
||||
---
|
||||
|
||||
Added duration (startTime and finishTime) and identity (uniqueName) to the RepoBuild results. Also did a bit of refactoring to help finish up the backend items in issue #7641
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': minor
|
||||
---
|
||||
|
||||
This continues the deprecation of classes used by the legacy catalog engine. New deprecations can be viewed in this [PR](https://github.com/backstage/backstage/pull/7500) or in the API reference documentation.
|
||||
|
||||
The `batchAddOrUpdateEntities` method of the `EntitiesCatalog` interface has been marked as optional and is being deprecated. It is still implemented and required to be implemented by the legacy catalog classes, but was never implemented in the new catalog.
|
||||
|
||||
This change is only relevant if you are consuming the `EntitiesCatalog` interface directly, in which case you will get a type error that you need to resolve. It can otherwise be ignored.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Bump sucrase to version 3.20.2
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': patch
|
||||
---
|
||||
|
||||
Added extra configuration parameters for active directory file system identity
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
'@backstage/catalog-model': patch
|
||||
'@backstage/cli': patch
|
||||
'@backstage/config-loader': patch
|
||||
'@backstage/core-app-api': patch
|
||||
'@backstage/errors': patch
|
||||
'@backstage/search-common': patch
|
||||
'@backstage/test-utils': patch
|
||||
'@backstage/plugin-app-backend': patch
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
'@backstage/plugin-catalog-backend-module-ldap': patch
|
||||
'@backstage/plugin-catalog-graphql': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-config-schema': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch
|
||||
'@backstage/plugin-scaffolder-backend-module-rails': patch
|
||||
'@backstage/plugin-scaffolder-backend-module-yeoman': patch
|
||||
'@backstage/plugin-scaffolder-common': patch
|
||||
'@backstage/plugin-search': patch
|
||||
'@backstage/plugin-shortcuts': patch
|
||||
---
|
||||
|
||||
Switch to use the json and observable types from `@backstage/types`
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-code-coverage-backend': patch
|
||||
---
|
||||
|
||||
check for existence of lines property in files
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/techdocs-common': patch
|
||||
---
|
||||
|
||||
Support optional bucketRootPath configuration parameter in S3 and GCS publishers
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'@backstage/config': patch
|
||||
'@backstage/core-app-api': patch
|
||||
'@backstage/core-plugin-api': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Start using the new `@backstage/types` package. Initially, this means using the `Observable` and `Json*` types from there. The types also remain in their old places but deprecated, and will be removed in a future release.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/config': patch
|
||||
'@backstage/core-app-api': patch
|
||||
'@backstage/core-plugin-api': patch
|
||||
---
|
||||
|
||||
Replace usage of test-utils-core with test-utils
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search-backend-node': patch
|
||||
---
|
||||
|
||||
Handle special case when filter array has single value optimizing Lunr search behaviour.
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Add an experimental `install <plugin>` command.
|
||||
|
||||
Given a `pluginId`, the command looks for NPM packages matching `@backstage/plugin-{pluginId}` or `backstage-plugin-{pluginId}` or `{pluginId}`. It looks for the `experimentalInstallationRecipe` in their `package.json` for the steps of installation. Detailed documentation and API Spec to follow (and to be decided as well).
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-sentry': patch
|
||||
---
|
||||
|
||||
fix: sentry-plugin correction for allowed period values
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Deprecated `DismissbleBannerClassKey` and fixed the typo to make `DismissableBannerClassKey`
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/errors': patch
|
||||
---
|
||||
|
||||
Add `stringifyError` that is useful for logging e.g. `Something went wrong, ${stringifyError(e)}`
|
||||
@@ -8,6 +8,7 @@ apis
|
||||
args
|
||||
asciidoc
|
||||
async
|
||||
Atlassian
|
||||
automations
|
||||
autoscaling
|
||||
Autoscaling
|
||||
@@ -310,3 +311,4 @@ Zalando
|
||||
Zhou
|
||||
zoomable
|
||||
zsh
|
||||
Firestore
|
||||
|
||||
@@ -140,7 +140,7 @@ jobs:
|
||||
|
||||
- name: test changed packages
|
||||
if: ${{ steps.yarn-lock.outcome == 'success' }}
|
||||
run: yarn lerna -- run test --since origin/master -- --coverage
|
||||
run: yarn lerna -- run test --since origin/master -- --coverage --runInBand
|
||||
env:
|
||||
BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres13.ports[5432] }}
|
||||
BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres9.ports[5432] }}
|
||||
@@ -149,7 +149,7 @@ jobs:
|
||||
- name: test all packages (and upload coverage)
|
||||
if: ${{ steps.yarn-lock.outcome == 'failure' }}
|
||||
run: |
|
||||
yarn lerna -- run test -- --coverage
|
||||
yarn lerna -- run test -- --coverage --runInBand
|
||||
bash <(curl -s https://codecov.io/bash) -N $(git rev-parse FETCH_HEAD)
|
||||
env:
|
||||
BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres13.ports[5432] }}
|
||||
|
||||
@@ -116,7 +116,7 @@ jobs:
|
||||
|
||||
- name: test (and upload coverage)
|
||||
run: |
|
||||
yarn lerna -- run test -- --coverage
|
||||
yarn lerna -- run test -- --coverage --runInBand
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
# Upload code coverage for some specific flags. Also see .codecov.yml
|
||||
bash <(curl -s https://codecov.io/bash) -f packages/core-app-api/coverage/* -F core-app-api
|
||||
|
||||
+61
-56
@@ -1,56 +1,61 @@
|
||||
| Organization | Contact | Description of Use |
|
||||
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. |
|
||||
| [bol.com](https://www.bol.com) | [@sagacity](https://github.com/sagacity) | Initial work being done to unify platform tooling. |
|
||||
| [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. |
|
||||
| [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up |
|
||||
| [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. |
|
||||
| [SDA SE](https://sda.se) | [@Fox32](https://github.com/Fox32) | Central place for developing and sharing services in our insurance ecosystem. |
|
||||
| [H-E-B](https://www.heb.com) | [@german-j-rodriguez](https://github.com/german-j-rodriguez) | Initial work on Engineering Portal service platform. |
|
||||
| [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications |
|
||||
| [Kiwi.com](https://kiwi.com) | [@aexvir](https://github.com/aexvir) | Replacing the frontend of [The Zoo](https://github.com/kiwicom/the-zoo), their service registry. |
|
||||
| [Voi](https://www.voiscooters.com/) | [@K-Phoen](https://github.com/K-Phoen) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. |
|
||||
| [Talkdesk](https://www.talkdesk.com) | [@jaime-talkdesk](https://github.com/jaime-talkdesk) | Initial work for Engineering Portal and Self Provisioning to R&D |
|
||||
| [Wealthsimple](https://www.wealthsimple.com) | [@andrewthauer](https://github.com/andrewthauer) | Developer portal, service catalog, documentation and tooling |
|
||||
| [Grab](https://www.grab.com) | [@althafh](https://github.com/althafh) | Initial work as a unified interface for all of Grab's internal tooling |
|
||||
| [Telenor Sweden](https://www.telenor.se) | [@O5ten](https://github.com/O5ten) | Building a developer portal for scaffolding projects towards our unified build environment and microservice stacks |
|
||||
| [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. |
|
||||
| [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. |
|
||||
| [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. |
|
||||
| [Expedia Group](https://www.expediagroup.com) | [Mike Turner](mailto:miturner@expediagroup.com), [Sneha Kumar](mailto:snkumar@expediagroup.com), [@guillermomanzo](https://github.com/guillermomanzo), [Erik Lindgren](https://github.com/lindgren) | EG Common Developer Toolkit |
|
||||
| [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go |
|
||||
| [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling |
|
||||
| [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. |
|
||||
| [Trendyol](https://trendyol.com) | [Gamze Senturk](https://github.com/gmzsenturk), [Mert Can Bilgic](https://github.com/mertcb) | The Developer Portal has been called `Pandora`. Provides an overview of Trendyol tech ecosystem. TechDocs, Catalog, Custom Plugins and Theme. |
|
||||
| [Peloton](https://www.onepeloton.com/) | [Jim Haughwout](https://github.com/JimHaughwout) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. |
|
||||
| [TELUS](https://telus.com) | [Seb Barre](https://github.com/sbarre) | The Go-to place to find answers about development and delivery at TELUS. |
|
||||
| [Brex](https://www.brex.com/) | [Vamsi Chitters](https://github.com/vamsikc) | A centralized UI to understand how a service fits in the whole Brex architecture and manage a team’s engineering dependencies. |
|
||||
| [Oriflame](https://www.oriflame.com/) | [Oriflame](https://github.com/oriflame) | Internal developer portal for services, single page apps and packages overview, API documentation, technical guides, tech-radar and more. |
|
||||
| [Booz Allen Hamilton](https://www.boozallen.com/) | [Jason Miller](https://github.com/JasonMiller-BAH) | Developer portal for a full-stack software development ecosystem that accelerates consistent and repeatable Modern Software Development practices for internal innovation and investments. |
|
||||
| [Netflix](https://www.netflix.com/) | [bleathem](https://github.com/bleathem) | Our Backstage implementation will be the front door to a unified experience connecting our internal platform products across important workflows with integrated knowledge and support. |
|
||||
| [b.well](https://www.icanbwell.com/) | [Jacob Rosales](https://github.com/jrosales) | Foundation for our engineering portal and cloud insights. |
|
||||
| [PagerDuty](https://www.pagerduty.com/) | [Mark Shaw](https://github.com/markshawtoronto) | Developer portal, initially focused on software templates and tech-docs. |
|
||||
| [MoonShiner](https://moonshiner.at) | [Fabian Hippmann](https://github.com/FabianHippmann) | Developer portal - helps us keep track of our customer projects, onboard new developers & improve our development process 🌕🚀🧑🚀 |
|
||||
| [FundApps](https://www.fundapps.co/) | [Elliot Greenwood](https://github.com/egnwd) | Developer Portal - A place for us to keep track of our projects and documentation for all services and processes |
|
||||
| [DAZN](https://dazn.com/) | [Lou Bichard](https://twitter.com/loujaybee), [Marco Crivellaro](https://github.com/crivetechie), [Alex Hollerith](mailto:alex.hollerith@dazn.com) | Ingesting all of DAZN's repos for the catalog, migrating our internal platform apps (pull request boards, release information, inner source marketplace etc) to Backstage plugins (where applicable). |
|
||||
| [HelloFresh](https://www.hellofresh.de/) | [@iammuho](https://github.com/iammuho), [@ElenaForester](https://github.com/ElenaForester), [@diegomarangoni](https://github.com/diegomarangoni) | Our developer portal at HelloFresh - Spread across an organisation of 500+ engineers globally. |
|
||||
| [FactSet](https://www.factset.com/) | [@kuangp](https://github.com/kuangp) | Developer portal to provide discoverability to all internal components, APIs, documentation, and scaffold templates with integrations to our internal infrastructure tools. |
|
||||
| [Workrise](https://www.workrise.com/) | [Michael Rode](https://github.com/michaelrode) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. |
|
||||
| [RedVentures](https://www.redventures.com/) | [Chris Diaz](https://github.com/codingdiaz) | Developer portal that brings everything an engineer needs to provide value into a single pane of glass. |
|
||||
| [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. |
|
||||
| [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) | [Andrew Thal](https://github.com/athal7) | Development team home-base, promoting service discoverability, resource dependencies, and tech radar |
|
||||
| [Taxfix](https://taxfix.de/) | [Sami Ur Rehman](https://github.com/samiurrehman92) | Developer's portal with software catalog at it's core. Hosts API Specs, Tech Docs, Tech Radar and some custom plugins. |
|
||||
| [Busuu](https://busuu.com/) | [Adam Tester](https://github.com/adamtester) | Developer portal with service catalog, API docs, Event docs, service templating, and cost insights. |
|
||||
| [Loadsmart](https://loadsmart.com/) | [Loadsmart](https://github.com/loadsmart) | Improve services visibility and operations for service owners and developers. |
|
||||
| [Monzo](https://monzo.com/) | [@WillSewell](https://github.com/WillSewell), [@joechrisellis](https://github.com/joechrisellis) | Developer portal showing metadata and docs for over 2000 microservices. We have built a number of plugins such as a UI for our system to measure [software excellence](https://monzo.com/blog/2021/09/15/how-we-measure-software-excellence), and a UI to show deployment and config change events. |
|
||||
| [Vaimo](https://www.vaimo.com) | [@vaimo-magnus](https://github.com/vaimo-magnus) | Developer Portal for our developers at Vaimo, currently docs and self-service towards our internal PaaS based on k8s. Plans to extend the catalog into Projects, Environments etc |
|
||||
| [Wayfair](https://www.wayfair.com) | [@fransan](https://github.com/fransan), [@errskipower](https://github.com/errskipower), [@hrrs](https://github.com/hrrs) | Developer portal for service catalog, technical documentation, and APIs. |
|
||||
| [CircleHD](https://www.circlehd.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe |
|
||||
| [CastDesk](https://castdesk.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe |
|
||||
| [Santagostino](https://santagostino.it) | [@santagostino](https://github.com/santagostino) | Developer portal, gateway to our infrastructure, documentation, service catalog and internal tooling. |
|
||||
| [Peak](https://peak.ai) | [Luke Beamish](https://github.com/lukebeamish-peak) | Developer portal for all internal engineers to access documentation and tooling. |
|
||||
| Organization | Contact | Description of Use |
|
||||
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. |
|
||||
| [bol.com](https://www.bol.com) | [@sagacity](https://github.com/sagacity) | Initial work being done to unify platform tooling. |
|
||||
| [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. |
|
||||
| [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up |
|
||||
| [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. |
|
||||
| [SDA SE](https://sda.se) | [@Fox32](https://github.com/Fox32) | Central place for developing and sharing services in our insurance ecosystem. |
|
||||
| [H-E-B](https://www.heb.com) | [@german-j-rodriguez](https://github.com/german-j-rodriguez) | Initial work on Engineering Portal service platform. |
|
||||
| [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications |
|
||||
| [Kiwi.com](https://kiwi.com) | [@aexvir](https://github.com/aexvir) | Replacing the frontend of [The Zoo](https://github.com/kiwicom/the-zoo), their service registry. |
|
||||
| [Voi](https://www.voiscooters.com/) | [@K-Phoen](https://github.com/K-Phoen) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. |
|
||||
| [Talkdesk](https://www.talkdesk.com) | [@jaime-talkdesk](https://github.com/jaime-talkdesk) | Initial work for Engineering Portal and Self Provisioning to R&D |
|
||||
| [Wealthsimple](https://www.wealthsimple.com) | [@andrewthauer](https://github.com/andrewthauer) | Developer portal, service catalog, documentation and tooling |
|
||||
| [Grab](https://www.grab.com) | [@althafh](https://github.com/althafh) | Initial work as a unified interface for all of Grab's internal tooling |
|
||||
| [Telenor Sweden](https://www.telenor.se) | [@O5ten](https://github.com/O5ten) | Building a developer portal for scaffolding projects towards our unified build environment and microservice stacks |
|
||||
| [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. |
|
||||
| [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. |
|
||||
| [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. |
|
||||
| [Expedia Group](https://www.expediagroup.com) | [Mike Turner](mailto:miturner@expediagroup.com), [Sneha Kumar](mailto:snkumar@expediagroup.com), [@guillermomanzo](https://github.com/guillermomanzo), [Erik Lindgren](https://github.com/lindgren) | EG Common Developer Toolkit |
|
||||
| [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go |
|
||||
| [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling |
|
||||
| [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. |
|
||||
| [Trendyol](https://trendyol.com) | [Gamze Senturk](https://github.com/gmzsenturk), [Mert Can Bilgic](https://github.com/mertcb) | The Developer Portal has been called `Pandora`. Provides an overview of Trendyol tech ecosystem. TechDocs, Catalog, Custom Plugins and Theme. |
|
||||
| [Peloton](https://www.onepeloton.com/) | [Jim Haughwout](https://github.com/JimHaughwout) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. |
|
||||
| [TELUS](https://telus.com) | [Seb Barre](https://github.com/sbarre) | The Go-to place to find answers about development and delivery at TELUS. |
|
||||
| [Brex](https://www.brex.com/) | [Vamsi Chitters](https://github.com/vamsikc) | A centralized UI to understand how a service fits in the whole Brex architecture and manage a team’s engineering dependencies. |
|
||||
| [Oriflame](https://www.oriflame.com/) | [Oriflame](https://github.com/oriflame) | Internal developer portal for services, single page apps and packages overview, API documentation, technical guides, tech-radar and more. |
|
||||
| [Booz Allen Hamilton](https://www.boozallen.com/) | [Jason Miller](https://github.com/JasonMiller-BAH) | Developer portal for a full-stack software development ecosystem that accelerates consistent and repeatable Modern Software Development practices for internal innovation and investments. |
|
||||
| [Netflix](https://www.netflix.com/) | [bleathem](https://github.com/bleathem) | Our Backstage implementation will be the front door to a unified experience connecting our internal platform products across important workflows with integrated knowledge and support. |
|
||||
| [b.well](https://www.icanbwell.com/) | [Jacob Rosales](https://github.com/jrosales) | Foundation for our engineering portal and cloud insights. |
|
||||
| [PagerDuty](https://www.pagerduty.com/) | [Mark Shaw](https://github.com/markshawtoronto) | Developer portal, initially focused on software templates and tech-docs. |
|
||||
| [MoonShiner](https://moonshiner.at) | [Fabian Hippmann](https://github.com/FabianHippmann) | Developer portal - helps us keep track of our customer projects, onboard new developers & improve our development process 🌕🚀🧑🚀 |
|
||||
| [FundApps](https://www.fundapps.co/) | [Elliot Greenwood](https://github.com/egnwd) | Developer Portal - A place for us to keep track of our projects and documentation for all services and processes |
|
||||
| [DAZN](https://dazn.com/) | [Lou Bichard](https://twitter.com/loujaybee), [Marco Crivellaro](https://github.com/crivetechie), [Alex Hollerith](mailto:alex.hollerith@dazn.com) | Ingesting all of DAZN's repos for the catalog, migrating our internal platform apps (pull request boards, release information, inner source marketplace etc) to Backstage plugins (where applicable). |
|
||||
| [HelloFresh](https://www.hellofresh.de/) | [@iammuho](https://github.com/iammuho), [@ElenaForester](https://github.com/ElenaForester), [@diegomarangoni](https://github.com/diegomarangoni) | Our developer portal at HelloFresh - Spread across an organisation of 500+ engineers globally. |
|
||||
| [FactSet](https://www.factset.com/) | [@kuangp](https://github.com/kuangp) | Developer portal to provide discoverability to all internal components, APIs, documentation, and scaffold templates with integrations to our internal infrastructure tools. |
|
||||
| [Workrise](https://www.workrise.com/) | [Michael Rode](https://github.com/michaelrode) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. |
|
||||
| [RedVentures](https://www.redventures.com/) | [Chris Diaz](https://github.com/codingdiaz) | Developer portal that brings everything an engineer needs to provide value into a single pane of glass. |
|
||||
| [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. |
|
||||
| [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) | [Andrew Thal](https://github.com/athal7) | Development team home-base, promoting service discoverability, resource dependencies, and tech radar |
|
||||
| [Taxfix](https://taxfix.de/) | [Sami Ur Rehman](https://github.com/samiurrehman92) | Developer's portal with software catalog at it's core. Hosts API Specs, Tech Docs, Tech Radar and some custom plugins. |
|
||||
| [Busuu](https://busuu.com/) | [Adam Tester](https://github.com/adamtester) | Developer portal with service catalog, API docs, Event docs, service templating, and cost insights. |
|
||||
| [Loadsmart](https://loadsmart.com/) | [Loadsmart](https://github.com/loadsmart) | Improve services visibility and operations for service owners and developers. |
|
||||
| [Monzo](https://monzo.com/) | [@WillSewell](https://github.com/WillSewell), [@joechrisellis](https://github.com/joechrisellis) | Developer portal showing metadata and docs for over 2000 microservices. We have built a number of plugins such as a UI for our system to measure [software excellence](https://monzo.com/blog/2021/09/15/how-we-measure-software-excellence), and a UI to show deployment and config change events. |
|
||||
| [Vaimo](https://www.vaimo.com) | [@vaimo-magnus](https://github.com/vaimo-magnus) | Developer Portal for our developers at Vaimo, currently docs and self-service towards our internal PaaS based on k8s. Plans to extend the catalog into Projects, Environments etc |
|
||||
| [Wayfair](https://www.wayfair.com) | [@fransan](https://github.com/fransan), [@errskipower](https://github.com/errskipower), [@hrrs](https://github.com/hrrs) | Developer portal for service catalog, technical documentation, and APIs. |
|
||||
| [CircleHD](https://www.circlehd.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe |
|
||||
| [CastDesk](https://castdesk.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe |
|
||||
| [Santagostino](https://santagostino.it) | [@santagostino](https://github.com/santagostino) | Developer portal, gateway to our infrastructure, documentation, service catalog and internal tooling. |
|
||||
| [Peak](https://peak.ai) | [Luke Beamish](https://github.com/lukebeamish-peak) | Developer portal for all internal engineers to access documentation and tooling. |
|
||||
| [Gelato](https://gelato.com/) | [Dmitry Makarenko](https://github.com/dmitry-makarenko-gelato) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal and third-party systems🚀. |
|
||||
| [GoCardless](https://gocardless.com/) | [James Turley](https://github.com/tragiclifestories) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal systems. |
|
||||
| [Box](https://www.box.com) | [@kielosz](https://github.com/kielosz), [@jluk-box](https://github.com/jluk-box), [@ptychu](https://github.com/ptychu), [@alexrybch](https://github.com/alexrybch), [@szubster](https://github.com/szubster) | Developer portal for service catalog, integration with internal systems, new service onboarding. |
|
||||
| [Bazaarvoice](https://www.bazaarvoice.com) | [@niallmccullagh](https://github.com/niallmccullagh) | Developer portal for service catalog and scaffolds, publishing Github docs and API documentation, visualising our internal tech radar and our product engineering org structure. |
|
||||
| [Krateo PlatformOps](https://www.krateo.io) | [@projectkerberus](https://github.com/projectkerberus) | A multi-cloud control plane to create, manage and deploy any kind of resource easily and centrally via a Developer Portal that centralizes via a self-service catalog the templating and ownership of services, the available documentation, the overview of the components that compose an entire domain and all the data of the service lifecycle. |
|
||||
|
||||
+4
-3
@@ -129,9 +129,10 @@ In general, changesets are not needed for the documentation, build utilities, co
|
||||
1. Run `yarn changeset`
|
||||
2. Select which packages you want to include a changeset for
|
||||
3. Select impact of change that you're introducing, using `minor` for breaking changes and `patch` otherwise. We do not use `major` changes while packages are at version `0.x`.
|
||||
4. Add generated changeset to Git
|
||||
5. Push the commit with your changeset to the branch associated with your PR
|
||||
6. Accept our gratitude for making the release process easier on the maintainers
|
||||
4. Explain your changes in the generated changeset. See [examples of well written changesets](https://backstage.io/docs/getting-started/contributors#writing-changesets).
|
||||
5. Add generated changeset to Git
|
||||
6. Push the commit with your changeset to the branch associated with your PR
|
||||
7. Accept our gratitude for making the release process easier on the maintainers
|
||||
|
||||
For more information, checkout [adding a changeset](https://github.com/atlassian/changesets/blob/master/docs/adding-a-changeset.md) documentation in the changesets repository.
|
||||
|
||||
|
||||
@@ -292,6 +292,15 @@ scaffolder:
|
||||
visibility: public # or or 'private'
|
||||
|
||||
auth:
|
||||
### Add auth.keyStore.provider to more granularly control how to store JWK data when running
|
||||
# the auth-backend.
|
||||
#
|
||||
# keyStore:
|
||||
# provider: firestore
|
||||
# firestore:
|
||||
# projectId: my-project
|
||||
# path: my-sessions
|
||||
|
||||
environment: development
|
||||
### Providing an auth.session.secret will enable session support in the auth-backend
|
||||
# session:
|
||||
@@ -364,6 +373,11 @@ auth:
|
||||
development:
|
||||
clientId: ${AUTH_BITBUCKET_CLIENT_ID}
|
||||
clientSecret: ${AUTH_BITBUCKET_CLIENT_SECRET}
|
||||
atlassian:
|
||||
development:
|
||||
clientId: ${AUTH_ATLASSIAN_CLIENT_ID}
|
||||
clientSecret: ${AUTH_ATLASSIAN_CLIENT_SECRET}
|
||||
scopes: ${AUTH_ATLASSIAN_SCOPES}
|
||||
costInsights:
|
||||
engineerCost: 200000
|
||||
products:
|
||||
|
||||
@@ -47,5 +47,5 @@ sentry:
|
||||
organization: {{ .Values.appConfig.sentry.organization | quote }}
|
||||
|
||||
techdocs:
|
||||
generators:
|
||||
techdocs: 'local'
|
||||
generator:
|
||||
runIn: 'local'
|
||||
@@ -32,7 +32,7 @@ spec:
|
||||
ports:
|
||||
- containerPort: {{ .Values.frontend.containerPort }}
|
||||
resources:
|
||||
{{- toYaml .Values.backend.resources | nindent 12 }}
|
||||
{{- toYaml .Values.frontend.resources | nindent 12 }}
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: {{ include "backstage.fullname" . }}-app-env
|
||||
|
||||
@@ -100,17 +100,16 @@ const app = createApp({
|
||||
|
||||
### Backend
|
||||
|
||||
When using ALB auth it is not possible to leverage the built-in auth config discovery mechanism implemented in the app created by default; bespoke logic needs to be implemented.
|
||||
When using ALB auth you can configure it as described [here](https://backstage.io/docs/auth/identity-resolver).
|
||||
|
||||
- replace the content of `packages/backend/plugin/auth.ts` with the below
|
||||
- replace the content of `packages/backend/plugin/auth.ts` with the below and tweak it according to your needs.
|
||||
|
||||
```ts
|
||||
import {
|
||||
createRouter,
|
||||
AuthResponse,
|
||||
AuthProviderFactoryOptions,
|
||||
defaultAuthProviderFactories,
|
||||
createAwsAlbProvider,
|
||||
} from '@backstage/plugin-auth-backend';
|
||||
import { Router } from 'express';
|
||||
import { PluginEnvironment } from '../types';
|
||||
|
||||
export default async function createPlugin({
|
||||
@@ -118,30 +117,59 @@ export default async function createPlugin({
|
||||
database,
|
||||
config,
|
||||
discovery,
|
||||
}: PluginEnvironment) {
|
||||
const identityResolver = (payload: any): Promise<AuthResponse<any>> => {
|
||||
return Promise.resolve({
|
||||
providerInfo: {},
|
||||
profile: {
|
||||
email: payload.email,
|
||||
displayName: payload.name,
|
||||
picture: payload.picture,
|
||||
},
|
||||
backstageIdentity: {
|
||||
id: payload.email,
|
||||
},
|
||||
});
|
||||
};
|
||||
const providerFactories = {
|
||||
awsalb: (options: AuthProviderFactoryOptions) =>
|
||||
defaultAuthProviderFactories.awsalb({ ...options, identityResolver }),
|
||||
};
|
||||
}: PluginEnvironment): Promise<Router> {
|
||||
return await createRouter({
|
||||
logger,
|
||||
config,
|
||||
database,
|
||||
discovery,
|
||||
providerFactories,
|
||||
providerFactories: {
|
||||
awsalb: createAwsAlbProvider({
|
||||
authHandler: async ({ fullProfile }) => {
|
||||
let email: string | undefined = undefined;
|
||||
if (fullProfile.emails && fullProfile.emails.length > 0) {
|
||||
const [firstEmail] = fullProfile.emails;
|
||||
email = firstEmail.value;
|
||||
}
|
||||
|
||||
let picture: string | undefined = undefined;
|
||||
if (fullProfile.photos && fullProfile.photos.length > 0) {
|
||||
const [firstPhoto] = fullProfile.photos;
|
||||
picture = firstPhoto.value;
|
||||
}
|
||||
|
||||
const displayName: string | undefined =
|
||||
fullProfile.displayName ?? fullProfile.username ?? fullProfile.id;
|
||||
|
||||
return {
|
||||
profile: {
|
||||
email,
|
||||
picture,
|
||||
displayName,
|
||||
},
|
||||
};
|
||||
},
|
||||
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 ent = [`user:default/${id}`];
|
||||
|
||||
// Resolve group membership from the Backstage catalog
|
||||
const fullEnt =
|
||||
await ctx.catalogIdentityClient.resolveCatalogMembership({
|
||||
entityRefs: [id].concat(ent),
|
||||
logger: ctx.logger,
|
||||
});
|
||||
const token = await ctx.tokenIssuer.issueToken({
|
||||
claims: { sub: id, ent: fullEnt },
|
||||
});
|
||||
return { id, token };
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 131 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,64 @@
|
||||
---
|
||||
id: provider
|
||||
title: Atlassian Authentication Provider
|
||||
sidebar_label: Atlassian
|
||||
description: Adding Atlassian as an authentication provider in Backstage
|
||||
---
|
||||
|
||||
The Backstage `core-plugin-api` package comes with an Atlassian authentication
|
||||
provider that can authenticate users using Atlassian products. This auth
|
||||
**only** provides scopes for the following APIs:
|
||||
|
||||
- Confluence API
|
||||
- User REST API
|
||||
- Jira platform REST API
|
||||
- Jira Service Desk API
|
||||
- Personal data reporting API
|
||||
- User identity API
|
||||
|
||||
## Create an OAuth 2.0 (3LO) app in the Atlassian developer console
|
||||
|
||||
To add Atlassian authentication, you must create an OAuth 2.0 (3LO) app.
|
||||
|
||||
Go to `https://developer.atlassian.com/console/myapps/`.
|
||||
|
||||
Click on the drop down `Create`, and choose `OAuth 2.0 integration`.
|
||||
|
||||
Name your integration and click on the `Create` button.
|
||||
|
||||
Settings for local development:
|
||||
|
||||
- Callback URL: `http://localhost:7000/api/auth/atlassian`
|
||||
- Use rotating refresh tokens
|
||||
- For permissions, you **must** enable `View user profile` for the currently
|
||||
logged-in user, under `User identity API`
|
||||
|
||||
## Configuration
|
||||
|
||||
The provider configuration can then be added to your `app-config.yaml` under the
|
||||
root `auth` configuration:
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
environment: development
|
||||
providers:
|
||||
atlassian:
|
||||
development:
|
||||
clientId: ${AUTH_ATLASSIAN_CLIENT_ID}
|
||||
clientSecret: ${AUTH_ATLASSIAN_CLIENT_SECRET}
|
||||
scopes: ${AUTH_ATLASSIAN_SCOPES}
|
||||
```
|
||||
|
||||
The Atlassian provider is a structure with three configuration keys:
|
||||
|
||||
- `clientId`: The Key you generated in the developer console.
|
||||
- `clientSecret`: The Secret tied to the generated Key.
|
||||
- `scopes`: List of scopes the app has permissions for, separated by spaces.
|
||||
|
||||
**NOTE:** the scopes `offline_access` and `read:me` are provided by default.
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
To add the provider to the frontend, add the `atlassianAuthApi` reference and
|
||||
`SignInPage` component as shown in
|
||||
[Adding the provider to the sign-in page](../index.md#adding-the-provider-to-the-sign-in-page).
|
||||
@@ -76,7 +76,7 @@ CMD ["node", "packages/backend", "--config", "app-config.yaml"]
|
||||
|
||||
For more details on how the `backend:bundle` command and the `skeleton.tar.gz`
|
||||
file works, see the
|
||||
[`backend:bundle` command docs](../cli/commands.md#backendbundle).
|
||||
[`backend:bundle` command docs](../local-dev/cli-commands.md#backendbundle).
|
||||
|
||||
The `Dockerfile` is located at `packages/backend/Dockerfile`, but needs to be
|
||||
executed with the root of the repo as the build context, in order to get access
|
||||
|
||||
@@ -29,6 +29,7 @@ kubernetes:
|
||||
serviceAccountToken: ${K8S_MINIKUBE_TOKEN}
|
||||
dashboardUrl: http://127.0.0.1:64713 # url copied from running the command: minikube service kubernetes-dashboard -n kubernetes-dashboard
|
||||
dashboardApp: standard
|
||||
caData: ${K8S_CONFIG_CA_DATA}
|
||||
- url: http://127.0.0.2:9999
|
||||
name: aws-cluster-1
|
||||
authProvider: 'aws'
|
||||
@@ -135,6 +136,24 @@ See also
|
||||
https://github.com/backstage/backstage/tree/master/plugins/kubernetes/src/utils/clusterLinks/formatters
|
||||
for real examples.
|
||||
|
||||
##### `clusters.\*.caData` (optional)
|
||||
|
||||
PEM-encoded certificate authority certificates.
|
||||
|
||||
This values could be obtained via inspecting the Kubernetes config file (usually
|
||||
at `~/.kube/config`) under `clusters.cluster.certificate-authority-data`. For
|
||||
GKE, execute the following command to obtain the value
|
||||
|
||||
```
|
||||
gcloud container clusters describe <YOUR_CLUSTER_NAME> \
|
||||
--zone=<YOUR_COMPUTE_ZONE> \
|
||||
--format="value(masterAuth.clusterCaCertificate)"
|
||||
```
|
||||
|
||||
See also
|
||||
https://cloud.google.com/kubernetes-engine/docs/how-to/api-server-authentication#environments-without-gcloud
|
||||
for complete docs about GKE without `gcloud`.
|
||||
|
||||
#### `gke`
|
||||
|
||||
This cluster locator is designed to work with Kubernetes clusters running in
|
||||
|
||||
@@ -59,14 +59,18 @@ add the following:
|
||||
|
||||
```typescript
|
||||
// In packages/backend/src/plugins/kubernetes.ts
|
||||
import { createRouter } from '@backstage/plugin-kubernetes-backend';
|
||||
import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';
|
||||
import { PluginEnvironment } from '../types';
|
||||
|
||||
export default async function createPlugin({
|
||||
logger,
|
||||
config,
|
||||
}: PluginEnvironment) {
|
||||
return await createRouter({ logger, config });
|
||||
const { router } = await KubernetesBuilder.createBuilder({
|
||||
logger,
|
||||
config,
|
||||
}).build();
|
||||
return router;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -102,20 +102,24 @@ more to come...
|
||||
See [Backstage Search Architecture](architecture.md) to get an overview of how
|
||||
the search engines are used.
|
||||
|
||||
| Search Engine | Support Status |
|
||||
| ------------- | -------------- |
|
||||
| Basic (lunr) | ✅ |
|
||||
| ElasticSearch | Not yet ❌ |
|
||||
| Search Engines | Support Status |
|
||||
| -------------------------------------------------- | -------------- |
|
||||
| [Lunr](./search-engines.md#lunr) | ✅ |
|
||||
| [ElasticSearch](./search-engines.md#elasticsearch) | ✅ |
|
||||
| [Postgres](./search-engines.md#postgres) | ✅ |
|
||||
|
||||
[Reach out to us](#feedback) if you want to chat about support for more search
|
||||
engines.
|
||||
[Reach out to us](#get-involved) if you want to chat about support for more
|
||||
search engines.
|
||||
|
||||
## Plugins Integrated with Search
|
||||
|
||||
| Plugin | Support Status |
|
||||
| -------- | -------------- |
|
||||
| Catalog | ✅ |
|
||||
| TechDocs | Not yet ❌ |
|
||||
| Plugin | Support Status |
|
||||
| -------------------------------------------------------------- | -------------- |
|
||||
| Catalog | ✅ |
|
||||
| [TechDocs](./how-to-guides.md#how-to-index-techdocs-documents) | ✅ |
|
||||
|
||||
[Reach out to us](#get-involved) if you want to chat about support for more
|
||||
plugins integrated to search.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
id: how-to-guides
|
||||
title: Search "HOW TO" guides
|
||||
sidebar_label: "HOW TO" guides
|
||||
description: Search "HOW TO" guides
|
||||
---
|
||||
|
||||
## How to implement your own Search API
|
||||
|
||||
The Search plugin provides implementation of one primary API by default: the
|
||||
[SearchApi](https://github.com/backstage/backstage/blob/db2666b980853c281b8fe77905d7639c5d255f13/plugins/search/src/apis.ts#L35),
|
||||
which is responsible for talking to the search-backend to query search results.
|
||||
|
||||
There may be occasions where you need to implement this API yourself, to
|
||||
customize it to your own needs - for example if you have your own search backend
|
||||
that you want to talk to. The purpose of this guide is to walk you through how
|
||||
to do that in two steps.
|
||||
|
||||
1. Implement the `SearchApi`
|
||||
[interface](https://github.com/backstage/backstage/blob/db2666b980853c281b8fe77905d7639c5d255f13/plugins/search/src/apis.ts#L31)
|
||||
according to your needs.
|
||||
|
||||
```typescript
|
||||
export class SearchClient implements SearchApi {
|
||||
// your implementation
|
||||
}
|
||||
```
|
||||
|
||||
2. Override the API ref `searchApiRef` with your new implemented API in the
|
||||
`App.tsx` using `ApiFactories`.
|
||||
[Read more about App APIs](https://backstage.io/docs/api/utility-apis#app-apis).
|
||||
|
||||
```typescript
|
||||
const app = createApp({
|
||||
apis: [
|
||||
// SearchApi
|
||||
createApiFactory({
|
||||
api: searchApiRef,
|
||||
deps: { discovery: discoveryApiRef },
|
||||
factory({ discovery }) {
|
||||
return new SearchClient({ discoveryApi: discovery });
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## How to index TechDocs documents
|
||||
|
||||
The TechDocs plugin has supported integrations to Search, meaning that it
|
||||
provides a default collator ready to be used.
|
||||
|
||||
The purpose of this guide is to walk you through how to register the
|
||||
[DefaultTechDocsCollator](https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts)
|
||||
in your App, so that you can get TechDocs documents indexed.
|
||||
|
||||
If you have been through the
|
||||
[Getting Started with Search guide](https://backstage.io/docs/features/search/getting-started),
|
||||
you should have the `packages/backend/src/plugins/search.ts` file available. If
|
||||
so, you can go ahead and follow this guide - if not, start by going through the
|
||||
getting started guide.
|
||||
|
||||
1. Import the DefaultTechDocsCollator from `@backstage/plugin-techdocs-backend`.
|
||||
|
||||
```typescript
|
||||
import { DefaultTechDocsCollator } from '@backstage/plugin-techdocs-backend';
|
||||
```
|
||||
|
||||
2. Register the DefaultTechDocsCollator with the IndexBuilder.
|
||||
|
||||
```typescript
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
collator: DefaultTechDocsCollator.fromConfig(config, {
|
||||
discovery,
|
||||
logger,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
You should now have your TechDocs documents indexed to your search engine of
|
||||
choice!
|
||||
|
||||
If you want your users to be able to filter down to the techdocs type when
|
||||
searching, you can update your `SearchPage.tsx` file in
|
||||
`packages/app/src/components/search` by adding `techdocs` to the list of values
|
||||
of the `SearchType` component.
|
||||
|
||||
```tsx
|
||||
<Paper className={classes.filters}>
|
||||
<SearchType
|
||||
values={['techdocs', 'software-catalog']}
|
||||
name="type"
|
||||
defaultValue="software-catalog"
|
||||
/>
|
||||
...
|
||||
</Paper>
|
||||
```
|
||||
@@ -620,9 +620,6 @@ The following describes the following entity kind:
|
||||
| `apiVersion` | `backstage.io/v1beta2` |
|
||||
| `kind` | `Template` |
|
||||
|
||||
If you're looking for docs on `v1alpha1` you can find them
|
||||
[here](../software-templates/legacy.md)
|
||||
|
||||
A template definition describes both the parameters that are rendered in the
|
||||
frontend part of the scaffolding wizard, and the steps that are executed when
|
||||
scaffolding that component.
|
||||
|
||||
@@ -429,3 +429,101 @@ from one environment to the other, do rollbacks, see their relative performance
|
||||
metrics, and similar. This coherency and collection of tooling in one place is
|
||||
where something like Backstage can offer the most value and effectiveness of
|
||||
use. Splitting your entities apart into small islands makes this harder.
|
||||
|
||||
## Implementing custom model extensions
|
||||
|
||||
This section walks you through the steps involved extending the catalog model
|
||||
with a new Entity type.
|
||||
|
||||
### Creating a custom entity definition
|
||||
|
||||
The first step of introducing a custom entity is to define what shape and schema
|
||||
it has. We do this both using a TypeScript type, along with a JSONSchema schema.
|
||||
|
||||
Most of the time you will want to have at least the TypeScript type of your
|
||||
extension available in both frontend and backend code, which means you likely
|
||||
want to have an isomorphic package that houses these types. Within the Backstage
|
||||
main repo the package naming pattern of `<plugin>-common` is used for isomorphic
|
||||
packages, and you may choose to adopt this pattern as well.
|
||||
|
||||
There's at this point no existing templates for generating isomorphic plugins
|
||||
using the `@backstage/cli`. Perhaps the simplest wat to get started right now is
|
||||
to copy the contents of one of the existing packages in the main repository,
|
||||
such as `plugins/scaffolder-common`, and rename the folder and file contents to
|
||||
the desired name. This example uses _foobar_ as the plugin name so the plugin
|
||||
will be named _foobar-common_.
|
||||
|
||||
Once you have a common package in place you can start adding your own entity
|
||||
definitions. For the exact details on how to do that we defer to getting
|
||||
inspired by the existing
|
||||
[scaffolder-common](https://github.com/backstage/backstage/tree/master/plugins/scaffolder-common/src/index.ts)
|
||||
package. But in short you will need to declare a TypeScript type and a
|
||||
JSONSchema for the new entity kind.
|
||||
|
||||
### Building a custom processor for the entity
|
||||
|
||||
The next step is to create a custom processor for your new entity kind. This
|
||||
will be used within the catalog to make sure that it's able to ingest and
|
||||
validate entities of our new kind. Just like with the definition package, you
|
||||
can find inspiration in for example the existing
|
||||
[ScaffolderEntitiesProcessor](https://github.com/backstage/backstage/tree/master/plugins/scaffolder-backend/src/processor/ScaffolderEntitiesProcessor.ts).
|
||||
We also provide a high-level example of what a catalog process for a custom
|
||||
entity might look like:
|
||||
|
||||
```ts
|
||||
import { entityKindSchemaValidator } from '@backstage/catalog-model';
|
||||
|
||||
export class FoobarEntitiesProcessor implements CatalogProcessor {
|
||||
// You often end up wanting to support multiple versions of your kind as you
|
||||
// iterate on the definition, so we keep each version inside this array.
|
||||
private readonly validators = [
|
||||
// This is where we use the JSONSchema that we export from our isomorphic package
|
||||
entityKindSchemaValidator(foobarEntityV1alpha1Schema),
|
||||
];
|
||||
|
||||
// validateEntityKind is responsible for signaling to the catalog processing engine
|
||||
// that this entity is valid and should therefore be submitted for further processing.
|
||||
async validateEntityKind(entity: Entity): Promise<boolean> {
|
||||
for (const validator of this.validators) {
|
||||
if (validator(entity)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async postProcessEntity(
|
||||
entity: Entity,
|
||||
_location: LocationSpec,
|
||||
emit: CatalogProcessorEmit,
|
||||
): Promise<Entity> {
|
||||
if (
|
||||
entity.apiVersion === 'example.com/v1alpha1' &&
|
||||
entity.kind === 'Foobar'
|
||||
) {
|
||||
const foobarEntity = entity as FoobarEntityV1alpha1;
|
||||
|
||||
// Here we can modify the entity or emit results related to the entity
|
||||
// Typically you will want to emit any relations associated with the entity here
|
||||
emit(results.relation({ ... }))
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Once the processor is created it can be wired up to the catalog via the
|
||||
`CatalogBuilder` in `packages/backend/src/plugins/catalog.ts`:
|
||||
|
||||
```diff
|
||||
+ import { FoobarEntitiesProcessor implements CatalogProcessor {
|
||||
} from '@internal/plugin-foobar-backend';
|
||||
|
||||
// ...
|
||||
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
+ builder.addProcessor(new FoobarEntitiesProcessor());
|
||||
const { processingEngine, router } = await builder.build();
|
||||
```
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
---
|
||||
id: template-legacy
|
||||
title: Writing Templates (Legacy)
|
||||
# prettier-ignore
|
||||
description: Old documentation describing the backstage.io/v1alpha1 format of the Template Schema
|
||||
---
|
||||
|
||||
## Kind: Template
|
||||
|
||||
Describes the following entity kind:
|
||||
|
||||
| Field | Value |
|
||||
| ------------ | ----------------------- |
|
||||
| `apiVersion` | `backstage.io/v1alpha1` |
|
||||
| `kind` | `Template` |
|
||||
|
||||
A Template describes a skeleton for use with the Scaffolder. It is used for
|
||||
describing what templating library is supported, and also for documenting the
|
||||
variables that the template requires using
|
||||
[JSON Forms Schema](https://jsonforms.io/).
|
||||
|
||||
Descriptor files for this kind may look as follows.
|
||||
|
||||
```yaml
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: Template
|
||||
metadata:
|
||||
name: react-ssr-template
|
||||
title: React SSR Template
|
||||
description:
|
||||
Next.js application skeleton for creating isomorphic web applications.
|
||||
tags:
|
||||
- recommended
|
||||
- react
|
||||
spec:
|
||||
owner: web@example.com
|
||||
templater: cookiecutter
|
||||
type: website
|
||||
path: '.'
|
||||
schema:
|
||||
required:
|
||||
- component_id
|
||||
- description
|
||||
properties:
|
||||
component_id:
|
||||
title: Name
|
||||
type: string
|
||||
description: Unique name of the component
|
||||
description:
|
||||
title: Description
|
||||
type: string
|
||||
description: Description of the component
|
||||
```
|
||||
|
||||
In addition to the [common envelope metadata](#common-to-all-kinds-the-metadata)
|
||||
shape, this kind has the following structure.
|
||||
|
||||
### `apiVersion` and `kind` [required]
|
||||
|
||||
Exactly equal to `backstage.io/v1alpha1` and `Template`, respectively.
|
||||
|
||||
### `metadata.title` [required]
|
||||
|
||||
The nice display name for the template as a string, e.g. `React SSR Template`.
|
||||
This field is required as is used to reference the template to the user instead
|
||||
of the `metadata.name` field.
|
||||
|
||||
### `metadata.tags` [optional]
|
||||
|
||||
A list of strings that can be associated with the template, e.g.
|
||||
`['recommended', 'react']`.
|
||||
|
||||
This list will also be used in the frontend to display to the user so you can
|
||||
potentially search and group templates by these tags.
|
||||
|
||||
### `spec.type` [optional]
|
||||
|
||||
The type of component as a string, e.g. `website`. This field is optional but
|
||||
recommended.
|
||||
|
||||
The software catalog accepts any type value, but an organization should take
|
||||
great care to establish a proper taxonomy for these. Tools including Backstage
|
||||
itself may read this field and behave differently depending on its value. For
|
||||
example, a website type component may present tooling in the Backstage interface
|
||||
that is specific to just websites.
|
||||
|
||||
The current set of well-known and common values for this field is:
|
||||
|
||||
- `service` - a backend service, typically exposing an API
|
||||
- `website` - a website
|
||||
- `library` - a software library, such as an npm module or a Java library
|
||||
|
||||
### `spec.templater` [required]
|
||||
|
||||
The templating library that is supported by the template skeleton as a string,
|
||||
e.g `cookiecutter`.
|
||||
|
||||
Different skeletons will use different templating syntax, so it's common that
|
||||
the template will need to be run with a particular piece of software.
|
||||
|
||||
This key will be used to identify the correct templater which is registered into
|
||||
the `TemplatersBuilder`.
|
||||
|
||||
The values which are available by default are:
|
||||
|
||||
- `cookiecutter` - [cookiecutter](https://github.com/cookiecutter/cookiecutter).
|
||||
|
||||
### `spec.path` [optional]
|
||||
|
||||
The string location where the templater should be run if it is not on the same
|
||||
level as the `template.yaml` definition, e.g. `./cookiecutter/skeleton`.
|
||||
|
||||
This will set the `cwd` when running the templater to the folder path that you
|
||||
specify relative to the `template.yaml` definition.
|
||||
|
||||
This is also particularly useful when you have multiple template definitions in
|
||||
the same repository but only a single `template.yaml` registered in backstage.
|
||||
@@ -1,333 +0,0 @@
|
||||
---
|
||||
id: migrating-from-v1alpha1-to-v1beta2
|
||||
title: Migrating to v1beta2 templates
|
||||
# prettier-ignore
|
||||
description: How to move your old templates from v1alpha1 to the more declarative v1beta2
|
||||
---
|
||||
|
||||
# What's new?
|
||||
|
||||
Previously, the scaffolder was very restricted in what you could do when
|
||||
creating new software components from templates. There were three scaffolding
|
||||
steps which was pretty hard to extend and add new functionality to, difficult to
|
||||
re-use logic between templates. There used to be a fixed pipeline of
|
||||
`preparers`, `templaters`, and `publishers`, which were defined by the backend
|
||||
and needed to be run for each template. This is now changed, to give the
|
||||
template total control over what should be executed as part of the templating
|
||||
run. This makes templates a little more declarative as you can now register
|
||||
different `actions` or `functions` with the `scaffolder-backend` which you then
|
||||
can decide how, and in what order, to run using the template definition YAML
|
||||
file.
|
||||
|
||||
We've also made some improvements, and added some helpers to work with
|
||||
cookiecutter. The skeleton for a template can now be stored in a different place
|
||||
to where your entity definition is: previously you needed to have your
|
||||
`template.yaml` next to the skeleton source (`{{cookiecutter.component_id}}`
|
||||
directory), but now that's not the case. Part of the changes with the `v1beta2`
|
||||
syntax is that you can grab your template source from any repository, and re-use
|
||||
them between templates.
|
||||
|
||||
We've also renamed the `schema` property to `parameters` as this makes more
|
||||
sense when using them as parameters to the actions or steps that you've setup
|
||||
for your templates. There's the added benefit that you can now assign an array
|
||||
to the `parameters` property, which will then give you multiple steps in the UI,
|
||||
so you can split apart your input parameters and group them as needed rather
|
||||
than having one long list of input fields.
|
||||
|
||||
## The `parameters` property
|
||||
|
||||
The `schema` key has now been renamed to `parameters` with a few more features.
|
||||
You can pass an array now to break apart the input form into different steps in
|
||||
the UI. You can also specify `ui:schema` fields that are passed along to
|
||||
[`react-jsonschema-form`](https://rjsf-team.github.io/react-jsonschema-form/)
|
||||
inline with the JSON schema.
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
parameters:
|
||||
- title: Fill in some steps
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
title: Name
|
||||
type: string
|
||||
description: Unique name of the component
|
||||
ui:autofocus: true
|
||||
ui:options:
|
||||
rows: 5
|
||||
```
|
||||
|
||||
## The `steps` property
|
||||
|
||||
`v1beta2` template syntax introduces the new `steps` property, which is an array
|
||||
of `actions` that the scaffolder will run in combination with the user input
|
||||
that is declared in the `schema`. Actions look like the following:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
steps:
|
||||
- id: publish # a unique id for the step, can be anything you like
|
||||
name: Publish # a user friendly name for the step, this is what is shown in the frontend
|
||||
action: publish:github # the action ID that has been registered with the scaffolder-backend
|
||||
input: # parameters that are passed as input to the action handler function
|
||||
allowedHosts: ['github.com']
|
||||
description: 'This is {{ parameters.name }}' # handlebars templating is supported with the values from the parameters section in the same file.
|
||||
repoUrl: '{{ parameters.repoUrl }}'
|
||||
```
|
||||
|
||||
# Migrating a `v1alpha1` template
|
||||
|
||||
## The template definition (.yaml)
|
||||
|
||||
### `parameters`
|
||||
|
||||
Because of the changes to invert the control to the `template.yaml` definition
|
||||
for running the workflow, we need to adjust the `schema` property and we also
|
||||
now need to define what the template is actually going to do as part of the
|
||||
template run.
|
||||
|
||||
A simple migration would move the following yaml:
|
||||
|
||||
```yaml
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: Template
|
||||
metadata:
|
||||
name: react-ssr-template
|
||||
title: React SSR Template
|
||||
description: Create a website powered with Next.js
|
||||
tags:
|
||||
- recommended
|
||||
- react
|
||||
spec:
|
||||
owner: web@example.com
|
||||
templater: cookiecutter
|
||||
type: website
|
||||
path: '.'
|
||||
schema:
|
||||
required:
|
||||
- component_id
|
||||
- description
|
||||
properties:
|
||||
component_id:
|
||||
title: Name
|
||||
type: string
|
||||
description: Unique name of the component
|
||||
description:
|
||||
title: Description
|
||||
type: string
|
||||
description: Help others understand what this website is for.
|
||||
```
|
||||
|
||||
To something that looks like the following:
|
||||
|
||||
```yaml
|
||||
apiVersion: backstage.io/v1beta2
|
||||
kind: Template
|
||||
metadata:
|
||||
name: react-ssr-template
|
||||
title: React SSR Template
|
||||
description: Create a website powered with Next.js
|
||||
tags:
|
||||
- recommended
|
||||
- react
|
||||
spec:
|
||||
owner: web@example.com
|
||||
type: website
|
||||
parameters:
|
||||
- title: Add some input
|
||||
required:
|
||||
- component_id
|
||||
- description
|
||||
properties:
|
||||
component_id:
|
||||
title: Name
|
||||
type: string
|
||||
description: Unique name of the component
|
||||
description:
|
||||
title: Description
|
||||
type: string
|
||||
description: Help others understand what this website is for.
|
||||
- title: Some more additional info that was previously provided automatically
|
||||
required:
|
||||
- owner
|
||||
- repoUrl
|
||||
properties:
|
||||
owner:
|
||||
title: Owner
|
||||
type: string
|
||||
description: Owner of the component
|
||||
ui:field: OwnerPicker
|
||||
ui:options:
|
||||
allowedKinds:
|
||||
- Group
|
||||
- title: Choose a location
|
||||
repoUrl:
|
||||
title: Repository Location
|
||||
type: string
|
||||
ui:field: RepoUrlPicker
|
||||
ui:options:
|
||||
allowedHosts:
|
||||
- github.com
|
||||
```
|
||||
|
||||
There are a few things to note here. On the `alpha` version, the second step of
|
||||
the template flow in the frontend was provided by Backstage for free, so we used
|
||||
to collect the user input for the `owner` field and the `repositoryUrl` that you
|
||||
were going to publish to. Now because `actions` can have any workflow they like,
|
||||
it doesn't make sense to still provide these fields for every scaffolding
|
||||
workflow, as you might not need these anymore. That's why we now manually add
|
||||
those fields back into the template parameters that are shown to the user:
|
||||
|
||||
```yaml
|
||||
- title: Some more additional info that was previously provided automatically
|
||||
required:
|
||||
- owner
|
||||
- repoUrl
|
||||
properties:
|
||||
owner:
|
||||
title: Owner
|
||||
type: string
|
||||
description: Owner of the component
|
||||
ui:field: OwnerPicker
|
||||
ui:options:
|
||||
allowedKinds:
|
||||
- Group
|
||||
- title: Choose a location
|
||||
repoUrl:
|
||||
title: Repository Location
|
||||
type: string
|
||||
ui:field: RepoUrlPicker
|
||||
ui:options:
|
||||
allowedHosts:
|
||||
- github.com
|
||||
```
|
||||
|
||||
Maybe you also don't need to publish to `github.com`, you should replace this
|
||||
with your VCS provider URL that is listed in your `integrations` config instead.
|
||||
|
||||
### `steps`
|
||||
|
||||
So now we should have all the required information that we need from the user in
|
||||
a much more extensible way. We now need to tell the scaffolder what to do with
|
||||
these parameters and what to do with the user input.
|
||||
|
||||
We've made templating using `cookiecutter` a little simpler. You don't need to
|
||||
store the `cookiecutter` skeleton in the same directory as the `template.yaml`
|
||||
definition, it can live wherever you like - maybe a shared repository somewhere
|
||||
so you can re-use the skeletons but apply different actions for different
|
||||
templates depending on your use case.
|
||||
|
||||
We also no longer need to have a directory called
|
||||
`{{cookiecutter.component_id}}`. This is because now we can't ensure that
|
||||
`component_id` will be a parameter that is provided from the frontend, this
|
||||
could break `cookiecutter`. If your directory structure used to look like this:
|
||||
|
||||
```
|
||||
my-awesome-template
|
||||
-> {{cookiecutter.component_id}}
|
||||
-> file.txt
|
||||
-> some_more_files.ts
|
||||
-> hooks
|
||||
-> post_gen_project.sh
|
||||
-> template.yaml
|
||||
```
|
||||
|
||||
We now recommend that you move to the following structure:
|
||||
|
||||
```
|
||||
my-awesome-template
|
||||
-> skeleton
|
||||
-> file.txt
|
||||
-> some_more_files.ts
|
||||
-> template.yaml
|
||||
```
|
||||
|
||||
This migration renames the skeleton folder to something more semantic, and also
|
||||
drops support for `cookiecutter` hooks. We've dropped support for `cookiecutter`
|
||||
hooks for now, as hopefully everything that is stored in these hooks can be
|
||||
moved to `actions` instead, and for security reasons, it's more secure to run
|
||||
trusted code that you ship with Backstage as an action rather than some script
|
||||
that can be pulled in from anywhere which doesn't get vetted first. It's a
|
||||
pretty big security risk that those scripts will be run on Backstage instances
|
||||
inside your infrastructure, especially `.sh` files.
|
||||
|
||||
If you really need hooks and can't find a suitable solution by using actions
|
||||
please reach out to us through a ticket and we'll see what we can do to assist
|
||||
:)
|
||||
|
||||
You'll notice that we removed the `templater` property from the `spec`
|
||||
definition in the template `yaml`, so there's no way to define that this is a
|
||||
`cookiecutter` `templater`.
|
||||
|
||||
We've created a built-in action that you can use which will when run, go grab a
|
||||
directory from anywhere and run `cookiecutter` on top of it, and then extract
|
||||
the contents into the working directory for the scaffolder.
|
||||
|
||||
Adding the `steps` for a simple template should look something like the
|
||||
following:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
steps:
|
||||
# this action will go use cookiecutter to template some files into the working directory
|
||||
- id: template # an ID for the templating step
|
||||
name: Create skeleton # A user friendly name for the action
|
||||
action: fetch:cookiecutter
|
||||
input:
|
||||
url: ./skeleton # this is the directory for your skeleton files.
|
||||
# If it's located next to the `template.yaml` then you can use a relative path,
|
||||
# otherwise you can use absolute URLs that point at the VCS: https://github.com/backstage/backstage/tree/master/some_folder_somewhere
|
||||
values:
|
||||
# for each value that you need to pass to cookiecutter, they should be listed here and set in this values object.
|
||||
# You can use the handlebars templating syntax to pull them from the input parameters listed in the same file
|
||||
name: '{{ parameters.name }}'
|
||||
owner: '{{ parameters.owner }}'
|
||||
destination: '{{ parseRepoUrl parameters.repoUrl }}'
|
||||
|
||||
# this action is for publishing the working directory to the VCS
|
||||
- id: publish
|
||||
name: Publish
|
||||
action: publish:github
|
||||
input:
|
||||
allowedHosts: ['github.com']
|
||||
description: 'This is {{ parameters.name }}'
|
||||
repoUrl: '{{ parameters.repoUrl }}'
|
||||
|
||||
# this action will then register the created component in Backstage
|
||||
- id: register
|
||||
name: Register
|
||||
action: catalog:register
|
||||
input:
|
||||
repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}'
|
||||
catalogInfoPath: '/catalog-info.yaml'
|
||||
```
|
||||
|
||||
### `output`
|
||||
|
||||
Steps can output values, and so can the template itself. This is good for
|
||||
returning values to the frontend, so we can make the buttons like
|
||||
`Go to catalog` and `Go to repo` work correctly. You can add the following to
|
||||
your `template.yaml` to make sure you return the right values from the steps:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
output:
|
||||
remoteUrl: '{{ steps.publish.output.remoteUrl }}'
|
||||
entityRef: '{{ steps.register.output.entityRef }}'
|
||||
```
|
||||
|
||||
Or you can return a `links` array with text and a URL explicitly:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
output:
|
||||
links:
|
||||
- url: '{{steps.publish.output.remoteUrl}}'
|
||||
title: 'Go to Repo'
|
||||
```
|
||||
|
||||
## Questions?
|
||||
|
||||
If you have any questions or feedback, please reach out to us on GitHub or
|
||||
Discord and we will do our best to help!
|
||||
@@ -0,0 +1,156 @@
|
||||
---
|
||||
id: migrating-from-v1beta2-to-v1beta3
|
||||
title: Migrating to v1beta3 templates
|
||||
# prettier-ignore
|
||||
description: How to migrate your existing templates to beta3 syntax
|
||||
---
|
||||
|
||||
# What's new?
|
||||
|
||||
Well then, here we are! 🚀
|
||||
|
||||
Backstage has had many forms of templating languages throughout different
|
||||
plugins and different systems. We've had `cookiecutter` syntax in templates, and
|
||||
we also had `handlebars` templating in the `kind: Template`. Then we wanted to
|
||||
remove the additional dependency on `cookiecutter` for Software Templates out of
|
||||
the box, so we introduced `nunjucks` as an alternative in `fetch:template`
|
||||
action which is based on the `jinja2` syntax so they're pretty similar. In an
|
||||
effort to reduce confusion and unify on to one templating language, we're
|
||||
officially deprecating support for `handlebars` templating in the
|
||||
`kind: Template` entities with `apiVersion` `scaffolder.backstage.io/v1beta3`
|
||||
and moving to using `nunjucks` instead.
|
||||
|
||||
This provides us a lot of built in `filters` (`handlebars` helpers), that as
|
||||
Template authors will give you much more flexibility out of the box, and also
|
||||
open up sharing of filters in the Entity and the actual `skeleton` too, and
|
||||
removing the slight differences between the two languages.
|
||||
|
||||
We've also removed a lot of the built in helpers that we shipped with
|
||||
`handlebars`, as they're now supported as first class citizens by either
|
||||
`nunjucks` or the new `scaffolder` when using `scaffolder.backstage.io/v1beta3`
|
||||
`apiVersion`
|
||||
|
||||
The migration path is pretty simple, and we've removed some of the pain points
|
||||
from writing the `handlebars` templates too. Let's go through what's new and how
|
||||
to upgrade.
|
||||
|
||||
## `backstage.io/v1beta2` -> `scaffolder.backstage.io/v1beta3`
|
||||
|
||||
The most important change is that you'll need to switch over the `apiVersion` in
|
||||
your templates to the new one.
|
||||
|
||||
```diff
|
||||
kind: Template
|
||||
- apiVersion: backstage.io/v1beta2
|
||||
+ apiVersion: scaffolder.backstage.io/v1beta3
|
||||
```
|
||||
|
||||
## `${{ }}` instead of `"{{ }}"`
|
||||
|
||||
One really big readability issue and cause for confusion was the fact that with
|
||||
`handlebars` and `yaml` you always had to wrap your templating strings in quotes
|
||||
in `yaml` so that it didn't try to parse it as a `json` object and fail. This
|
||||
was pretty annoying, as it also meant that all things look like strings. Now
|
||||
that's no longer the case, you can now remove the `""` and take advantage of
|
||||
writing nice `yaml` files that just work.
|
||||
|
||||
```diff
|
||||
spec:
|
||||
steps:
|
||||
input:
|
||||
allowedHosts: ['github.com']
|
||||
- description: 'This is {{ parameters.name }}'
|
||||
+ description: This is ${{ parameters.name }}
|
||||
- repoUrl: '{{ parameters.repoUrl }}'
|
||||
+ repoUrl: ${{ parameters.repoUrl }}
|
||||
```
|
||||
|
||||
## No more `eq` or `not` helpers
|
||||
|
||||
These helpers are no longer needed with the more expressive `api` that
|
||||
`nunjucks` provides. You can simply use the built-in `nunjucks` and `jinja2`
|
||||
style operators.
|
||||
|
||||
```diff
|
||||
spec:
|
||||
steps:
|
||||
input:
|
||||
- if: '{{ eq parameters.value "backstage" }}'
|
||||
+ if: ${{ parameters.value === "backstage" }}
|
||||
...
|
||||
```
|
||||
|
||||
And then for the `not`
|
||||
|
||||
```diff
|
||||
spec:
|
||||
steps:
|
||||
input:
|
||||
- if: '{{ not parameters.value "backstage" }}'
|
||||
+ if: ${{ parameters.value !== "backstage" }}
|
||||
...
|
||||
```
|
||||
|
||||
Much better right? ✨
|
||||
|
||||
## No more `json` helper
|
||||
|
||||
This helper is no longer needed, as we've added support for complex values and
|
||||
supporting the additional primitive values now rather than everything being a
|
||||
`string`. This means that now that you can pass around `parameters` and it
|
||||
should all work as expected and keep the type that has been declared in the
|
||||
input schema.
|
||||
|
||||
```diff
|
||||
spec:
|
||||
parameters:
|
||||
test:
|
||||
type: number
|
||||
name: Test Number
|
||||
address:
|
||||
type: object
|
||||
required:
|
||||
- line1
|
||||
properties:
|
||||
line1:🙏
|
||||
type: string
|
||||
name: Line 1
|
||||
line2:
|
||||
type: string
|
||||
name: Line 2
|
||||
|
||||
steps:
|
||||
- id: test step
|
||||
action: run:something
|
||||
input:
|
||||
- address: '{{ json parameters.address }}'
|
||||
+ address: ${{ parameters.address }}
|
||||
- number: '{{ parameters.number }}'
|
||||
+ number: ${{ parameters.number }} # this will now make sure that the type of number is a number 🙏
|
||||
```
|
||||
|
||||
## `parseRepoUrl` is now a `filter`
|
||||
|
||||
All calls to `parseRepoUrl` are now a `jinja2` `filter`, which means you'll need
|
||||
to update the syntax.
|
||||
|
||||
```diff
|
||||
spec:
|
||||
steps:
|
||||
input:
|
||||
- repoUrl: '{{ parseRepoUrl parameters.repoUrl }}'
|
||||
+ repoUrl: ${{ parameters.repoUrl | parseRepoUrl }}
|
||||
...
|
||||
```
|
||||
|
||||
Now we have complex value support here too, expect that this `filter` will go
|
||||
away in future versions and the `RepoUrlPicker` will return an object so
|
||||
`parameters.repoUrl` will already be a
|
||||
`{ host: string; owner: string; repo: string }` 🚀
|
||||
|
||||
### Summary
|
||||
|
||||
Of course, we're always available on [discord](https://discord.gg/MUpMjP2) if
|
||||
you're stuck or something's not working as expected. You can also
|
||||
[raise an issue](https://github.com/backstage/backstage/issues/new/choose) with
|
||||
feedback or bugs!
|
||||
@@ -63,6 +63,10 @@ techdocs:
|
||||
# (Required) Cloud Storage Bucket Name
|
||||
bucketName: 'techdocs-storage'
|
||||
|
||||
# (Optional) Location in storage bucket to save files
|
||||
# If not set, the default location will be the root of the storage bucket
|
||||
bucketRootPath: '/'
|
||||
|
||||
# (Optional) An API key is required to write to a storage bucket.
|
||||
# If missing, GOOGLE_APPLICATION_CREDENTIALS environment variable will be used.
|
||||
# https://cloud.google.com/docs/authentication/production
|
||||
@@ -75,6 +79,10 @@ techdocs:
|
||||
# (Required) AWS S3 Bucket Name
|
||||
bucketName: 'techdocs-storage'
|
||||
|
||||
# (Optional) Location in storage bucket to save files
|
||||
# If not set, the default location will be the root of the storage bucket
|
||||
bucketRootPath: '/'
|
||||
|
||||
# (Optional) An API key is required to write to a storage bucket.
|
||||
# If not set, environment variables or aws config file will be used to authenticate.
|
||||
# https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/loading-node-credentials-environment.html
|
||||
|
||||
@@ -5,11 +5,12 @@ sidebar_label: Creating and Publishing Documentation
|
||||
description: Guidance on how to create and publish documentation
|
||||
---
|
||||
|
||||
This section will guide you through:
|
||||
This section will guide you through how to:
|
||||
|
||||
- [Create a basic documentation setup](#create-a-basic-documentation-setup)
|
||||
- [Use any software template](#use-any-software-template)
|
||||
- [Use the documentation template](#use-the-documentation-template)
|
||||
- [Manually add documentation setup to already existing repository](#manually-add-documentation-setup-to-already-existing-repository)
|
||||
- [Enable documentation for an already existing entity](#enable-documentation-for-an-already-existing-entity)
|
||||
- [Writing and previewing your documentation](#writing-and-previewing-your-documentation)
|
||||
|
||||
## Prerequisites
|
||||
@@ -21,29 +22,47 @@ This section will guide you through:
|
||||
|
||||
If you have an existing repository that you'd like to add documentation to, skip
|
||||
to the
|
||||
[Manually add documentation setup](#manually-add-documentation-setup-to-already-existing-repository)
|
||||
section below. Otherwise, continue reading to start a documentation repo from
|
||||
scratch.
|
||||
[Enable documentation for an already existing entity setup](#enable-documentation-for-an-already-existing-entity)
|
||||
section below. Otherwise, continue reading to create a new software entity
|
||||
including documentation from scratch.
|
||||
|
||||
### Use any software template
|
||||
|
||||
TechDocs is built on top of the
|
||||
[docs like code approach](https://www.docslikecode.com/about/). This, in short,
|
||||
means that you should keep documentation close to the code.
|
||||
|
||||
Your Backstage app has a set of software templates added by default. All of
|
||||
these software templates include everything you need to get your TechDocs site
|
||||
up and running and to start writing your documentation.
|
||||
|
||||
If you have created software templates that do not include documentation by
|
||||
default, we highly recommend you to set that up. Follow our how-to guide
|
||||
[How to add documentation setup to your software templates](./how-to-guides.md#how-to-add-the-documentation-setup-to-your-software-templates)
|
||||
to get started.
|
||||
|
||||
### Use the documentation template
|
||||
|
||||
Your working Backstage instance should by default have a documentation template
|
||||
added. If not, copy the catalog locations from the
|
||||
There could be _some_ situations where you don't want to keep your docs close to
|
||||
your code, but still want to publish documentation - for example, an onboarding
|
||||
tutorial. For this use case, we have put together a documentation template. Your
|
||||
Backstage instance should by default have a documentation template added. If
|
||||
not, copy the catalog locations from the
|
||||
[create-app template](https://github.com/backstage/backstage/blob/master/packages/create-app/templates/default-app/app-config.yaml.hbs)
|
||||
to add the documentation template. The template creates a component with only
|
||||
TechDocs configuration and default markdown files as below mentioned in manual
|
||||
documentation setup, and is otherwise empty.
|
||||
to add the documentation template. The template creates a component with
|
||||
**only** TechDocs configuration and default markdown files, and is otherwise
|
||||
empty.
|
||||
|
||||

|
||||
|
||||
Create an entity from the documentation template and you will get the needed
|
||||
setup for free.
|
||||
|
||||
### Manually add documentation setup to already existing repository
|
||||
### Enable documentation for an already existing entity
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- An existing component
|
||||
- An existing entity
|
||||
[registered in backstage](../software-catalog/index.md#adding-components-to-the-catalog)
|
||||
(e.g. via a `catalog-info.yaml` file).
|
||||
|
||||
@@ -72,11 +91,11 @@ metadata:
|
||||
The
|
||||
[`backstage.io/techdocs-ref` annotation](../software-catalog/well-known-annotations.md#backstageiotechdocs-ref)
|
||||
is used by TechDocs to download the documentation source files for generating an
|
||||
Entity's TechDocs site.
|
||||
entity's TechDocs site.
|
||||
|
||||
Create a `/docs` folder in the root of the project with at least an `index.md`
|
||||
file. _(If you add more markdown files, make sure to update the nav in the
|
||||
mkdocs.yml file to get a proper navigation for your documentation.)_
|
||||
Create a `/docs` folder in the root of your repository with at least an
|
||||
`index.md` file in it. _(If you add more markdown files, make sure to update the
|
||||
nav in the mkdocs.yml file to get a proper navigation for your documentation.)_
|
||||
|
||||
> Note - Although `docs` is a popular directory name for storing documentation,
|
||||
> it can be renamed to something else and can be configured by `mkdocs.yml`. See
|
||||
@@ -95,9 +114,10 @@ updated documentation next time you run Backstage!
|
||||
|
||||
## Writing and previewing your documentation
|
||||
|
||||
Using the `techdocs-cli` you can preview your docs inside a local Backstage
|
||||
instance and get live reload on changes. This is useful when you want to preview
|
||||
your documentation while writing.
|
||||
Using the [techdocs-cli](https://github.com/backstage/techdocs-cli) you can
|
||||
preview your docs inside a local Backstage instance and get live reload on
|
||||
changes. This is useful when you want to preview your documentation while
|
||||
writing.
|
||||
|
||||
To do this you can run:
|
||||
|
||||
|
||||
@@ -215,10 +215,10 @@ techdocs:
|
||||
publisher:
|
||||
type: 'local'
|
||||
generator:
|
||||
techdocs: local
|
||||
runIn: local
|
||||
```
|
||||
|
||||
Setting `generators.techdocs` to `local` means you will have to make sure your
|
||||
Setting `generator.runIn` to `local` means you will have to make sure your
|
||||
environment is compatible with techdocs.
|
||||
|
||||
You will have to install the `mkdocs` and `mkdocs-techdocs-core` package from
|
||||
|
||||
@@ -110,7 +110,8 @@ TechDocs uses a composability pattern similar to the Search and Catalog plugins
|
||||
in Backstage. While a default table experience, similar to the one provided by
|
||||
the Catalog plugin, is made available for ease-of-use, it's possible for you to
|
||||
provide a completely custom experience, tailored to the needs of your
|
||||
organization.
|
||||
organization. For example, TechDocs comes with an alternative grid based layout
|
||||
(`<EntityListDocsGrid>`).
|
||||
|
||||
This is done in your `app` package. By default, you might see something like
|
||||
this in your `App.tsx`:
|
||||
@@ -348,3 +349,75 @@ const app = createApp({
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## How to add the documentation setup to your software templates
|
||||
|
||||
[Software Templates](https://backstage.io/docs/features/software-templates/software-templates-index)
|
||||
in Backstage is a tool that can help your users to create new components out of
|
||||
already configured templates. It comes with a set of default templates to use,
|
||||
but you can also
|
||||
[add your own templates](https://backstage.io/docs/features/software-templates/adding-templates).
|
||||
|
||||
If you have your own templates set up, we highly recommend that you include the
|
||||
required setup for TechDocs in those templates. When creating a new component,
|
||||
your users will then get a TechDocs site up and running automatically, ready for
|
||||
them to start writing technical documentation.
|
||||
|
||||
The purpose of this how-to guide is to walk you through how to add the required
|
||||
configuration and some default markdown files to your new template. You can use
|
||||
the
|
||||
[react-ssr-template](https://github.com/backstage/software-templates/tree/main/scaffolder-templates/react-ssr-template)
|
||||
as a reference when walking through the steps.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- An existing software template including a `template.yaml` together with a
|
||||
skeleton folder including at least a `catalog-info.yaml`.
|
||||
|
||||
1. Update your component's entity description by adding the following lines to
|
||||
the `catalog-info.yaml` in your skeleton folder.
|
||||
|
||||
```yaml
|
||||
annotations:
|
||||
backstage.io/techdocs-ref: dir:.
|
||||
```
|
||||
|
||||
The
|
||||
[`backstage.io/techdocs-ref` annotation](../software-catalog/well-known-annotations.md#backstageiotechdocs-ref)
|
||||
is used by TechDocs to download the documentation source files for generating an
|
||||
entity's TechDocs site.
|
||||
|
||||
2. Create an `mkdocs.yml` file in the root of your skeleton folder with the
|
||||
following content:
|
||||
|
||||
```yaml
|
||||
site_name: ${{values.component_id}}
|
||||
site_description: ${{values.description}}
|
||||
|
||||
nav:
|
||||
- Introduction: index.md
|
||||
|
||||
plugins:
|
||||
- techdocs-core
|
||||
```
|
||||
|
||||
3. Create a `/docs` folder in the skeleton folder with at least an `index.md`
|
||||
file in it.
|
||||
|
||||
The `docs/index.md` can for example have the following content:
|
||||
|
||||
```md
|
||||
# ${{ values.component_id }}
|
||||
|
||||
${{ values.description }}
|
||||
|
||||
## Getting started
|
||||
|
||||
Start writing your documentation by adding more markdown (.md) files to this
|
||||
folder (/docs) or replace the content in this file.
|
||||
```
|
||||
|
||||
> Note: The values of `site_name`, `component_id` and `site_description` depends
|
||||
> on how you have configured your `template.yaml`
|
||||
|
||||
Done! You now have support for TechDocs in your own software template!
|
||||
|
||||
@@ -96,7 +96,7 @@ yarn start # Start serving the example app, use --check to include type checks a
|
||||
|
||||
yarn storybook # Start local storybook, useful for working on components in @backstage/core-components
|
||||
|
||||
yarn workspace @backstage/plugin-welcome start # Serve welcome plugin only, also supports --check
|
||||
yarn workspace @backstage/plugin-api-docs start # Serve api-docs plugin only, also supports --check
|
||||
|
||||
yarn tsc # Run typecheck, use --watch for watch mode
|
||||
yarn tsc:full # Run full type checking, for example without skipLibCheck, use in CI
|
||||
@@ -139,3 +139,92 @@ default app configs.
|
||||
|
||||
You can learn more about the local configuration in
|
||||
[Static Configuration in Backstage](../conf/) section.
|
||||
|
||||
## Writing changesets
|
||||
|
||||
Changesets are an important part of the development process. They are used to
|
||||
generate Changelog entries for all changes to the project. Ultimately they are
|
||||
read by the end users to learn about important changes and fixes to the project.
|
||||
Some of these fixes might require manual intervention from users so it's
|
||||
important to write changesets that users understand and can take action on.
|
||||
|
||||
Here are some important do's and don'ts when writing changesets:
|
||||
|
||||
### Changeset should give a clear description to what has changed
|
||||
|
||||
#### Bad
|
||||
|
||||
```
|
||||
---
|
||||
'@backstage/catalog': patch
|
||||
---
|
||||
Fixed table layout
|
||||
```
|
||||
|
||||
#### Good
|
||||
|
||||
```
|
||||
---
|
||||
'@backstage/catalog': patch
|
||||
---
|
||||
|
||||
Fixed bug in EntityTable component where table layout did not readjust properly below 1080x768 pixels.
|
||||
```
|
||||
|
||||
### Breaking changes not caught by the type checker should be clearly marked with bold **BREAKING** text
|
||||
|
||||
#### Bad
|
||||
|
||||
```
|
||||
---
|
||||
'@backstage/catalog': minor
|
||||
---
|
||||
|
||||
getEntity is now a function that returns a Promise.
|
||||
```
|
||||
|
||||
#### Good
|
||||
|
||||
```
|
||||
---
|
||||
'@backstage/catalog': minor
|
||||
---
|
||||
|
||||
**BREAKING** The getEntity function now returns a Promise and **must** be awaited from now on.
|
||||
```
|
||||
|
||||
### Changes to code should include a diff of the files that need updating
|
||||
|
||||
#### Bad
|
||||
|
||||
```
|
||||
---
|
||||
'@backstage/catalog': patch
|
||||
---
|
||||
|
||||
**BREAKING** The catalogEngine now requires a flux capacitor to be passed.
|
||||
```
|
||||
|
||||
#### Good
|
||||
|
||||
---
|
||||
'@backstage/catalog': patch
|
||||
---
|
||||
|
||||
**BREAKING** The catalog createRouter now requires that a `FluxCapacitor` is
|
||||
passed to the router.
|
||||
|
||||
These changes are **required** to `packages/backend/src/plugins/catalog.ts`
|
||||
|
||||
```diff
|
||||
+ import { FluxCapacitor } from '@backstage/time';
|
||||
+ const fluxCapacitor = new FluxCapacitor();
|
||||
return await createRouter({
|
||||
entitiesCatalog,
|
||||
locationAnalyzer,
|
||||
locationService,
|
||||
+ fluxCapacitor,
|
||||
logger: env.logger,
|
||||
config: env.config,
|
||||
});
|
||||
```
|
||||
|
||||
@@ -132,56 +132,3 @@ Now you're free to hack away on your own Backstage installation!
|
||||
As you get more experienced with the app, in future you can run just the
|
||||
frontend with `yarn start` in one window, and the backend with
|
||||
`yarn start-backend` in a different window.
|
||||
|
||||
## Linking in local Backstage packages
|
||||
|
||||
It can often be useful to try out changes to the packages in the main Backstage
|
||||
repo within your own app. For example if you want to make modifications to
|
||||
`@backstage/core-plugin-api` and try them out in your app.
|
||||
|
||||
To link in external packages, add them to your `package.json` and `lerna.json`
|
||||
workspace paths. These can be either relative or absolute paths with or without
|
||||
globs. For example:
|
||||
|
||||
```json
|
||||
"packages": [
|
||||
"packages/*",
|
||||
"plugins/*",
|
||||
"../backstage/packages/core-plugin-api", // New path added to work on @backstage/core-plugin-api
|
||||
],
|
||||
```
|
||||
|
||||
Then reinstall packages to make yarn set up symlinks:
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
With this in place you can now modify the `@backstage/core-plugin-api` package
|
||||
within the main repo, and have those changes be reflected and tested in your
|
||||
app. Simply run your app using `yarn dev` (or `yarn start` for just frontend) as
|
||||
normal.
|
||||
|
||||
Note that for backend packages you need to make sure that linked packages are
|
||||
not dependencies of any non-linked package. If you for example want to work on
|
||||
`@backstage/backend-common`, you need to also link in other backend plugins and
|
||||
packages that depend on `@backstage/backend-common`, or temporarily disable
|
||||
those plugins in your backend. This is because the transformation of backend
|
||||
module tree stops whenever a non-local package is encountered, and from that
|
||||
point node will `require` packages directly for that entire module subtree.
|
||||
|
||||
Type checking can also have issues when linking in external packages, since the
|
||||
linked in packages will use the types in the external project and dependency
|
||||
version mismatches between the two projects may cause errors. To fix any of
|
||||
those errors you need to sync versions of the dependencies in the two projects.
|
||||
A simple way to do this can be to copy over `yarn.lock` from the external
|
||||
project and run `yarn install`, although this is quite intrusive and can cause
|
||||
other issues in existing projects, so use this method with care. It can often be
|
||||
best to simply ignore the type errors, as app serving will work just fine
|
||||
anyway.
|
||||
|
||||
Another issue with type checking is that the incremental type cache doesn't
|
||||
invalidate correctly for the linked in packages, causing type checking to not
|
||||
reflect changes made to types. You can work around this by either setting
|
||||
`compilerOptions.incremental = false` in `tsconfig.json`, or by deleting the
|
||||
types cache folder `dist-types` before running `yarn tsc`.
|
||||
|
||||
@@ -4,49 +4,99 @@ title: Getting Started
|
||||
description: Documentation on How to get started with Backstage
|
||||
---
|
||||
|
||||
There are two different ways to get started with Backstage:
|
||||
For most Backstage installations, installing the standalone app will bring you
|
||||
the best and most streamlined experience. In this guide you will:
|
||||
|
||||
- **Recommended:** Create a standalone app
|
||||
- **Contributors:** Clone the Backstage repository
|
||||
- Deploy Backstage Standalone with npm packages
|
||||
- Run Backstage Standalone with a SQLite in-memory database and demo content
|
||||
|
||||
Creating a standalone app makes it simpler to customize the application for your
|
||||
needs and stay up to date with the project. You will depend on `@backstage`
|
||||
packages from npm, making your app much smaller. This is the recommended
|
||||
approach for most installations.
|
||||
This guide assumes a basic understanding of working on a Linux based operating
|
||||
system using tools like apt-get, npm, yarn, curl. Docker knowledge is also
|
||||
helpful for making the best use of your Backstage installation.
|
||||
|
||||
If you want to contribute plugins or to the project in general, it's easier to
|
||||
fork and clone the repository. The `@backstage` packages will be included in the
|
||||
clone. That will let you stay up to date with the latest changes, and give you
|
||||
an easier path to make Pull Requests.
|
||||
If you are planning to contribute plugins or the project in general, we advise
|
||||
you to use the
|
||||
[Getting Started for Contributors](https://backstage.io/docs/getting-started/running-backstage-locally)
|
||||
guide to do a repository-based installation.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Access to a Linux-based operating system, such as Linux, MacOS or
|
||||
[Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/)
|
||||
- An account with elevated rights
|
||||
- `curl` or `wget` installed
|
||||
- Node.js Active LTS Release installed (currently v14) using one of these
|
||||
methods:
|
||||
- Using `nvm` (recommended)
|
||||
- [Installing nvm](https://github.com/nvm-sh/nvm#install--update-script)
|
||||
- [Install and change Node version with nvm](https://nodejs.org/en/download/package-manager/#nvm)
|
||||
- [Binary Download](https://nodejs.org/en/download/)
|
||||
- [Package manager](https://nodejs.org/en/download/package-manager/)
|
||||
- [Using NodeSource packages](https://github.com/nodesource/distributions/blob/master/README.md)
|
||||
- `yarn` [Installation](https://classic.yarnpkg.com/en/docs/install)
|
||||
- `docker` [installation](https://docs.docker.com/engine/install/)
|
||||
- `git` [installation](https://github.com/git-guides/install-git)
|
||||
- If the system is not directly accessible over your network, the following
|
||||
ports need to be opened: 3000, 7000
|
||||
|
||||
### Create your Backstage App
|
||||
|
||||
Backstage provides the `@backstage/create-app` package to scaffold standalone
|
||||
instances of Backstage. You will need to have
|
||||
[Node.js](https://nodejs.org/en/download/) Active LTS Release installed
|
||||
(currently v14) and [Yarn](https://classic.yarnpkg.com/en/docs/install). You
|
||||
will also need to have [Docker](https://docs.docker.com/engine/install/)
|
||||
installed to use some features like Software Templates and TechDocs.
|
||||
|
||||
Using `npx` you can then run the following to create an app in a chosen
|
||||
subdirectory of your current working directory:
|
||||
To install the Backstage Standalone app, we make use of `npx`, a tool to run
|
||||
Node executables straight from the registry. Running the command below will
|
||||
install Backstage. The wizard will create a subdirectory inside your current
|
||||
working directory.
|
||||
|
||||
```bash
|
||||
npx @backstage/create-app
|
||||
```
|
||||
|
||||
You will be taken through a wizard to create your app. You can read more about
|
||||
this process in [Create an app](./create-an-app.md).
|
||||
The wizard will ask you
|
||||
|
||||
### Contributing to Backstage
|
||||
- The name of the app, which will also be the name of the directory
|
||||
- The database type to use for the backend. For this guide, you'll be using the
|
||||
SQLite option.
|
||||
|
||||
If you intend to make changes to the core project's packages, certain plugins,
|
||||
or project documentation, then you can fork and clone
|
||||
[https://github.com/backstage/backstage](https://github.com/backstage/backstage).
|
||||
<p align='center'>
|
||||
<img src='../assets/getting-started/wizard.png' alt='Screenshot of the wizard asking for a name for the app, and a selection menu for the database.'>
|
||||
</p>
|
||||
|
||||
This will let you run the latest code off of the `master` branch, fix bugs or
|
||||
contribute new features, run test suites, etc.
|
||||
### Run the Backstage app
|
||||
|
||||
You can read more in our
|
||||
[CONTRIBUTING](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md)
|
||||
guide, which can help you get setup with a Backstage development environment.
|
||||
When the installation is complete you can go to the application directory and
|
||||
start the app. The `yarn dev` command will run both the frontend and backend as
|
||||
separate processes (named `[0]` and `[1]`) in the same window.
|
||||
|
||||
```bash
|
||||
cd my-backstage-app
|
||||
yarn dev
|
||||
```
|
||||
|
||||
<p align='center'>
|
||||
<img src='../assets/getting-started/startup.png' alt='Screenshot of the command output, with the message web pack compiled successfully.'>
|
||||
</p>
|
||||
|
||||
It might take a little while, but as soon as the message
|
||||
`[0] webpack compiled successfully` appears, you can open a browser and directly
|
||||
navigate to your freshly installed Backstage portal at `http://localhost:3000`.
|
||||
You can start exploring the demo immediately.
|
||||
|
||||
<p align='center'>
|
||||
<img src='../assets/getting-started/portal.png' alt='Screenshot of the Backstage portal.'>
|
||||
</p>
|
||||
|
||||
Congratulations! That should be it. Let us know how it went:
|
||||
[on discord](https://discord.gg/EBHEGzX), file issues for any
|
||||
[feature](https://github.com/backstage/backstage/issues/new?labels=help+wanted&template=feature_template.md)
|
||||
or
|
||||
[plugin suggestions](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME),
|
||||
or
|
||||
[bugs](https://github.com/backstage/backstage/issues/new?labels=bug&template=bug_template.md)
|
||||
you have, and feel free to
|
||||
[contribute](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md)!
|
||||
|
||||
The most common next steps are to configure Backstage, add a plugin and moving
|
||||
to a more persistent database:
|
||||
|
||||
- [Setting up Authentication](https://backstage.io/docs/auth/)
|
||||
- [Switching from SQLite to PostgresQL](https://backstage.io/docs/tutorials/switching-sqlite-postgres)
|
||||
- [Adding a plugin](https://backstage.io/docs/getting-started/configure-app-with-plugins)
|
||||
|
||||
@@ -7,7 +7,7 @@ description: Importing users and groups from a Microsoft Azure Active Directory
|
||||
---
|
||||
|
||||
The Backstage catalog can be set up to ingest organizational data - users and
|
||||
teams - directly from an tenant in Microsoft Azure Active Directory via the
|
||||
teams - directly from a tenant in Microsoft Azure Active Directory via the
|
||||
Microsoft Graph API.
|
||||
|
||||
More details on this are available in the
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
id: installation
|
||||
title: Google Analytics Installation
|
||||
sidebar_label: Installation
|
||||
# prettier-ignore
|
||||
description: Adding Google Analytics to Your App
|
||||
---
|
||||
|
||||
There is a basic
|
||||
[Google Analytics](https://marketingplatform.google.com/about/analytics/)
|
||||
integration built into Backstage. You can enable it by adding the following to
|
||||
your app configuration:
|
||||
|
||||
```yaml
|
||||
app:
|
||||
googleAnalyticsTrackingId: UA-000000-0
|
||||
```
|
||||
|
||||
Replace the tracking ID with the one generated for you after signing up for the
|
||||
Google Analytics service.
|
||||
|
||||
The default behavior is only to send a pageview hit. To record more, review the
|
||||
[Google Analytics developer documentation](https://developers.google.com/analytics/devguides/collection/gtagjs).
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
id: commands
|
||||
title: Commands
|
||||
id: cli-commands
|
||||
title: CLI Commands
|
||||
description: Descriptions of all commands available in the CLI.
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
id: index
|
||||
title: Overview
|
||||
id: cli-overview
|
||||
title: CLI Overview
|
||||
description: Overview of the Backstage CLI
|
||||
---
|
||||
|
||||
@@ -20,7 +20,7 @@ Under the hood the CLI uses [Webpack](https://webpack.js.org/) for bundling,
|
||||
linting. It also includes custom tooling for working within Backstage apps, for
|
||||
example for keeping the app up to date and verifying static configuration.
|
||||
|
||||
For a full list of CLI commands, see the [commands](./commands.md) page.
|
||||
For a full list of CLI commands, see the [commands](./cli-commands.md) page.
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
id: linking-local-packages
|
||||
title: Linking in Local Packages
|
||||
description: How to link in other local packages into your Backstage monorepo
|
||||
---
|
||||
|
||||
It can often be useful to try out changes to the packages in the main Backstage
|
||||
repo within your own app. For example if you want to make modifications to
|
||||
`@backstage/core-plugin-api` and try them out in your app.
|
||||
|
||||
To link in external packages, add them to your `package.json` and `lerna.json`
|
||||
workspace paths. These can be either relative or absolute paths with or without
|
||||
globs. For example:
|
||||
|
||||
```json
|
||||
"packages": [
|
||||
"packages/*",
|
||||
"plugins/*",
|
||||
"../backstage/packages/core-plugin-api", // New path added to work on @backstage/core-plugin-api
|
||||
],
|
||||
```
|
||||
|
||||
Then reinstall packages to make yarn set up symlinks:
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
With this in place you can now modify the `@backstage/core-plugin-api` package
|
||||
within the main repo, and have those changes be reflected and tested in your
|
||||
app. Simply run your app using `yarn dev` (or `yarn start` for just frontend) as
|
||||
normal.
|
||||
|
||||
Note that for backend packages you need to make sure that linked packages are
|
||||
not dependencies of any non-linked package. If you for example want to work on
|
||||
`@backstage/backend-common`, you need to also link in other backend plugins and
|
||||
packages that depend on `@backstage/backend-common`, or temporarily disable
|
||||
those plugins in your backend. This is because the transformation of backend
|
||||
module tree stops whenever a non-local package is encountered, and from that
|
||||
point node will `require` packages directly for that entire module subtree.
|
||||
|
||||
Type checking can also have issues when linking in external packages, since the
|
||||
linked in packages will use the types in the external project and dependency
|
||||
version mismatches between the two projects may cause errors. To fix any of
|
||||
those errors you need to sync versions of the dependencies in the two projects.
|
||||
A simple way to do this can be to copy over `yarn.lock` from the external
|
||||
project and run `yarn install`, although this is quite intrusive and can cause
|
||||
other issues in existing projects, so use this method with care. It can often be
|
||||
best to simply ignore the type errors, as app serving will work just fine
|
||||
anyway.
|
||||
|
||||
Another issue with type checking is that the incremental type cache doesn't
|
||||
invalidate correctly for the linked in packages, causing type checking to not
|
||||
reflect changes made to types. You can work around this by either setting
|
||||
`compilerOptions.incremental = false` in `tsconfig.json`, or by deleting the
|
||||
types cache folder `dist-types` before running `yarn tsc`.
|
||||
@@ -0,0 +1,298 @@
|
||||
---
|
||||
id: analytics
|
||||
title: Plugin Analytics
|
||||
description: Measuring usage of your Backstage instance.
|
||||
---
|
||||
|
||||
Setting up, maintaining, and iterating on an instance of Backstage can be a
|
||||
large investment. To help measure return on this investment, Backstage comes
|
||||
with an event-based Analytics API that grants app integrators the flexibility to
|
||||
collect and analyze Backstage usage in the analytics tool of their choice, while
|
||||
providing plugin developers a standard interface for instrumenting key user
|
||||
interactions.
|
||||
|
||||
## Concepts
|
||||
|
||||
- **Events** consist of, at a minimum, an `action` (like `click`) and a
|
||||
`subject` (like `thing that was clicked on`).
|
||||
- **Attributes** represent additional dimensional data (in the form of key/value
|
||||
pairs) that may be provided on an event-by-event basis. To continue the above
|
||||
example, the URL a user clicked to might look like `{ "to": "/a/page" }`.
|
||||
- **Context** represents the broader context in which an event took place. By
|
||||
default, information like `pluginId`, `extension`, and `routeRef` are
|
||||
provided.
|
||||
|
||||
This composition of events aims to allow analysis at different levels of detail,
|
||||
enabling very granular questions (like "what is the most clicked on thing on a
|
||||
particular route") as well as very high-level questions (like "what is the most
|
||||
used plugin in my Backstage instance") to be answered.
|
||||
|
||||
## Supported Analytics Tools
|
||||
|
||||
While all that's needed to consume and forward these events to an analytics tool
|
||||
is a concrete implementation of [AnalyticsApi][analytics-api-type], common
|
||||
integrations are packaged and provided as plugins. Find your analytics tool of
|
||||
choice below.
|
||||
|
||||
| Analytics Tool | Support Status |
|
||||
| ---------------------- | -------------- |
|
||||
| [Google Analytics][ga] | Yes ✅ |
|
||||
|
||||
To suggest an integration, please [open an issue][add-tool] for the analytics
|
||||
tool your organization uses. Or jump to [Writing Integrations][int-howto] to
|
||||
learn how to contribute the integration yourself!
|
||||
|
||||
[ga]:
|
||||
https://github.com/backstage/backstage/blob/master/plugins/analytics-module-ga/README.md
|
||||
[add-tool]:
|
||||
https://github.com/backstage/backstage/issues/new?assignees=&labels=plugin&template=plugin_template.md&title=%5BAnalytics+Module%5D+THE+ANALYTICS+TOOL+TO+INTEGRATE
|
||||
[int-howto]: #writing-integrations
|
||||
[analytics-api-type]:
|
||||
https://backstage.io/docs/reference/core-plugin-api.analyticsapi
|
||||
|
||||
## Key Events
|
||||
|
||||
The following table summarizes events that, depending on the plugins you have
|
||||
installed, may be captured.
|
||||
|
||||
| Action | Provided By | Subject |
|
||||
| ---------- | -------------- | ----------------------------------------- |
|
||||
| `navigate` | Backstage Core | The URL of the page that was navigated to |
|
||||
| `click` | Backstage Core | The text of the link that was clicked on |
|
||||
|
||||
If there is an event you'd like to see captured, please [open an
|
||||
issue][add-event] describing the event you want to see and the questions it
|
||||
would help you answer. Or jump to [Capturing Events][event-howto] to learn how
|
||||
to contribute the instrumentation yourself!
|
||||
|
||||
_OSS plugin maintainers: feel free to document your events in the table above._
|
||||
|
||||
[add-event]:
|
||||
https://github.com/backstage/backstage/issues/new?assignees=&labels=enhancement&template=feature_template.md&title=[Analytics%20Event]:%20THE+EVENT+TO+CAPTURE
|
||||
[event-howto]: #capturing-events
|
||||
|
||||
## Writing Integrations
|
||||
|
||||
Analytics event forwarding is implemented as a Backstage utility API. Just as
|
||||
you might provide a custom API implementation for errors or SCM Authentication,
|
||||
you can provide one for analytics.
|
||||
|
||||
The provided API need only provide a single method `captureEvent`, which takes
|
||||
an `AnalyticsEvent` object.
|
||||
|
||||
```ts
|
||||
import {
|
||||
analyticsApiRef,
|
||||
AnalyticsEvent,
|
||||
AnyApiFactory,
|
||||
createApiFactory,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
export const apis: AnyApiFactory[] = [
|
||||
createApiFactory(analyticsApiRef, {
|
||||
captureEvent: (event: AnalyticsEvent) => {
|
||||
window._AcmeAnalyticsQ.push(event);
|
||||
},
|
||||
}),
|
||||
];
|
||||
```
|
||||
|
||||
In reality, you would likely want to encapsulate instantiation logic and pull
|
||||
some details from configuration. A more complete example might look like:
|
||||
|
||||
```ts
|
||||
import {
|
||||
AnalyticsApi,
|
||||
analyticsApiRef,
|
||||
AnalyticsEvent,
|
||||
AnyApiFactory,
|
||||
configApiRef,
|
||||
createApiFactory,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { AcmeAnalytics } from 'acme-analytics';
|
||||
|
||||
class AcmeAnalytics implements AnalyticsApi {
|
||||
private constructor(accountId: number) {
|
||||
AcmeAnalytics.init(accountId);
|
||||
}
|
||||
|
||||
static fromConfig(config) {
|
||||
const accountId = config.getString('app.analytics.acme.id');
|
||||
return new AcmeAnalytics(accountId);
|
||||
}
|
||||
|
||||
captureEvent(event: AnalyticsEvent) {
|
||||
const { action, ...rest } = event;
|
||||
AcmeAnalytics.send(action, rest);
|
||||
}
|
||||
}
|
||||
|
||||
export const apis: AnyApiFactory[] = [
|
||||
createApiFactory({
|
||||
api: analyticsApiRef,
|
||||
deps: { configApi: configApiRef },
|
||||
factory: ({ configApi }) => AcmeAnalytics.fromConfig(configApi),
|
||||
}),
|
||||
];
|
||||
```
|
||||
|
||||
If you are integrating with an analytics service (as opposed to an internal
|
||||
tool), consider contributing your API implementation as a plugin!
|
||||
|
||||
By convention, such packages should be named
|
||||
`@backstage/analytics-module-[name]`, and any configuration should be keyed
|
||||
under `app.analytics.[name]`.
|
||||
|
||||
## Capturing Events
|
||||
|
||||
To instrument an event in a component, start by retrieving an analytics tracker
|
||||
using the `useAnalytics()` hook provided by `@backstage/core-plugin-api`. The
|
||||
tracker includes a `captureEvent` method which takes an `action` and a `subject`
|
||||
as arguments.
|
||||
|
||||
```ts
|
||||
import { useAnalytics } from '@backstage/core-plugin-api';
|
||||
|
||||
const analytics = useAnalytics();
|
||||
analytics.captureEvent('deploy', serviceName);
|
||||
```
|
||||
|
||||
### Providing Extra Attributes
|
||||
|
||||
Additional dimensional `attributes` as well as a numeric `value` can be provided
|
||||
on a third `options` argument if/when relevant for the event:
|
||||
|
||||
```ts
|
||||
analytics.captureEvent('merge', pullRequestName, {
|
||||
value: pullRequestAgeInMinutes,
|
||||
attributes: {
|
||||
org,
|
||||
repo,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
In the above example, an event resembling the following object would be
|
||||
captured:
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "merge",
|
||||
"subject": "Name of Pull Request",
|
||||
"value": 60,
|
||||
"attributes": {
|
||||
"org": "some-org",
|
||||
"repo": "some-repo"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Providing Context for Events
|
||||
|
||||
The `attributes` option is good for capturing details available to you within
|
||||
the component that you're instrumenting. For capturing metadata only available
|
||||
further up the react tree, or to help app integrators aggregate distinct events
|
||||
by some common value, use an `<AnalyticsContext>`.
|
||||
|
||||
```tsx
|
||||
import { AnalyticsContext, useAnalytics } from '@backstage/core-plugin-api';
|
||||
|
||||
const MyComponent = ({ value }) => {
|
||||
const analytics = useAnalytics();
|
||||
const handleClick = () => analytics.captureEvent('check', value);
|
||||
return <SomeThing value={value} onClick={handleClick} />;
|
||||
};
|
||||
|
||||
const MyWrapper = () => {
|
||||
return (
|
||||
<AnalyticsContext attributes={{ segment: 'xyz' }}>
|
||||
<MyComponent value={'Some Value'} />
|
||||
</AnalyticsContext>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
In the above example, clicking on `<SomeThing />` would result in an analytics
|
||||
event resembling:
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "check",
|
||||
"subject": "Some Value",
|
||||
"context": {
|
||||
"segment": "xyz"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that, for brevity in the example above, the context keys provided by
|
||||
Backstage core (`pluginId`, `extension`, and `routeRef`) have been omitted. In
|
||||
reality, those details would be included alongside any additional context
|
||||
provided by you.
|
||||
|
||||
Analytics contexts can be nested; their values are merged down the react tree,
|
||||
allowing keys to be overwritten.
|
||||
|
||||
### Event Naming Considerations
|
||||
|
||||
An event is split into its constituent parts to enable analysis at various
|
||||
levels of granularity. In order to maintain this flexibility at analysis-time,
|
||||
it's important to keep each of these levels of detail disaggregated.
|
||||
|
||||
- Avoid providing an overly specific `action`. For example, instead of
|
||||
`filterEntityTable`, consider just using `filter` as the action, and allowing
|
||||
`EntityTable` to be specified as part of the event's `context` (most likely
|
||||
automatically as part of the `extension` in which the `filter` event was
|
||||
captured).
|
||||
|
||||
- On the flip side, when adding `attributes` to an event, look at existing
|
||||
events and see if the data you are capturing matches the intention, type, or
|
||||
even the content of _their_ `attributes`. For instance, it may be common for
|
||||
events that involve the Catalog to add details like entity `name`, `kind`,
|
||||
and/or `namespace` as `attributes`. Using the same keys in your event will
|
||||
ensure that events instrumented across plugins can easily be aggregated.
|
||||
|
||||
### Unit Testing Event Capture
|
||||
|
||||
The `@backstage/test-utils` package includes a `MockAnalyticsApi` implementation
|
||||
that you can use in your unit tests to spy on and make assertions about any
|
||||
analytics events captured.
|
||||
|
||||
Use it like this:
|
||||
|
||||
```tsx
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
import { analyticsApiRef } from '@backstage/core-plugin-api';
|
||||
import { MockAnalyticsApi, wrapInTestApp } from '@backstage/test-utils';
|
||||
import { render, fireEvent, waitFor } from '@testing-library/react';
|
||||
|
||||
describe('SomeComponent', () => {
|
||||
it('should capture event on click', () => {
|
||||
// Use the Mock Analytics API to spy on event captures.
|
||||
const apiSpy = new MockAnalyticsApi();
|
||||
|
||||
// Render the component being tested
|
||||
const { getByText } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={ApiRegistry.from([[analyticsApiRef, apiSpy]])}>
|
||||
<SomeComponentUnderTest />
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
|
||||
// Fire the event that triggers event capture.
|
||||
fireEvent.click(getByText('some component text'));
|
||||
|
||||
// Assert that the event was captured with the expected data.
|
||||
await waitFor(() => {
|
||||
expect(apiSpy.getEvents()[0]).toMatchObject({
|
||||
action: 'expected action',
|
||||
subject: 'expected subject',
|
||||
attributes: {
|
||||
foo: 'bar',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
@@ -10,7 +10,8 @@ A Backstage Plugin adds functionality to Backstage.
|
||||
|
||||
To create a new plugin, make sure you've run `yarn install` and installed
|
||||
dependencies, then run the following on your command line (a shortcut to
|
||||
invoking the [`backstage-cli create-plugin`](../cli/commands.md#create-plugin))
|
||||
invoking the
|
||||
[`backstage-cli create-plugin`](../local-dev/cli-commands.md#create-plugin))
|
||||
from the root of your project.
|
||||
|
||||
```bash
|
||||
|
||||
@@ -36,7 +36,7 @@ that we provide. This gives us a way to automate some of the work required to
|
||||
create a GitHub app.
|
||||
|
||||
You can read more about the
|
||||
[`backstage-cli create-github-app` method](../cli/commands.md#create-github-app).
|
||||
[`backstage-cli create-github-app` method](../local-dev/cli-commands.md#create-github-app).
|
||||
|
||||
Once you've gone through the CLI command, it should produce a YAML file in the
|
||||
root of the project which you can then use as an `include` in your
|
||||
@@ -60,7 +60,7 @@ The YAML file must include the following information. Please note that the
|
||||
indentation for the `privateKey` is required.
|
||||
|
||||
```yaml
|
||||
appId: 1
|
||||
appId: app id
|
||||
clientId: client id
|
||||
clientSecret: client secret
|
||||
webhookSecret: webhook secret
|
||||
@@ -95,7 +95,7 @@ If you want to limit the GitHub app installations visible to backstage you may
|
||||
optionally include the `allowedInstallationOwners` option.
|
||||
|
||||
```yaml
|
||||
appId: 1
|
||||
appId: app id
|
||||
allowedInstallationOwners: ['GlobexCorp']
|
||||
clientId: client id
|
||||
clientSecret: client secret
|
||||
|
||||
@@ -8,11 +8,6 @@ description: Adding Observability to Your Plugin
|
||||
This article briefly describes the observability options that are available to a
|
||||
Backstage integrator.
|
||||
|
||||
## Google Analytics
|
||||
|
||||
See how to install Google Analytics in your app
|
||||
[here](../integrations/google-analytics/installation.md)
|
||||
|
||||
## Datadog RUM Events
|
||||
|
||||
See how to install Datadog Events in your app
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: 'Analytics Module: Google Analytics'
|
||||
author: Spotify
|
||||
authorUrl: https://github.com/spotify
|
||||
category: Analytics
|
||||
description: Track usage of your Backstage instance using Google Analytics.
|
||||
documentation: https://github.com/backstage/backstage/blob/master/plugins/analytics-module-ga/README.md
|
||||
iconUrl: img/ga-icon.png
|
||||
npmPackageName: '@backstage/plugin-analytics-module-ga'
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: GKE Usage
|
||||
author: BESTSELLER
|
||||
authorUrl: bestsellerit.com
|
||||
authorUrl: https://bestsellerit.com
|
||||
category: Discovery
|
||||
description: This plugin will show you the cost and resource usage of your application within Google Kubernetes Engine (GKE).
|
||||
documentation: https://github.com/BESTSELLER/backstage-plugin-gkeusage/blob/master/README.md
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Grafana
|
||||
author: K-Phoen
|
||||
authorUrl: https://github.com/K-Phoen
|
||||
category: Monitoring
|
||||
description: Associate alerts and dashboards to components.
|
||||
documentation: https://github.com/K-Phoen/backstage-plugin-grafana/
|
||||
iconUrl: https://avatars.githubusercontent.com/u/7195757?s=200&v=4
|
||||
npmPackageName: '@k-phoen/backstage-plugin-grafana'
|
||||
tags:
|
||||
- dashboards
|
||||
- monitoring
|
||||
- alerting
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Harbor
|
||||
author: BESTSELLER
|
||||
authorUrl: bestsellerit.com
|
||||
authorUrl: https://bestsellerit.com
|
||||
category: Discovery
|
||||
description: This plugin will show you information about Docker images within the Harbor cloud native registry.
|
||||
documentation: https://github.com/BESTSELLER/backstage-plugin-harbor/blob/master/README.md
|
||||
|
||||
+14
-9
@@ -29,7 +29,14 @@
|
||||
"getting-started/contributors",
|
||||
"getting-started/project-structure"
|
||||
],
|
||||
"CLI": ["cli/index", "cli/commands"],
|
||||
"Local Development": [
|
||||
{
|
||||
"type": "subcategory",
|
||||
"label": "CLI",
|
||||
"ids": ["local-dev/cli-overview", "local-dev/cli-commands"]
|
||||
},
|
||||
"local-dev/linking-local-packages"
|
||||
],
|
||||
"Core Features": [
|
||||
{
|
||||
"type": "subcategory",
|
||||
@@ -71,8 +78,7 @@
|
||||
"features/software-templates/builtin-actions",
|
||||
"features/software-templates/writing-custom-actions",
|
||||
"features/software-templates/writing-custom-field-extensions",
|
||||
"features/software-templates/template-legacy",
|
||||
"features/software-templates/migrating-from-v1alpha1-to-v1beta2"
|
||||
"features/software-templates/migrating-from-v1beta2-to-v1beta3"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -83,7 +89,8 @@
|
||||
"features/search/getting-started",
|
||||
"features/search/concepts",
|
||||
"features/search/architecture",
|
||||
"features/search/search-engines"
|
||||
"features/search/search-engines",
|
||||
"features/search/how-to-guides"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -146,11 +153,6 @@
|
||||
"label": "GitLab",
|
||||
"ids": ["integrations/gitlab/locations"]
|
||||
},
|
||||
{
|
||||
"type": "subcategory",
|
||||
"label": "Google Analytics",
|
||||
"ids": ["integrations/google-analytics/installation"]
|
||||
},
|
||||
{
|
||||
"type": "subcategory",
|
||||
"label": "Google GCS",
|
||||
@@ -170,6 +172,7 @@
|
||||
"plugins/structure-of-a-plugin",
|
||||
"plugins/integrating-plugin-into-software-catalog",
|
||||
"plugins/composability",
|
||||
"plugins/analytics",
|
||||
{
|
||||
"type": "subcategory",
|
||||
"label": "Backends and APIs",
|
||||
@@ -210,6 +213,8 @@
|
||||
"label": "Included providers",
|
||||
"ids": [
|
||||
"auth/auth0/provider",
|
||||
"auth/atlassian/provider",
|
||||
"auth/bitbucket/provider",
|
||||
"auth/microsoft/provider",
|
||||
"auth/github/provider",
|
||||
"auth/gitlab/provider",
|
||||
|
||||
@@ -1217,3 +1217,7 @@ code {
|
||||
.medium-zoom-image {
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
h3.collapsible span.arrow {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
+7
-5
@@ -27,9 +27,11 @@ nav:
|
||||
- Key Concepts: 'getting-started/concepts.md'
|
||||
- Contributors: 'getting-started/contributors.md'
|
||||
- Project Structure: 'getting-started/project-structure.md'
|
||||
- CLI:
|
||||
- Overview: 'cli/index.md'
|
||||
- Commands: 'cli/commands.md'
|
||||
- Local Development:
|
||||
- CLI:
|
||||
- Overview: 'local-dev/cli-overview.md'
|
||||
- Commands: 'local-dev/cli-commands.md'
|
||||
- Linking in Local Packages: 'local-dev/linking-local-packages.md'
|
||||
- Core Features:
|
||||
- Software Catalog:
|
||||
- Overview: 'features/software-catalog/index.md'
|
||||
@@ -66,6 +68,7 @@ nav:
|
||||
- Concepts: 'features/search/concepts.md'
|
||||
- Search Architecture: 'features/search/architecture.md'
|
||||
- Search Engines: 'features/search/search-engines.md'
|
||||
- HOW TO guides: 'features/search/how-to-guides.md'
|
||||
- TechDocs:
|
||||
- Overview: 'features/techdocs/README.md'
|
||||
- Getting Started: 'features/techdocs/getting-started.md'
|
||||
@@ -97,8 +100,6 @@ nav:
|
||||
- Org Data: 'integrations/github/org.md'
|
||||
- GitLab:
|
||||
- Locations: 'integrations/gitlab/locations.md'
|
||||
- Google Analytics:
|
||||
- Installation: 'integrations/google-analytics/installation.md'
|
||||
- Google GCS:
|
||||
- Locations: 'integrations/google-cloud-storage/locations.md'
|
||||
- LDAP:
|
||||
@@ -112,6 +113,7 @@ nav:
|
||||
- Plugin Development: 'plugins/plugin-development.md'
|
||||
- Integrate into the Software Catalog: 'plugins/integrating-plugin-into-software-catalog.md'
|
||||
- Composability System: 'plugins/composability.md'
|
||||
- Plugin Analytics: 'plugins/analytics.md'
|
||||
- Backends and APIs:
|
||||
- Proxying: 'plugins/proxying.md'
|
||||
- Backend plugin: 'plugins/backend-plugin.md'
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
"devDependencies": {
|
||||
"@types/webpack": "^5.28.0",
|
||||
"@changesets/cli": "^2.14.0",
|
||||
"@octokit/openapi-types": "^2.2.0",
|
||||
"@spotify/prettier-config": "^11.0.0",
|
||||
"command-exists": "^1.2.9",
|
||||
"concurrently": "^6.0.0",
|
||||
@@ -71,7 +70,6 @@
|
||||
"lerna": "^4.0.0",
|
||||
"lint-staged": "^11.1.2",
|
||||
"prettier": "^2.2.1",
|
||||
"recursive-readdir": "^2.2.2",
|
||||
"shx": "^0.3.2",
|
||||
"yarn-lock-check": "^1.0.5"
|
||||
},
|
||||
@@ -87,10 +85,5 @@
|
||||
"*.md": [
|
||||
"node ./scripts/check-docs-quality"
|
||||
]
|
||||
},
|
||||
"jest": {
|
||||
"transformModules": [
|
||||
"@asyncapi/react-component"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,67 @@
|
||||
# example-app
|
||||
|
||||
## 0.2.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.7.1
|
||||
- @backstage/plugin-techdocs@0.12.3
|
||||
- @backstage/plugin-sentry@0.3.26
|
||||
- @backstage/plugin-user-settings@0.3.10
|
||||
- @backstage/plugin-catalog-graph@0.2.1
|
||||
- @backstage/plugin-jenkins@0.5.11
|
||||
- @backstage/core-app-api@0.1.18
|
||||
- @backstage/core-plugin-api@0.1.11
|
||||
- @backstage/cli@0.8.0
|
||||
- @backstage/plugin-catalog@0.7.2
|
||||
- @backstage/plugin-catalog-import@0.7.3
|
||||
- @backstage/plugin-catalog-react@0.6.1
|
||||
- @backstage/catalog-model@0.9.5
|
||||
|
||||
## 0.2.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-catalog-react@0.6.0
|
||||
- @backstage/plugin-catalog@0.7.1
|
||||
- @backstage/plugin-api-docs@0.6.12
|
||||
- @backstage/plugin-scaffolder@0.11.8
|
||||
- @backstage/core-app-api@0.1.17
|
||||
- @backstage/core-components@0.7.0
|
||||
- @backstage/theme@0.2.11
|
||||
- @backstage/plugin-graphiql@0.2.20
|
||||
- @backstage/cli@0.7.16
|
||||
- @backstage/plugin-home@0.4.4
|
||||
- @backstage/plugin-catalog-graph@0.2.0
|
||||
- @backstage/plugin-search@0.4.15
|
||||
- @backstage/plugin-techdocs@0.12.2
|
||||
- @backstage/plugin-kubernetes@0.4.17
|
||||
- @backstage/plugin-azure-devops@0.1.1
|
||||
- @backstage/plugin-badges@0.2.13
|
||||
- @backstage/plugin-catalog-import@0.7.2
|
||||
- @backstage/plugin-circleci@0.2.27
|
||||
- @backstage/plugin-cloudbuild@0.2.27
|
||||
- @backstage/plugin-code-coverage@0.1.15
|
||||
- @backstage/plugin-explore@0.3.20
|
||||
- @backstage/plugin-github-actions@0.4.22
|
||||
- @backstage/plugin-jenkins@0.5.10
|
||||
- @backstage/plugin-kafka@0.2.19
|
||||
- @backstage/plugin-lighthouse@0.2.29
|
||||
- @backstage/plugin-org@0.3.27
|
||||
- @backstage/plugin-pagerduty@0.3.17
|
||||
- @backstage/plugin-rollbar@0.3.18
|
||||
- @backstage/plugin-sentry@0.3.25
|
||||
- @backstage/plugin-todo@0.1.14
|
||||
- @backstage/integration-react@0.1.12
|
||||
- @backstage/plugin-cost-insights@0.11.10
|
||||
- @backstage/plugin-gcp-projects@0.3.8
|
||||
- @backstage/plugin-newrelic@0.3.8
|
||||
- @backstage/plugin-shortcuts@0.1.12
|
||||
- @backstage/plugin-tech-radar@0.4.11
|
||||
- @backstage/plugin-user-settings@0.3.9
|
||||
|
||||
## 0.2.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
+41
-40
@@ -1,48 +1,49 @@
|
||||
{
|
||||
"name": "example-app",
|
||||
"version": "0.2.49",
|
||||
"version": "0.2.51",
|
||||
"private": true,
|
||||
"bundled": true,
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^0.9.4",
|
||||
"@backstage/cli": "^0.7.15",
|
||||
"@backstage/core-app-api": "^0.1.16",
|
||||
"@backstage/core-components": "^0.6.1",
|
||||
"@backstage/core-plugin-api": "^0.1.10",
|
||||
"@backstage/integration-react": "^0.1.11",
|
||||
"@backstage/plugin-api-docs": "^0.6.11",
|
||||
"@backstage/plugin-badges": "^0.2.12",
|
||||
"@backstage/plugin-catalog": "^0.7.0",
|
||||
"@backstage/plugin-catalog-graph": "^0.1.3",
|
||||
"@backstage/plugin-catalog-import": "^0.7.1",
|
||||
"@backstage/plugin-catalog-react": "^0.5.2",
|
||||
"@backstage/plugin-circleci": "^0.2.26",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.26",
|
||||
"@backstage/plugin-code-coverage": "^0.1.14",
|
||||
"@backstage/plugin-cost-insights": "^0.11.9",
|
||||
"@backstage/plugin-explore": "^0.3.19",
|
||||
"@backstage/plugin-gcp-projects": "^0.3.7",
|
||||
"@backstage/plugin-github-actions": "^0.4.21",
|
||||
"@backstage/plugin-graphiql": "^0.2.19",
|
||||
"@backstage/plugin-home": "^0.4.3",
|
||||
"@backstage/plugin-jenkins": "^0.5.9",
|
||||
"@backstage/plugin-kafka": "^0.2.18",
|
||||
"@backstage/plugin-kubernetes": "^0.4.16",
|
||||
"@backstage/plugin-lighthouse": "^0.2.28",
|
||||
"@backstage/plugin-newrelic": "^0.3.7",
|
||||
"@backstage/plugin-org": "^0.3.26",
|
||||
"@backstage/plugin-pagerduty": "0.3.16",
|
||||
"@backstage/plugin-rollbar": "^0.3.17",
|
||||
"@backstage/plugin-scaffolder": "^0.11.7",
|
||||
"@backstage/plugin-search": "^0.4.14",
|
||||
"@backstage/plugin-sentry": "^0.3.24",
|
||||
"@backstage/plugin-shortcuts": "^0.1.11",
|
||||
"@backstage/plugin-tech-radar": "^0.4.10",
|
||||
"@backstage/plugin-techdocs": "^0.12.1",
|
||||
"@backstage/plugin-todo": "^0.1.13",
|
||||
"@backstage/plugin-user-settings": "^0.3.8",
|
||||
"@backstage/catalog-model": "^0.9.5",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@backstage/core-app-api": "^0.1.18",
|
||||
"@backstage/core-components": "^0.7.1",
|
||||
"@backstage/core-plugin-api": "^0.1.11",
|
||||
"@backstage/integration-react": "^0.1.12",
|
||||
"@backstage/plugin-api-docs": "^0.6.12",
|
||||
"@backstage/plugin-azure-devops": "^0.1.1",
|
||||
"@backstage/plugin-badges": "^0.2.13",
|
||||
"@backstage/plugin-catalog": "^0.7.2",
|
||||
"@backstage/plugin-catalog-graph": "^0.2.1",
|
||||
"@backstage/plugin-catalog-import": "^0.7.3",
|
||||
"@backstage/plugin-catalog-react": "^0.6.1",
|
||||
"@backstage/plugin-circleci": "^0.2.27",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.27",
|
||||
"@backstage/plugin-code-coverage": "^0.1.15",
|
||||
"@backstage/plugin-cost-insights": "^0.11.10",
|
||||
"@backstage/plugin-explore": "^0.3.20",
|
||||
"@backstage/plugin-gcp-projects": "^0.3.8",
|
||||
"@backstage/plugin-github-actions": "^0.4.22",
|
||||
"@backstage/plugin-graphiql": "^0.2.20",
|
||||
"@backstage/plugin-home": "^0.4.4",
|
||||
"@backstage/plugin-jenkins": "^0.5.11",
|
||||
"@backstage/plugin-kafka": "^0.2.19",
|
||||
"@backstage/plugin-kubernetes": "^0.4.17",
|
||||
"@backstage/plugin-lighthouse": "^0.2.29",
|
||||
"@backstage/plugin-newrelic": "^0.3.8",
|
||||
"@backstage/plugin-org": "^0.3.27",
|
||||
"@backstage/plugin-pagerduty": "0.3.17",
|
||||
"@backstage/plugin-rollbar": "^0.3.18",
|
||||
"@backstage/plugin-scaffolder": "^0.11.8",
|
||||
"@backstage/plugin-search": "^0.4.15",
|
||||
"@backstage/plugin-sentry": "^0.3.26",
|
||||
"@backstage/plugin-shortcuts": "^0.1.12",
|
||||
"@backstage/plugin-tech-radar": "^0.4.11",
|
||||
"@backstage/plugin-techdocs": "^0.12.3",
|
||||
"@backstage/plugin-todo": "^0.1.14",
|
||||
"@backstage/plugin-user-settings": "^0.3.10",
|
||||
"@backstage/search-common": "^0.2.0",
|
||||
"@backstage/theme": "^0.2.10",
|
||||
"@backstage/theme": "^0.2.11",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
@@ -62,7 +63,7 @@
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/test-utils": "^0.1.18",
|
||||
"@backstage/test-utils": "^0.1.19",
|
||||
"@rjsf/core": "^3.0.0",
|
||||
"@testing-library/cypress": "^7.0.1",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
window,
|
||||
document,
|
||||
'script',
|
||||
'https://www.datadoghq-browser-agent.com/datadog-rum.js',
|
||||
'https://www.datadoghq-browser-agent.com/datadog-rum-v3.js',
|
||||
'DD_RUM',
|
||||
);
|
||||
DD_RUM.onReady(function () {
|
||||
|
||||
@@ -14,13 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EntityLayout } from '@backstage/plugin-catalog';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { cicdContent } from './EntityPage';
|
||||
import { githubActionsApiRef } from '@backstage/plugin-github-actions';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
import { EntityLayout } from '@backstage/plugin-catalog';
|
||||
import {
|
||||
DefaultStarredEntitiesApi,
|
||||
EntityProvider,
|
||||
starredEntitiesApiRef,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { githubActionsApiRef } from '@backstage/plugin-github-actions';
|
||||
import { MockStorageApi, renderInTestApp } from '@backstage/test-utils';
|
||||
import React from 'react';
|
||||
import { cicdContent } from './EntityPage';
|
||||
|
||||
describe('EntityPage Test', () => {
|
||||
const entity = {
|
||||
@@ -48,7 +52,10 @@ describe('EntityPage Test', () => {
|
||||
downloadJobLogsForWorkflowRun: jest.fn(),
|
||||
} as jest.Mocked<typeof githubActionsApiRef.T>;
|
||||
|
||||
const apis = ApiRegistry.with(githubActionsApiRef, mockedApi);
|
||||
const apis = ApiRegistry.with(githubActionsApiRef, mockedApi).with(
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({ storageApi: MockStorageApi.create() }),
|
||||
);
|
||||
|
||||
describe('cicdContent', () => {
|
||||
it('Should render GitHub Actions View', async () => {
|
||||
|
||||
@@ -33,6 +33,10 @@ import {
|
||||
EntityProvidedApisCard,
|
||||
EntityProvidingComponentsCard,
|
||||
} from '@backstage/plugin-api-docs';
|
||||
import {
|
||||
EntityAzurePipelinesContent,
|
||||
isAzureDevOpsAvailable,
|
||||
} from '@backstage/plugin-azure-devops';
|
||||
import { EntityBadgesDialog } from '@backstage/plugin-badges';
|
||||
import {
|
||||
EntityAboutCard,
|
||||
@@ -183,6 +187,10 @@ export const cicdContent = (
|
||||
<EntityGithubActionsContent />
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case if={isAzureDevOpsAvailable}>
|
||||
<EntityAzurePipelinesContent defaultLimit={25} />
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case>
|
||||
<EmptyState
|
||||
title="No CI/CD available for this entity"
|
||||
|
||||
@@ -14,26 +14,43 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import {
|
||||
HomePageRandomJoke,
|
||||
ComponentAccordion,
|
||||
ComponentTabs,
|
||||
ComponentTab,
|
||||
WelcomeTitle,
|
||||
HeaderWorldClock,
|
||||
ClockConfig,
|
||||
} from '@backstage/plugin-home';
|
||||
import {
|
||||
Content,
|
||||
Header,
|
||||
Page,
|
||||
HomepageTimer,
|
||||
} from '@backstage/core-components';
|
||||
import { Content, Header, Page } from '@backstage/core-components';
|
||||
import { HomePageSearchBar } from '@backstage/plugin-search';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import React from 'react';
|
||||
|
||||
const clockConfigs: ClockConfig[] = [
|
||||
{
|
||||
label: 'NYC',
|
||||
timeZone: 'America/New_York',
|
||||
},
|
||||
{
|
||||
label: 'UTC',
|
||||
timeZone: 'UTC',
|
||||
},
|
||||
{
|
||||
label: 'STO',
|
||||
timeZone: 'Europe/Stockholm',
|
||||
},
|
||||
{
|
||||
label: 'TYO',
|
||||
timeZone: 'Asia/Tokyo',
|
||||
},
|
||||
];
|
||||
|
||||
export const HomePage = () => (
|
||||
<Page themeId="home">
|
||||
<Header title="Home">
|
||||
<HomepageTimer />
|
||||
<Header title={<WelcomeTitle />} pageTitleOverride="Home">
|
||||
<HeaderWorldClock clockConfigs={clockConfigs} />
|
||||
</Header>
|
||||
<Content>
|
||||
<Grid container spacing={3}>
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/backend-common
|
||||
|
||||
## 0.9.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- be59619212: Add "rate limit exceeded" to error from GithubUrlReader if that is the cause of a read failure
|
||||
- 36e67d2f24: Internal updates to apply more strict checks to throw errors.
|
||||
- Updated dependencies
|
||||
- @backstage/config-loader@0.7.0
|
||||
- @backstage/errors@0.1.3
|
||||
|
||||
## 0.9.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -18,7 +18,7 @@ import { GithubCredentialsProvider } from '@backstage/integration';
|
||||
import { GitHubIntegration } from '@backstage/integration';
|
||||
import { GitLabIntegration } from '@backstage/integration';
|
||||
import { isChildPath } from '@backstage/cli-common';
|
||||
import { JsonValue } from '@backstage/config';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { Knex } from 'knex';
|
||||
import { Logger as Logger_2 } from 'winston';
|
||||
import { MergeResult } from 'isomorphic-git';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-common",
|
||||
"description": "Common functionality library for Backstage backends",
|
||||
"version": "0.9.6",
|
||||
"version": "0.9.7",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -31,9 +31,10 @@
|
||||
"dependencies": {
|
||||
"@backstage/cli-common": "^0.1.4",
|
||||
"@backstage/config": "^0.1.10",
|
||||
"@backstage/config-loader": "^0.6.10",
|
||||
"@backstage/errors": "^0.1.2",
|
||||
"@backstage/config-loader": "^0.7.0",
|
||||
"@backstage/errors": "^0.1.3",
|
||||
"@backstage/integration": "^0.6.7",
|
||||
"@backstage/types": "^0.1.1",
|
||||
"@google-cloud/storage": "^5.8.0",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
"@types/cors": "^2.8.6",
|
||||
@@ -77,7 +78,7 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.15",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@backstage/test-utils": "^0.1.18",
|
||||
"@types/archiver": "^5.1.0",
|
||||
"@types/compression": "^1.7.0",
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { JsonValue } from '@backstage/config';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { createHash } from 'crypto';
|
||||
import Keyv from 'keyv';
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ import { resolve as resolvePath } from 'path';
|
||||
import parseArgs from 'minimist';
|
||||
import { Logger } from 'winston';
|
||||
import { findPaths } from '@backstage/cli-common';
|
||||
import { Config, ConfigReader, JsonValue } from '@backstage/config';
|
||||
import { Config, ConfigReader } from '@backstage/config';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
|
||||
export class ObservableConfigProxy implements Config {
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
*/
|
||||
import { Knex } from 'knex';
|
||||
import { omit } from 'lodash';
|
||||
import { Config, ConfigReader, JsonObject } from '@backstage/config';
|
||||
import { Config, ConfigReader } from '@backstage/config';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import {
|
||||
createDatabaseClient,
|
||||
ensureDatabaseExists,
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Config, JsonObject } from '@backstage/config';
|
||||
import { Config } from '@backstage/config';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { InputError } from '@backstage/errors';
|
||||
import knexFactory, { Knex } from 'knex';
|
||||
import { mergeDatabaseConfig } from './config';
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import knexFactory, { Knex } from 'knex';
|
||||
|
||||
import { Config } from '@backstage/config';
|
||||
import { ForwardedError } from '@backstage/errors';
|
||||
import { mergeDatabaseConfig } from '../config';
|
||||
import { DatabaseConnector } from '../types';
|
||||
import defaultNameOverride from './defaultNameOverride';
|
||||
@@ -94,8 +95,7 @@ function requirePgConnectionString() {
|
||||
try {
|
||||
return require('pg-connection-string').parse;
|
||||
} catch (e) {
|
||||
const message = `Postgres: Install 'pg-connection-string'`;
|
||||
throw new Error(`${message}\n${e.message}`);
|
||||
throw new ForwardedError("Postgres: Install 'pg-connection-string'", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ConfigReader, JsonObject } from '@backstage/config';
|
||||
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { getVoidLogger } from '../logging';
|
||||
import { DefaultReadTreeResponseFactory } from './tree';
|
||||
import { AwsS3UrlReader } from './AwsS3UrlReader';
|
||||
@@ -135,13 +137,7 @@ describe('AwsS3UrlReader', () => {
|
||||
'getObject',
|
||||
Buffer.from(
|
||||
require('fs').readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'awsS3',
|
||||
'awsS3-mock-object.yaml',
|
||||
),
|
||||
path.resolve(__dirname, '__fixtures__/awsS3/awsS3-mock-object.yaml'),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -173,7 +169,7 @@ describe('AwsS3UrlReader', () => {
|
||||
),
|
||||
).rejects.toThrow(
|
||||
Error(
|
||||
`Could not retrieve file from S3: not a valid AWS S3 URL: https://test-bucket.s3.us-east-2.NOTamazonaws.com/file.yaml`,
|
||||
`Could not retrieve file from S3; caused by Error: not a valid AWS S3 URL: https://test-bucket.s3.us-east-2.NOTamazonaws.com/file.yaml`,
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -187,13 +183,7 @@ describe('AwsS3UrlReader', () => {
|
||||
'getObject',
|
||||
Buffer.from(
|
||||
require('fs').readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'awsS3',
|
||||
'awsS3-mock-object.yaml',
|
||||
),
|
||||
path.resolve(__dirname, '__fixtures__/awsS3/awsS3-mock-object.yaml'),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -228,7 +218,7 @@ describe('AwsS3UrlReader', () => {
|
||||
),
|
||||
).rejects.toThrow(
|
||||
Error(
|
||||
`Could not retrieve file from S3: not a valid AWS S3 URL: https://test-bucket.s3.us-east-2.NOTamazonaws.com/file.yaml`,
|
||||
`Could not retrieve file from S3; caused by Error: not a valid AWS S3 URL: https://test-bucket.s3.us-east-2.NOTamazonaws.com/file.yaml`,
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -249,13 +239,7 @@ describe('AwsS3UrlReader', () => {
|
||||
'getObject',
|
||||
Buffer.from(
|
||||
require('fs').readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'awsS3',
|
||||
'awsS3-mock-object.yaml',
|
||||
),
|
||||
path.resolve(__dirname, '__fixtures__/awsS3/awsS3-mock-object.yaml'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
} from './types';
|
||||
import getRawBody from 'raw-body';
|
||||
import { AwsS3Integration, ScmIntegrations } from '@backstage/integration';
|
||||
import { ForwardedError } from '@backstage/errors';
|
||||
import { ListObjectsV2Output, ObjectList } from 'aws-sdk/clients/s3';
|
||||
|
||||
const parseURL = (
|
||||
@@ -162,7 +163,7 @@ export class AwsS3UrlReader implements UrlReader {
|
||||
etag: etag,
|
||||
};
|
||||
} catch (e) {
|
||||
throw new Error(`Could not retrieve file from S3: ${e.message}`);
|
||||
throw new ForwardedError('Could not retrieve file from S3', e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +204,7 @@ export class AwsS3UrlReader implements UrlReader {
|
||||
|
||||
return await this.deps.treeResponseFactory.fromReadableArray(responses);
|
||||
} catch (e) {
|
||||
throw new Error(`Could not retrieve file tree from S3: ${e.message}`);
|
||||
throw new ForwardedError('Could not retrieve file tree from S3', e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ describe('AzureUrlReader', () => {
|
||||
|
||||
describe('readTree', () => {
|
||||
const repoBuffer = fs.readFileSync(
|
||||
path.resolve('src', 'reading', '__fixtures__', 'mock-main.zip'),
|
||||
path.resolve(__dirname, '__fixtures__/mock-main.zip'),
|
||||
);
|
||||
|
||||
const processor = new AzureUrlReader(
|
||||
@@ -264,7 +264,7 @@ describe('AzureUrlReader', () => {
|
||||
|
||||
describe('search', () => {
|
||||
const repoBuffer = fs.readFileSync(
|
||||
path.resolve('src', 'reading', '__fixtures__', 'mock-main.zip'),
|
||||
path.resolve(__dirname, '__fixtures__/mock-main.zip'),
|
||||
);
|
||||
|
||||
const processor = new AzureUrlReader(
|
||||
|
||||
@@ -104,20 +104,13 @@ describe('BitbucketUrlReader', () => {
|
||||
describe('readTree', () => {
|
||||
const repoBuffer = fs.readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'bitbucket-repo-with-commit-hash.tar.gz',
|
||||
__dirname,
|
||||
'__fixtures__/bitbucket-repo-with-commit-hash.tar.gz',
|
||||
),
|
||||
);
|
||||
|
||||
const privateBitbucketRepoBuffer = fs.readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'bitbucket-server-repo.tar.gz',
|
||||
),
|
||||
path.resolve(__dirname, '__fixtures__/bitbucket-server-repo.tar.gz'),
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -298,10 +291,8 @@ describe('BitbucketUrlReader', () => {
|
||||
describe('search hosted', () => {
|
||||
const repoBuffer = fs.readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'bitbucket-repo-with-commit-hash.tar.gz',
|
||||
__dirname,
|
||||
'__fixtures__/bitbucket-repo-with-commit-hash.tar.gz',
|
||||
),
|
||||
);
|
||||
|
||||
@@ -386,12 +377,7 @@ describe('BitbucketUrlReader', () => {
|
||||
|
||||
describe('search private', () => {
|
||||
const privateBitbucketRepoBuffer = fs.readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'bitbucket-server-repo.tar.gz',
|
||||
),
|
||||
path.resolve(__dirname, '__fixtures__/bitbucket-server-repo.tar.gz'),
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -221,6 +221,32 @@ describe('GithubUrlReader', () => {
|
||||
).rejects.toThrow(NotModifiedError);
|
||||
});
|
||||
|
||||
it('should throw Error with ratelimit exceeded if GitHub responds with 403 and rate limit is exceeded', async () => {
|
||||
expect.assertions(1);
|
||||
|
||||
worker.use(
|
||||
rest.get(
|
||||
'https://ghe.github.com/api/v3/repos/backstage/mock/tree/contents/',
|
||||
(_req, res, ctx) => {
|
||||
return res(
|
||||
ctx.status(403),
|
||||
ctx.set('X-RateLimit-Remaining', '0'),
|
||||
ctx.body(
|
||||
'{"message": "API rate limit exceeded for xxx.xxx.xxx.xxx..."}',
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
await expect(
|
||||
gheProcessor.readUrl(
|
||||
'https://github.com/backstage/mock/tree/blob/main',
|
||||
{ etag: 'foo' },
|
||||
),
|
||||
).rejects.toThrow(/rate limit exceeded/);
|
||||
});
|
||||
|
||||
it('should return etag from the response', async () => {
|
||||
(mockCredentialsProvider.getCredentials as jest.Mock).mockResolvedValue({
|
||||
headers: {
|
||||
@@ -254,12 +280,7 @@ describe('GithubUrlReader', () => {
|
||||
|
||||
describe('readTree', () => {
|
||||
const repoBuffer = fs.readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'backstage-mock-etag123.tar.gz',
|
||||
),
|
||||
path.resolve(__dirname, '__fixtures__/backstage-mock-etag123.tar.gz'),
|
||||
);
|
||||
|
||||
const reposGithubApiResponse = {
|
||||
@@ -540,12 +561,7 @@ describe('GithubUrlReader', () => {
|
||||
|
||||
describe('search', () => {
|
||||
const repoBuffer = fs.readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'backstage-mock-etag123.tar.gz',
|
||||
),
|
||||
path.resolve(__dirname, '__fixtures__/backstage-mock-etag123.tar.gz'),
|
||||
);
|
||||
|
||||
const githubTreeContents: GhTreeResponse['tree'] = [
|
||||
|
||||
@@ -126,10 +126,21 @@ export class GithubUrlReader implements UrlReader {
|
||||
};
|
||||
}
|
||||
|
||||
const message = `${url} could not be read as ${ghUrl}, ${response.status} ${response.statusText}`;
|
||||
let message = `${url} could not be read as ${ghUrl}, ${response.status} ${response.statusText}`;
|
||||
if (response.status === 404) {
|
||||
throw new NotFoundError(message);
|
||||
}
|
||||
|
||||
// GitHub returns a 403 response with a couple of headers indicating rate
|
||||
// limit status. See more in the GitHub docs:
|
||||
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting
|
||||
if (
|
||||
response.status === 403 &&
|
||||
response.headers.get('X-RateLimit-Remaining') === '0'
|
||||
) {
|
||||
message += ' (rate limit exceeded)';
|
||||
}
|
||||
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ describe('GitlabUrlReader', () => {
|
||||
|
||||
describe('readTree', () => {
|
||||
const archiveBuffer = fs.readFileSync(
|
||||
path.resolve('src', 'reading', '__fixtures__', 'gitlab-archive.tar.gz'),
|
||||
path.resolve(__dirname, '__fixtures__/gitlab-archive.tar.gz'),
|
||||
);
|
||||
|
||||
const projectGitlabApiResponse = {
|
||||
@@ -495,7 +495,7 @@ describe('GitlabUrlReader', () => {
|
||||
|
||||
describe('search', () => {
|
||||
const archiveBuffer = fs.readFileSync(
|
||||
path.resolve('src', 'reading', '__fixtures__', 'gitlab-archive.tar.gz'),
|
||||
path.resolve(__dirname, '__fixtures__/gitlab-archive.tar.gz'),
|
||||
);
|
||||
|
||||
const projectGitlabApiResponse = {
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ConfigReader, JsonObject } from '@backstage/config';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { getVoidLogger } from '../logging';
|
||||
import { DefaultReadTreeResponseFactory } from './tree';
|
||||
import { GoogleGcsUrlReader } from './GoogleGcsUrlReader';
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { isError } from '@backstage/errors';
|
||||
import { getVoidLogger } from '../logging';
|
||||
import { UrlReaders } from './UrlReaders';
|
||||
|
||||
@@ -71,7 +72,10 @@ function withRetries(count: number, fn: () => Promise<void>) {
|
||||
error = err;
|
||||
}
|
||||
}
|
||||
if (!error.message.match(/rate limit|Too Many Requests/)) {
|
||||
if (
|
||||
isError(error) &&
|
||||
!error.message.match(/rate limit|Too Many Requests/)
|
||||
) {
|
||||
throw error;
|
||||
} else {
|
||||
console.warn('Request was rate limited', error);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import Docker from 'dockerode';
|
||||
import fs from 'fs-extra';
|
||||
import { ForwardedError } from '@backstage/errors';
|
||||
import { PassThrough } from 'stream';
|
||||
import { ContainerRunner, RunContainerOptions } from './ContainerRunner';
|
||||
|
||||
@@ -45,8 +46,9 @@ export class DockerContainerRunner implements ContainerRunner {
|
||||
try {
|
||||
await this.dockerClient.ping();
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`This operation requires Docker. Docker does not appear to be available. Docker.ping() failed with: ${e.message}`,
|
||||
throw new ForwardedError(
|
||||
'This operation requires Docker. Docker does not appear to be available. Docker.ping() failed with',
|
||||
e,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @backstage/backend-test-utils
|
||||
|
||||
## 0.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-common@0.9.7
|
||||
- @backstage/cli@0.8.0
|
||||
|
||||
## 0.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-test-utils",
|
||||
"description": "Test helpers library for Backstage backends",
|
||||
"version": "0.1.7",
|
||||
"version": "0.1.8",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -30,8 +30,8 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.9.2",
|
||||
"@backstage/cli": "^0.7.11",
|
||||
"@backstage/backend-common": "^0.9.7",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@backstage/config": "^0.1.9",
|
||||
"knex": "^0.95.1",
|
||||
"mysql2": "^2.2.5",
|
||||
@@ -41,7 +41,7 @@
|
||||
"uuid": "^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.11",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"jest": "^26.0.1"
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# example-backend
|
||||
|
||||
## 0.2.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-auth-backend@0.4.4
|
||||
- @backstage/integration@0.6.8
|
||||
- @backstage/plugin-scaffolder-backend@0.15.8
|
||||
- @backstage/plugin-catalog-backend@0.17.0
|
||||
- @backstage/plugin-azure-devops-backend@0.1.2
|
||||
- @backstage/plugin-code-coverage-backend@0.1.13
|
||||
- @backstage/plugin-kubernetes-backend@0.3.17
|
||||
- example-app@0.2.50
|
||||
|
||||
## 0.2.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "example-backend",
|
||||
"version": "0.2.49",
|
||||
"version": "0.2.50",
|
||||
"main": "dist/index.cjs.js",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -24,36 +24,36 @@
|
||||
"migrate:create": "knex migrate:make -x ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.9.6",
|
||||
"@backstage/backend-common": "^0.9.7",
|
||||
"@backstage/catalog-client": "^0.5.0",
|
||||
"@backstage/catalog-model": "^0.9.4",
|
||||
"@backstage/catalog-model": "^0.9.5",
|
||||
"@backstage/config": "^0.1.10",
|
||||
"@backstage/integration": "^0.6.7",
|
||||
"@backstage/plugin-app-backend": "^0.3.16",
|
||||
"@backstage/plugin-auth-backend": "^0.4.3",
|
||||
"@backstage/plugin-azure-devops-backend": "^0.1.1",
|
||||
"@backstage/integration": "^0.6.8",
|
||||
"@backstage/plugin-app-backend": "^0.3.17",
|
||||
"@backstage/plugin-auth-backend": "^0.4.5",
|
||||
"@backstage/plugin-azure-devops-backend": "^0.1.3",
|
||||
"@backstage/plugin-badges-backend": "^0.1.11",
|
||||
"@backstage/plugin-catalog-backend": "^0.16.0",
|
||||
"@backstage/plugin-code-coverage-backend": "^0.1.12",
|
||||
"@backstage/plugin-catalog-backend": "^0.17.1",
|
||||
"@backstage/plugin-code-coverage-backend": "^0.1.14",
|
||||
"@backstage/plugin-graphql-backend": "^0.1.9",
|
||||
"@backstage/plugin-jenkins-backend": "^0.1.6",
|
||||
"@backstage/plugin-kubernetes-backend": "^0.3.16",
|
||||
"@backstage/plugin-kubernetes-backend": "^0.3.18",
|
||||
"@backstage/plugin-kafka-backend": "^0.2.10",
|
||||
"@backstage/plugin-proxy-backend": "^0.2.13",
|
||||
"@backstage/plugin-rollbar-backend": "^0.1.15",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.15.7",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.15.10",
|
||||
"@backstage/plugin-scaffolder-backend-module-rails": "^0.1.5",
|
||||
"@backstage/plugin-search-backend": "^0.2.6",
|
||||
"@backstage/plugin-search-backend-node": "^0.4.2",
|
||||
"@backstage/plugin-search-backend-module-elasticsearch": "^0.0.4",
|
||||
"@backstage/plugin-search-backend-module-pg": "^0.2.1",
|
||||
"@backstage/plugin-techdocs-backend": "^0.10.4",
|
||||
"@backstage/plugin-techdocs-backend": "^0.10.5",
|
||||
"@backstage/plugin-todo-backend": "^0.1.13",
|
||||
"@gitbeaker/node": "^30.2.0",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
"azure-devops-node-api": "^11.0.1",
|
||||
"dockerode": "^3.2.1",
|
||||
"example-app": "^0.2.49",
|
||||
"example-app": "^0.2.51",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^4.1.0",
|
||||
"express-prom-bundle": "^6.3.6",
|
||||
@@ -65,7 +65,7 @@
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.15",
|
||||
"@backstage/cli": "^0.8.0",
|
||||
"@types/dockerode": "^3.2.1",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/express-serve-static-core": "^4.17.5"
|
||||
|
||||
@@ -38,7 +38,7 @@ import { Config } from '@backstage/config';
|
||||
import healthcheck from './plugins/healthcheck';
|
||||
import { metricsInit, metricsHandler } from './metrics';
|
||||
import auth from './plugins/auth';
|
||||
import azureDevOps from './plugins/azuredevops';
|
||||
import azureDevOps from './plugins/azure-devops';
|
||||
import catalog from './plugins/catalog';
|
||||
import codeCoverage from './plugins/codecoverage';
|
||||
import kubernetes from './plugins/kubernetes';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user