diff --git a/.changeset/afraid-boats-check.md b/.changeset/afraid-boats-check.md
deleted file mode 100644
index d36fda4e03..0000000000
--- a/.changeset/afraid-boats-check.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
-'@backstage/plugin-techdocs-backend': patch
----
-
-Specify type of `visibilityPermission` property on collators and collator factories.
diff --git a/.changeset/angry-pens-begin.md b/.changeset/angry-pens-begin.md
deleted file mode 100644
index ed5bbf4c4e..0000000000
--- a/.changeset/angry-pens-begin.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend': minor
----
-
-Override default commit message and author details in GitLab action
diff --git a/.changeset/beige-avocados-matter.md b/.changeset/beige-avocados-matter.md
deleted file mode 100644
index d6c1e3b2a5..0000000000
--- a/.changeset/beige-avocados-matter.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-'@backstage/plugin-catalog-backend': minor
----
-
-**BREAKING (alpha api):** Replace `createCatalogPolicyDecision` export with `createCatalogConditionalDecision`, which accepts a permission parameter of type `ResourcePermission<'catalog-entity'>` along with conditions. The permission passed is expected to be the handled permission in `PermissionPolicy#handle`, whose type must first be narrowed using methods like `isPermission` and `isResourcePermission`:
-
-```typescript
-class TestPermissionPolicy implements PermissionPolicy {
- async handle(
- request: PolicyQuery,
- _user?: BackstageIdentityResponse,
- ): Promise {
- if (
- // Narrow type of `request.permission` to `ResourcePermission<'catalog-entity'>
- isResourcePermission(request.permission, RESOURCE_TYPE_CATALOG_ENTITY)
- ) {
- return createCatalogConditionalDecision(
- request.permission,
- catalogConditions.isEntityOwner(
- _user?.identity.ownershipEntityRefs ?? [],
- ),
- );
- }
-
- return {
- result: AuthorizeResult.ALLOW,
- };
-```
diff --git a/.changeset/beige-baboons-walk.md b/.changeset/beige-baboons-walk.md
deleted file mode 100644
index a5b424a489..0000000000
--- a/.changeset/beige-baboons-walk.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/integration': patch
-'@backstage/plugin-catalog-backend': patch
-'@backstage/plugin-catalog-backend-module-msgraph': patch
----
-
-Clarify that config locations that emit User and Group kinds now need to declare so in the `catalog.locations.[].rules`
diff --git a/.changeset/beige-panthers-dream.md b/.changeset/beige-panthers-dream.md
new file mode 100644
index 0000000000..e477419c13
--- /dev/null
+++ b/.changeset/beige-panthers-dream.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-auth-backend': patch
+---
+
+Fixed a bug that was introduced in `0.13.1-next.0` which caused the `ent` claim of issued tokens to be dropped.
diff --git a/.changeset/big-buses-clap.md b/.changeset/big-buses-clap.md
deleted file mode 100644
index 503aa314bc..0000000000
--- a/.changeset/big-buses-clap.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-bazaar': patch
----
-
-Pass authorization header with Backstage token to backend requests.
diff --git a/.changeset/big-mayflies-sin.md b/.changeset/big-mayflies-sin.md
deleted file mode 100644
index 6aa18fc9c5..0000000000
--- a/.changeset/big-mayflies-sin.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-search-backend': patch
----
-
-Check for non-resource permissions when authorizing result-by-result in AuthorizedSearchEngine.
diff --git a/.changeset/blue-beers-kiss.md b/.changeset/blue-beers-kiss.md
deleted file mode 100644
index 15ea58efb4..0000000000
--- a/.changeset/blue-beers-kiss.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-permission-react': minor
----
-
-**BREAKING**: More restrictive typing for `usePermission` hook and `PermissionedRoute` component. It's no longer possible to pass a `resourceRef` unless the permission is of type `ResourcePermission`.
diff --git a/.changeset/blue-geese-work.md b/.changeset/blue-geese-work.md
deleted file mode 100644
index b40c1f93b6..0000000000
--- a/.changeset/blue-geese-work.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend': patch
----
-
-Updated openid-client from 4.1.2 to 5.1.3
diff --git a/.changeset/brave-chairs-stare.md b/.changeset/brave-chairs-stare.md
deleted file mode 100644
index 8a2dd91e91..0000000000
--- a/.changeset/brave-chairs-stare.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-tasks': patch
----
-
-Refactored the internal `TaskWorker` class to make it easier to test.
diff --git a/.changeset/breezy-days-prove.md b/.changeset/breezy-days-prove.md
new file mode 100644
index 0000000000..d3bc3c169e
--- /dev/null
+++ b/.changeset/breezy-days-prove.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': minor
+---
+
+Add new bitbucket(Cloud/Server) integrations to ScaffolderClient.
diff --git a/.changeset/breezy-mugs-build.md b/.changeset/breezy-mugs-build.md
deleted file mode 100644
index 026932e971..0000000000
--- a/.changeset/breezy-mugs-build.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-home': patch
----
-
-Export template logos `TemplateBackstageLogo` and `TemplateBackstageLogoIcon` from package.
diff --git a/.changeset/breezy-schools-compete.md b/.changeset/breezy-schools-compete.md
deleted file mode 100644
index b6e82eff25..0000000000
--- a/.changeset/breezy-schools-compete.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-Fixed an issue where sometimes entities would have stale relations "stuck" and
-not getting removed as expected, after the other end of the relation had stopped
-referring to them.
diff --git a/.changeset/slimy-horses-do.md b/.changeset/bright-panthers-guess.md
similarity index 51%
rename from .changeset/slimy-horses-do.md
rename to .changeset/bright-panthers-guess.md
index 196c47c988..a83f2e4bf1 100644
--- a/.changeset/slimy-horses-do.md
+++ b/.changeset/bright-panthers-guess.md
@@ -2,4 +2,4 @@
'@backstage/plugin-api-docs': patch
---
-Add dedicated gRPC api definition widget
+Updated dependency `graphiql` to `^1.8.8`.
diff --git a/.changeset/calm-walls-heal.md b/.changeset/calm-walls-heal.md
deleted file mode 100644
index f47ce4a0e9..0000000000
--- a/.changeset/calm-walls-heal.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-permission-common': minor
----
-
-Add `resourceType` property to `PermissionCondition` type to allow matching them with `ResourcePermission` instances.
diff --git a/.changeset/chatty-forks-bathe.md b/.changeset/chatty-forks-bathe.md
new file mode 100644
index 0000000000..e6d3816cc6
--- /dev/null
+++ b/.changeset/chatty-forks-bathe.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-adr': minor
+'@backstage/plugin-adr-backend': minor
+'@backstage/plugin-adr-common': minor
+---
+
+Implement ADR plugin
diff --git a/.changeset/clean-lions-taste.md b/.changeset/clean-lions-taste.md
deleted file mode 100644
index 1ec1eec952..0000000000
--- a/.changeset/clean-lions-taste.md
+++ /dev/null
@@ -1,52 +0,0 @@
----
-'@backstage/create-app': patch
----
-
-Made `User` and `Group` entity kinds not permitted by the default
-`catalog.rules` config.
-
-The effect of this is that after creating a new Backstage repository, its
-catalog no longer permits regular users to register `User` or `Group` entities
-using the Backstage interface. Additionally, if you have config locations that
-result in `User` or `Group` entities, you need to add those kinds to its own
-specific rules:
-
-```yaml
-catalog:
- locations:
- # This applies for example to url type locations
- - type: url
- target: https://example.com/org.yaml
- rules:
- - allow: [User, Group]
- # But also note that this applies to ALL org location types!
- - type: github-org
- target: https://github.com/my-org-name
- rules:
- - allow: [User, Group]
-```
-
-This rule change does NOT affect entity providers, only things that are emitted
-by entity processors.
-
-We recommend that this change is applied to your own Backstage repository, since
-it makes it impossible for regular end users to affect your org data through
-e.g. YAML files. To do so, remove the two kinds from the default rules in your config:
-
-```diff
- catalog:
- rules:
-- - allow: [Component, System, API, Group, User, Resource, Location]
-+ - allow: [Component, System, API, Resource, Location]
-```
-
-And for any location that in any way results in org data being ingested, add the corresponding rule to it:
-
-```diff
- catalog:
- locations:
- - type: github-org
- target: https://github.com/my-org-name
-+ rules:
-+ - allow: [User, Group]
-```
diff --git a/.changeset/clever-buckets-doubt.md b/.changeset/clever-buckets-doubt.md
deleted file mode 100644
index 751db72bf8..0000000000
--- a/.changeset/clever-buckets-doubt.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-techdocs': patch
----
-
-imports from `@backstage/plugin-search-react` instead of `@backstage/plugin-search`
diff --git a/.changeset/clever-donuts-teach.md b/.changeset/clever-donuts-teach.md
deleted file mode 100644
index 2304de1137..0000000000
--- a/.changeset/clever-donuts-teach.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
----
-
-Prevent permissions with types other than `ResourcePermission<'catalog-entity'>` from being used with the `useEntityPermission` hook.
diff --git a/.changeset/clever-pumpkins-tease.md b/.changeset/clever-pumpkins-tease.md
deleted file mode 100644
index d0784361ff..0000000000
--- a/.changeset/clever-pumpkins-tease.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Bump the `rushstack` api generator libraries to their latest versions
diff --git a/.changeset/shiny-seas-yell.md b/.changeset/clever-trains-greet.md
similarity index 51%
rename from .changeset/shiny-seas-yell.md
rename to .changeset/clever-trains-greet.md
index 9a939701d8..dc75f2f02a 100644
--- a/.changeset/shiny-seas-yell.md
+++ b/.changeset/clever-trains-greet.md
@@ -2,9 +2,10 @@
'@backstage/plugin-tech-insights-backend': minor
---
-This backend now uses the `@backstage/backend-tasks` package facilities for scheduling fact retrievers.
-
-**BREAKING**: The `buildTechInsightsContext` function now takes an additional field in its options argument: `scheduler`. This is an instance of `PluginTaskScheduler`, which can be found in your backend initialization code's `env`.
+**BREAKING**: The `buildTechInsightsContext` function now takes an additional
+field in its options argument: `tokenManager`. This is an instance of
+`TokenManager`, which can be found in your backend initialization code's
+`env`.
```diff
const builder = buildTechInsightsContext({
@@ -12,7 +13,8 @@ This backend now uses the `@backstage/backend-tasks` package facilities for sche
config: env.config,
database: env.database,
discovery: env.discovery,
-+ scheduler: env.scheduler,
+ scheduler: env.scheduler,
++ tokenManager: env.tokenManager,
factRetrievers: [ /* ... */ ],
});
```
diff --git a/.changeset/cold-steaks-provide.md b/.changeset/cold-steaks-provide.md
deleted file mode 100644
index 8a107f7b53..0000000000
--- a/.changeset/cold-steaks-provide.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder': minor
----
-
-Added a context menu to the scaffolder page that provides links to the template editor and actions reference. These links and the presence of the context menu can be toggled through the `contextMenu` prop of the scaffolder page.
diff --git a/.changeset/cool-mice-sit.md b/.changeset/cool-mice-sit.md
new file mode 100644
index 0000000000..321b5fcf0b
--- /dev/null
+++ b/.changeset/cool-mice-sit.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-tech-insights': patch
+---
+
+Add new component `EntityTechInsightsScorecardCard`, which can be used in the overview of the `EntityPage` page or display multiple individual `EntityTechInsightsScorecardCard` in `EntityLayout.Route`.
diff --git a/.changeset/cool-ties-share.md b/.changeset/cool-ties-share.md
new file mode 100644
index 0000000000..fb76785fcf
--- /dev/null
+++ b/.changeset/cool-ties-share.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-common': patch
+---
+
+Gerrit integration: Added optional `cloneUrl` string to config.
diff --git a/.changeset/cuddly-turtles-sleep.md b/.changeset/cuddly-turtles-sleep.md
deleted file mode 100644
index a63cd44232..0000000000
--- a/.changeset/cuddly-turtles-sleep.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-Use new `PermissionEvaluator#authorizeConditional` method when retrieving permission conditions.
diff --git a/.changeset/curly-parrots-applaud.md b/.changeset/curly-parrots-applaud.md
new file mode 100644
index 0000000000..d9443415eb
--- /dev/null
+++ b/.changeset/curly-parrots-applaud.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-scaffolder-backend': minor
+---
+
+Update the `github:publish` action to allow passing required status check
+contexts before merging to the main branch.
diff --git a/.changeset/dependabot-05b19b9.md b/.changeset/dependabot-05b19b9.md
deleted file mode 100644
index 97845bb77d..0000000000
--- a/.changeset/dependabot-05b19b9.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-build(deps): bump `eslint-plugin-jest` from 25.3.4 to 26.1.2
diff --git a/.changeset/dependabot-2b68456.md b/.changeset/dependabot-2b68456.md
deleted file mode 100644
index f54dd17d55..0000000000
--- a/.changeset/dependabot-2b68456.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/catalog-model': patch
-'@backstage/config-loader': patch
-'@backstage/plugin-tech-insights-backend-module-jsonfc': patch
----
-
-build(deps): bump `ajv` from 7.0.3 to 8.10.0
diff --git a/.changeset/dependabot-456f3f4.md b/.changeset/dependabot-456f3f4.md
deleted file mode 100644
index 1ccd243715..0000000000
--- a/.changeset/dependabot-456f3f4.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-kubernetes': patch
----
-
-build(deps): bump `cronstrue` from 1.125.0 to 2.2.0
diff --git a/.changeset/dependabot-51da438.md b/.changeset/dependabot-51da438.md
deleted file mode 100644
index d7d735b9a1..0000000000
--- a/.changeset/dependabot-51da438.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend': patch
----
-
-build(deps): bump `isbinaryfile` from 4.0.8 to 5.0.0
diff --git a/.changeset/dependabot-6754062.md b/.changeset/dependabot-6754062.md
deleted file mode 100644
index 14d9648071..0000000000
--- a/.changeset/dependabot-6754062.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-build(deps): bump `eslint-webpack-plugin` from 2.6.0 to 3.1.1
diff --git a/.changeset/dependabot-699dc23.md b/.changeset/dependabot-699dc23.md
deleted file mode 100644
index b73b0eab46..0000000000
--- a/.changeset/dependabot-699dc23.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-kafka-backend': patch
----
-
-build(deps-dev): bump `@types/jest-when` from 2.7.2 to 3.5.0
diff --git a/.changeset/dependabot-7272684.md b/.changeset/dependabot-7272684.md
deleted file mode 100644
index 6f68191ab7..0000000000
--- a/.changeset/dependabot-7272684.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend': patch
----
-
-build(deps): bump `@gitbeaker/core` from 34.6.0 to 35.6.0
diff --git a/.changeset/dependabot-84caed8.md b/.changeset/dependabot-84caed8.md
deleted file mode 100644
index d4806431a0..0000000000
--- a/.changeset/dependabot-84caed8.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-build(deps): bump `@spotify/eslint-config-base` from 12.0.0 to 13.0.0
diff --git a/.changeset/dependabot-a13a4a3.md b/.changeset/dependabot-a13a4a3.md
deleted file mode 100644
index 5a339330e7..0000000000
--- a/.changeset/dependabot-a13a4a3.md
+++ /dev/null
@@ -1,64 +0,0 @@
----
-'@backstage/core-app-api': patch
-'@backstage/core-components': patch
-'@backstage/core-plugin-api': patch
-'@backstage/dev-utils': patch
-'@backstage/integration-react': patch
-'@backstage/test-utils': patch
-'@backstage/plugin-airbrake': patch
-'@backstage/plugin-allure': patch
-'@backstage/plugin-analytics-module-ga': patch
-'@backstage/plugin-apache-airflow': patch
-'@backstage/plugin-api-docs': patch
-'@backstage/plugin-azure-devops': patch
-'@backstage/plugin-badges': patch
-'@backstage/plugin-bitrise': patch
-'@backstage/plugin-catalog-graph': patch
-'@backstage/plugin-catalog-import': patch
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-catalog': patch
-'@backstage/plugin-circleci': patch
-'@backstage/plugin-cloudbuild': patch
-'@backstage/plugin-code-climate': patch
-'@backstage/plugin-code-coverage': patch
-'@backstage/plugin-config-schema': patch
-'@backstage/plugin-cost-insights': patch
-'@backstage/plugin-explore-react': patch
-'@backstage/plugin-explore': patch
-'@backstage/plugin-firehydrant': patch
-'@backstage/plugin-fossa': patch
-'@backstage/plugin-gcalendar': patch
-'@backstage/plugin-gcp-projects': patch
-'@backstage/plugin-git-release-manager': patch
-'@backstage/plugin-github-actions': patch
-'@backstage/plugin-github-deployments': patch
-'@backstage/plugin-gitops-profiles': patch
-'@backstage/plugin-gocd': patch
-'@backstage/plugin-graphiql': patch
-'@backstage/plugin-home': patch
-'@backstage/plugin-ilert': patch
-'@backstage/plugin-jenkins': patch
-'@backstage/plugin-kafka': patch
-'@backstage/plugin-kubernetes': patch
-'@backstage/plugin-lighthouse': patch
-'@backstage/plugin-newrelic': patch
-'@backstage/plugin-org': patch
-'@backstage/plugin-pagerduty': patch
-'@backstage/plugin-periskop': patch
-'@backstage/plugin-rollbar': patch
-'@backstage/plugin-scaffolder': patch
-'@backstage/plugin-search': patch
-'@backstage/plugin-sentry': patch
-'@backstage/plugin-shortcuts': patch
-'@backstage/plugin-sonarqube': patch
-'@backstage/plugin-splunk-on-call': patch
-'@backstage/plugin-stack-overflow': patch
-'@backstage/plugin-tech-insights': patch
-'@backstage/plugin-tech-radar': patch
-'@backstage/plugin-techdocs': patch
-'@backstage/plugin-todo': patch
-'@backstage/plugin-user-settings': patch
-'@backstage/plugin-xcmetrics': patch
----
-
-build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
diff --git a/.changeset/dependabot-c1fe92f.md b/.changeset/dependabot-c1fe92f.md
deleted file mode 100644
index 8d106e3962..0000000000
--- a/.changeset/dependabot-c1fe92f.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-build(deps): bump `@spotify/eslint-config-typescript`
diff --git a/.changeset/dependabot-c762551.md b/.changeset/dependabot-c762551.md
deleted file mode 100644
index 4da9ddd18d..0000000000
--- a/.changeset/dependabot-c762551.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-build(deps): bump `@spotify/eslint-config-react` from 12.0.0 to 13.0.0
diff --git a/.changeset/dependabot-cccf2f0.md b/.changeset/dependabot-cccf2f0.md
deleted file mode 100644
index 6b420f9a48..0000000000
--- a/.changeset/dependabot-cccf2f0.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-build(deps): bump `npm-packlist` from 3.0.0 to 5.0.0
diff --git a/.changeset/dependabot-ebb092c.md b/.changeset/dependabot-ebb092c.md
deleted file mode 100644
index 78850d2065..0000000000
--- a/.changeset/dependabot-ebb092c.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-api-docs': patch
----
-
-build(deps): bump `@asyncapi/react-component`
diff --git a/.changeset/dirty-eagles-hunt.md b/.changeset/dirty-eagles-hunt.md
new file mode 100644
index 0000000000..d3ad27dfc3
--- /dev/null
+++ b/.changeset/dirty-eagles-hunt.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-common': patch
+---
+
+Split BitbucketUrlReader into BitbucketCloudUrlReader and BitbucketServerUrlReader. Backwards compatible.
diff --git a/.changeset/dry-fans-arrive.md b/.changeset/dry-fans-arrive.md
deleted file mode 100644
index 6947703e7f..0000000000
--- a/.changeset/dry-fans-arrive.md
+++ /dev/null
@@ -1,63 +0,0 @@
----
-'@backstage/plugin-permission-node': minor
----
-
-**BREAKING**: Stronger typing in `PermissionPolicy` 🎉.
-
-Previously, it was entirely the responsibility of the `PermissionPolicy` author to only return `CONDITIONAL` decisions for permissions that are associated with a resource, and to return the correct kind of `PermissionCondition` instances inside the decision. Now, the policy authoring helpers provided in this package now ensure that the decision and permission match.
-
-**For policy authors**: rename and adjust api of `createConditionExports`. Previously, the function returned a factory for creating conditional decisions named `createPolicyDecision`, which had a couple of drawbacks:
-
-1. The function always creates a _conditional_ policy decision, but this was not reflected in the name.
-2. Conditional decisions should only ever be returned from `PermissionPolicy#handle` for resource permissions, but there was nothing in the API that encoded this constraint.
-
-This change addresses the drawbacks above by making the following changes for policy authors:
-
-- The `createPolicyDecision` method has been renamed to `createConditionalDecision`.
-- Along with conditions, the method now accepts a permission, which must be a `ResourcePermission`. This is expected to be the handled permission in `PermissionPolicy#handle`, whose type must first be narrowed using methods like `isPermission` and `isResourcePermission`:
-
-```typescript
-class TestPermissionPolicy implements PermissionPolicy {
- async handle(
- request: PolicyQuery,
- _user?: BackstageIdentityResponse,
- ): Promise {
- if (
- // Narrow type of `request.permission` to `ResourcePermission<'catalog-entity'>
- isResourcePermission(request.permission, RESOURCE_TYPE_CATALOG_ENTITY)
- ) {
- return createCatalogConditionalDecision(
- request.permission,
- catalogConditions.isEntityOwner(
- _user?.identity.ownershipEntityRefs ?? [],
- ),
- );
- }
-
- return {
- result: AuthorizeResult.ALLOW,
- };
-```
-
-**BREAKING**: when creating `PermissionRule`s, provide a `resourceType`.
-
-```diff
-export const isEntityOwner = createCatalogPermissionRule({
- name: 'IS_ENTITY_OWNER',
- description: 'Allow entities owned by the current user',
-+ resourceType: RESOURCE_TYPE_CATALOG_ENTITY,
- apply: (resource: Entity, claims: string[]) => {
- if (!resource.relations) {
- return false;
- }
-
- return resource.relations
- .filter(relation => relation.type === RELATION_OWNED_BY)
- .some(relation => claims.includes(relation.targetRef));
- },
- toQuery: (claims: string[]) => ({
- key: 'relations.ownedBy',
- values: claims,
- }),
-});
-```
diff --git a/.changeset/eight-cobras-think.md b/.changeset/eight-cobras-think.md
deleted file mode 100644
index af1c7cd113..0000000000
--- a/.changeset/eight-cobras-think.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-search-backend': patch
----
-
-Use `PermissionEvaluator` instead of `PermissionAuthorizer`, which is now deprecated.
diff --git a/.changeset/eighty-chicken-retire.md b/.changeset/eighty-chicken-retire.md
new file mode 100644
index 0000000000..f6d66f5eba
--- /dev/null
+++ b/.changeset/eighty-chicken-retire.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-kubernetes-backend': patch
+---
+
+Add filtering to GKE cluster locator
diff --git a/.changeset/eleven-days-brush.md b/.changeset/eleven-days-brush.md
deleted file mode 100644
index d628b068fc..0000000000
--- a/.changeset/eleven-days-brush.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-tasks': minor
----
-
-Adds the ability to manually trigger tasks which are registered
diff --git a/.changeset/eleven-frogs-promise.md b/.changeset/eleven-frogs-promise.md
deleted file mode 100644
index 1868bb9df5..0000000000
--- a/.changeset/eleven-frogs-promise.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-'@backstage/plugin-permission-common': minor
----
-
-Refactor api types into more specific, decoupled names.
-
-- **BREAKING:**
- - Renamed `AuthorizeDecision` to `EvaluatePermissionResponse`
- - Renamed `AuthorizeQuery` to `EvaluatePermissionRequest`
- - Renamed `AuthorizeRequest` to `EvaluatePermissionRequestBatch`
- - Renamed `AuthorizeResponse` to `EvaluatePermissionResponseBatch`
- - Renamed `Identified` to `IdentifiedPermissionMessage`
-- Add `PermissionMessageBatch` helper type
-- Add `ConditionalPolicyDecision`, `DefinitivePolicyDecision`, and `PolicyDecision` types from `@backstage/plugin-permission-node`
diff --git a/.changeset/eleven-pens-collect.md b/.changeset/eleven-pens-collect.md
deleted file mode 100644
index 0df1bb0400..0000000000
--- a/.changeset/eleven-pens-collect.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog': patch
----
-
-Corrected replacements for depreciated FilteredEntityLayout items
diff --git a/.changeset/empty-mugs-bow.md b/.changeset/empty-mugs-bow.md
new file mode 100644
index 0000000000..d9d63e7f89
--- /dev/null
+++ b/.changeset/empty-mugs-bow.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-plugin-api': patch
+---
+
+The authentication APIs are no longer `@alpha`. Since the `@backstage/core-plugin-api` has no `/alpha` entrypoint, the only effect of marking the APIs as `@alpha` was to hide them in documentation. They are still expected to be widely used and there will be a migration path if they are changed in the future.
diff --git a/.changeset/empty-pens-invent.md b/.changeset/empty-pens-invent.md
deleted file mode 100644
index d6937afc84..0000000000
--- a/.changeset/empty-pens-invent.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-search-backend': minor
----
-
-**BREAKING**: The `authorization` property is no longer returned on search results when queried. Note: this will only result in a breaking change if you have custom code in your frontend that relies on the `authorization.resourceRef` property on documents.
diff --git a/.changeset/empty-poems-lick.md b/.changeset/empty-poems-lick.md
new file mode 100644
index 0000000000..2f620758ed
--- /dev/null
+++ b/.changeset/empty-poems-lick.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-common': patch
+---
+
+Update types to match the new version of `@keyv/redis`
diff --git a/.changeset/fair-dingos-glow.md b/.changeset/fair-dingos-glow.md
deleted file mode 100644
index 569f7a3fab..0000000000
--- a/.changeset/fair-dingos-glow.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-'@backstage/create-app': patch
----
-
-Remove the `knex` package that is installed in the `packages/backend` as it's provided by the `@backstage/*` packages for you automatically. You can make the following change in your `packages/backend/package.json` if you wish to apply this change.
-
-```diff
- "lint": "backstage-cli package lint",
- "test": "backstage-cli package test",
- "clean": "backstage-cli package clean",
-- "migrate:create": "knex migrate:make -x ts"
-```
-
-```diff
- "express": "^4.17.1",
- "express-promise-router": "^4.1.0",
-- "knex": "^0.21.6",
- "pg": "^8.3.0",
-```
diff --git a/.changeset/fair-kings-retire.md b/.changeset/fair-kings-retire.md
new file mode 100644
index 0000000000..156632f6ae
--- /dev/null
+++ b/.changeset/fair-kings-retire.md
@@ -0,0 +1,5 @@
+---
+'@backstage/integration': minor
+---
+
+Gerrit UrlReader: Implemented `readTree`
diff --git a/.changeset/fair-lamps-leave.md b/.changeset/fair-lamps-leave.md
deleted file mode 100644
index 9e902b51f2..0000000000
--- a/.changeset/fair-lamps-leave.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-user-settings': patch
----
-
-Wired up the OneLogin provider to be visible in the Settings UI when configured correctly.
-
-Previously it wasn't visible at all.
diff --git a/.changeset/fair-pigs-mate.md b/.changeset/fair-pigs-mate.md
new file mode 100644
index 0000000000..ce82e138b8
--- /dev/null
+++ b/.changeset/fair-pigs-mate.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-tech-insights-node': minor
+---
+
+**BREAKING**: The `FactRetrieverContext` type now contains an additional
+field: `tokenManager`.
diff --git a/.changeset/famous-seas-flash.md b/.changeset/famous-seas-flash.md
deleted file mode 100644
index cd19dc257e..0000000000
--- a/.changeset/famous-seas-flash.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-sentry': patch
----
-
-Exposed options for the material table
diff --git a/.changeset/fast-cheetahs-grow.md b/.changeset/fast-cheetahs-grow.md
deleted file mode 100644
index 5567436b5e..0000000000
--- a/.changeset/fast-cheetahs-grow.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-node': minor
----
-
-**BREAKING**: Removed the deprecated `id` and `entity` fields from `BackstageSignInResult`.
diff --git a/.changeset/few-buttons-breathe.md b/.changeset/few-buttons-breathe.md
deleted file mode 100644
index 7c7996774a..0000000000
--- a/.changeset/few-buttons-breathe.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-components': patch
----
-
-Add BackstageTab to overridableComponents so can override styles in a theme
diff --git a/.changeset/few-hotels-approve.md b/.changeset/few-hotels-approve.md
deleted file mode 100644
index 49ca040ef7..0000000000
--- a/.changeset/few-hotels-approve.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder': patch
----
-
-Changed input label for owner field in GitlabRepoPicker
diff --git a/.changeset/few-mayflies-divide.md b/.changeset/few-mayflies-divide.md
deleted file mode 100644
index e8744c47da..0000000000
--- a/.changeset/few-mayflies-divide.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-'@backstage/plugin-permission-node': minor
----
-
-**BREAKING:**
-
-- Rename `PolicyAuthorizeQuery` to `PolicyQuery`
-- Remove `PolicyDecision`, `DefinitivePolicyDecision`, and `ConditionalPolicyDecision`. These types are now exported from `@backstage/plugin-permission-common`
diff --git a/.changeset/few-seas-fail.md b/.changeset/few-seas-fail.md
deleted file mode 100644
index c5d9db4d47..0000000000
--- a/.changeset/few-seas-fail.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-'@backstage/plugin-permission-common': patch
----
-
-Added `PermissionEvaluator`, which will replace the existing `PermissionAuthorizer` interface. This new interface provides stronger type safety and validation by splitting `PermissionAuthorizer.authorize()` into two methods:
-
-- `authorize()`: Used when the caller requires a definitive decision.
-- `authorizeConditional()`: Used when the caller can optimize the evaluation of any conditional decisions. For example, a plugin backend may want to use conditions in a database query instead of evaluating each resource in memory.
diff --git a/.changeset/fluffy-grapes-sort.md b/.changeset/fluffy-grapes-sort.md
deleted file mode 100644
index 461d80275d..0000000000
--- a/.changeset/fluffy-grapes-sort.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-user-settings': patch
----
-
-Dynamically layout User Settings theme toggle container
diff --git a/.changeset/forty-poets-tie.md b/.changeset/forty-poets-tie.md
deleted file mode 100644
index 9118100934..0000000000
--- a/.changeset/forty-poets-tie.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
----
-
-Decouple tags picker from backend entities
-
-`EntityTagPicker` fetches all the tags independently and it doesn't require all the entities to be available client side.
diff --git a/.changeset/forty-pumpkins-marry.md b/.changeset/forty-pumpkins-marry.md
deleted file mode 100644
index 782fb5ae91..0000000000
--- a/.changeset/forty-pumpkins-marry.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-msgraph': patch
----
-
-Now plugin configuration accept a new optional parameter `groupSelect` which allow the client to fetch defined fields from the ms-graph api.
diff --git a/.changeset/four-birds-peel.md b/.changeset/four-birds-peel.md
deleted file mode 100644
index e90f631858..0000000000
--- a/.changeset/four-birds-peel.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-home': patch
----
-
-- Adds new `HomePageStackOverflowQuestions` component which renders a list of stack overflow questions on your homepage.
-
-- Exports `ComponentRenderer` type.
diff --git a/.changeset/four-dolphins-report.md b/.changeset/four-dolphins-report.md
deleted file mode 100644
index fa3f06c532..0000000000
--- a/.changeset/four-dolphins-report.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-permission-node': minor
----
-
-**BREAKING:** `ServerPermissionClient` now implements `PermissionEvaluator`, which moves out the capabilities for evaluating conditional decisions from `authorize()` to `authorizeConditional()` method.
diff --git a/.changeset/fresh-boxes-pull.md b/.changeset/fresh-boxes-pull.md
deleted file mode 100644
index e73d7e25c2..0000000000
--- a/.changeset/fresh-boxes-pull.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-jenkins-backend': patch
----
-
-Use `PermissionEvaluator` instead of `PermissionAuthorizer`, which is now deprecated.
diff --git a/.changeset/fresh-bulldogs-own.md b/.changeset/fresh-bulldogs-own.md
deleted file mode 100644
index 7772262efe..0000000000
--- a/.changeset/fresh-bulldogs-own.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-badges-backend': patch
----
-
-allow overriding `DefaultBadgeBuilder.getMarkdownCode`
diff --git a/.changeset/fresh-cobras-admire.md b/.changeset/fresh-cobras-admire.md
deleted file mode 100644
index c73d4ab5d5..0000000000
--- a/.changeset/fresh-cobras-admire.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-kubernetes': patch
----
-
-export kubernetes components
diff --git a/.changeset/fresh-dodos-rush.md b/.changeset/fresh-dodos-rush.md
deleted file mode 100644
index b71c2ad055..0000000000
--- a/.changeset/fresh-dodos-rush.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-tech-insights-node': patch
----
-
-Adds an optional timeout to fact retriever registrations to stop a task if it runs too long.
diff --git a/.changeset/friendly-hairs-happen.md b/.changeset/friendly-hairs-happen.md
deleted file mode 100644
index 219d5efbcd..0000000000
--- a/.changeset/friendly-hairs-happen.md
+++ /dev/null
@@ -1,76 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-aws': patch
----
-
-Add a new provider `AwsS3EntityProvider` as replacement for `AwsS3DiscoveryProcessor`.
-
-In order to migrate from the `AwsS3DiscoveryProcessor` you need to apply
-the following changes:
-
-**Before:**
-
-```yaml
-# app-config.yaml
-
-catalog:
- locations:
- - type: s3-discovery
- target: https://sample-bucket.s3.us-east-2.amazonaws.com/prefix/
-```
-
-```ts
-/* packages/backend/src/plugins/catalog.ts */
-
-import { AwsS3DiscoveryProcessor } from '@backstage/plugin-catalog-backend-module-aws';
-
-const builder = await CatalogBuilder.create(env);
-/** ... other processors ... */
-builder.addProcessor(new AwsS3DiscoveryProcessor(env.reader));
-```
-
-**After:**
-
-```yaml
-# app-config.yaml
-
-catalog:
- providers:
- awsS3:
- yourProviderId: # identifies your dataset / provider independent of config changes
- bucketName: sample-bucket
- prefix: prefix/ # optional
- region: us-east-2 # optional, uses the default region otherwise
-```
-
-```ts
-/* packages/backend/src/plugins/catalog.ts */
-
-import { AwsS3EntityProvider } from '@backstage/plugin-catalog-backend-module-aws';
-
-const builder = await CatalogBuilder.create(env);
-/** ... other processors and/or providers ... */
-builder.addEntityProvider(
- ...AwsS3EntityProvider.fromConfig(env.config, {
- logger: env.logger,
- schedule: env.scheduler.createScheduledTaskRunner({
- frequency: Duration.fromObject({ minutes: 30 }),
- timeout: Duration.fromObject({ minutes: 3 }),
- }),
- }),
-);
-```
-
-For simple setups, you can omit the provider ID at the config
-which has the same effect as using `default` for it.
-
-```yaml
-# app-config.yaml
-
-catalog:
- providers:
- awsS3:
- # uses "default" as provider ID
- bucketName: sample-bucket
- prefix: prefix/ # optional
- region: us-east-2 # optional, uses the default region otherwise
-```
diff --git a/.changeset/fuzzy-seahorses-teach.md b/.changeset/fuzzy-seahorses-teach.md
new file mode 100644
index 0000000000..71ef28dd52
--- /dev/null
+++ b/.changeset/fuzzy-seahorses-teach.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Add instructions to `create-github-app` command.
diff --git a/.changeset/giant-cheetahs-thank.md b/.changeset/giant-cheetahs-thank.md
new file mode 100644
index 0000000000..a135fbc4a3
--- /dev/null
+++ b/.changeset/giant-cheetahs-thank.md
@@ -0,0 +1,30 @@
+---
+'@backstage/plugin-catalog-backend-module-msgraph': patch
+---
+
+Add annotation `microsoft.com/email` when using the `defaultUserTransformer`.
+
+This will allow users of the Microsoft auth provider to utilize the predefined
+SignIn resolver instead of maintaining their own.
+
+```typescript
+// backend/plugins/auth.ts
+
+// [...]
+
+export default async function createPlugin(
+ env: PluginEnvironment,
+): Promise {
+ return await createRouter({
+ // [...]
+ providerFactories: {
+ microsoft: providers.microsoft.create({
+ signIn: {
+ resolver:
+ providers.microsoft.resolvers.emailMatchingUserEntityAnnotation(),
+ },
+ }),
+ },
+ });
+}
+```
diff --git a/.changeset/gorgeous-donuts-float.md b/.changeset/gorgeous-donuts-float.md
deleted file mode 100644
index 72a28ba6f9..0000000000
--- a/.changeset/gorgeous-donuts-float.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-todo-backend': patch
----
-
-Fix method to get source-location.
diff --git a/.changeset/seven-apricots-sell.md b/.changeset/grumpy-panthers-peel.md
similarity index 53%
rename from .changeset/seven-apricots-sell.md
rename to .changeset/grumpy-panthers-peel.md
index 977bdd7d49..ecf4397554 100644
--- a/.changeset/seven-apricots-sell.md
+++ b/.changeset/grumpy-panthers-peel.md
@@ -2,4 +2,4 @@
'@backstage/plugin-tech-insights-backend-module-jsonfc': patch
---
-Removes node-cron from tech-insights to utilize backend-tasks
+Updated usages of `buildTechInsightsContext` in README.
diff --git a/.changeset/grumpy-parents-prove.md b/.changeset/grumpy-parents-prove.md
deleted file mode 100644
index ff01fe13f0..0000000000
--- a/.changeset/grumpy-parents-prove.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-'@backstage/plugin-org': patch
----
-
-Provides the ability to hide the relations toggle on the `OwnershipCard` as well as setting a default relation type.
-
-To hide the toggle simply include the `hideRelationsToggle` prop like this:
-
-```tsx
-
-```
-
-To set the default relation type, add the `relationsType` prop with a value of direct or aggregated, the default if not provided is direct. Here is an example:
-
-```tsx
-
-```
diff --git a/.changeset/happy-foxes-arrive.md b/.changeset/happy-foxes-arrive.md
deleted file mode 100644
index 53e59c8d77..0000000000
--- a/.changeset/happy-foxes-arrive.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Added an experimental `package fix` command which applies automated fixes to the target package. The initial fix that is available is to add missing monorepo dependencies to the target package.
diff --git a/.changeset/happy-mugs-camp.md b/.changeset/happy-mugs-camp.md
deleted file mode 100644
index 22d13d80d1..0000000000
--- a/.changeset/happy-mugs-camp.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-search-common': patch
----
-
-- Introduce `SearchDocument` type. This type contains the subset of `IndexableDocument` properties relevant to the frontend, and is intended to be used for documents returned to the frontend from the search API.
-- `SearchResultSet` is now a wrapper for documents of type `SearchDocument`, and is intended to be used in the frontend. This isn't a breaking change, since `IndexableDocument`s are valid `SearchDocument`s, so the old and new types are compatible.
-- Introduce `IndexableResultSet` type, which wraps `IndexableDocument` instances in the same way as `SearchResultSet`.
diff --git a/.changeset/heavy-stingrays-talk.md b/.changeset/heavy-stingrays-talk.md
deleted file mode 100644
index d17a85090b..0000000000
--- a/.changeset/heavy-stingrays-talk.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-common': patch
----
-
-The backend will no longer fail to start up when configured secrets do not match the configuration schema.
diff --git a/.changeset/hip-adults-collect.md b/.changeset/hip-adults-collect.md
new file mode 100644
index 0000000000..97afdf3da2
--- /dev/null
+++ b/.changeset/hip-adults-collect.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Fixing broken types for `knex` when checking returned rows
diff --git a/.changeset/hip-poems-breathe.md b/.changeset/hip-poems-breathe.md
deleted file mode 100644
index f8a507b2a7..0000000000
--- a/.changeset/hip-poems-breathe.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Stop logging "Stopped watcher" when shutting down the development backend.
diff --git a/.changeset/honest-kids-live.md b/.changeset/honest-kids-live.md
new file mode 100644
index 0000000000..e829d00d91
--- /dev/null
+++ b/.changeset/honest-kids-live.md
@@ -0,0 +1,7 @@
+---
+'@backstage/create-app': patch
+---
+
+Optimized the command order in `packages/backend/Dockerfile` as well as added the `--no-install-recommends` to the `apt-get install` and tweaked the installed packages.
+
+To apply this change to an existing app, update your `packages/backend/Dockerfile` to match the documented `Dockerfile` at https://backstage.io/docs/deployment/docker#host-build.
diff --git a/.changeset/hot-items-smoke.md b/.changeset/hot-items-smoke.md
deleted file mode 100644
index c9b9c8a135..0000000000
--- a/.changeset/hot-items-smoke.md
+++ /dev/null
@@ -1,61 +0,0 @@
----
-'@backstage/plugin-kubernetes-backend': minor
----
-
-**BREAKING** Custom cluster suppliers need to cache their getClusters result
-
-To allow custom `KubernetesClustersSupplier` instances to refresh the list of clusters
-the `getClusters` method is now called whenever the list of clusters is needed.
-
-Existing `KubernetesClustersSupplier` implementations will need to ensure that `getClusters`
-can be called frequently and should return a cached result from `getClusters` instead.
-
-For example, here's a simple example of a custom supplier in `packages/backend/src/plugins/kubernetes.ts`:
-
-```diff
--import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';
-+import {
-+ ClusterDetails,
-+ KubernetesBuilder,
-+ KubernetesClustersSupplier,
-+} from '@backstage/plugin-kubernetes-backend';
- import { Router } from 'express';
- import { PluginEnvironment } from '../types';
-+import { Duration } from 'luxon';
-+
-+export class CustomClustersSupplier implements KubernetesClustersSupplier {
-+ constructor(private clusterDetails: ClusterDetails[] = []) {}
-+
-+ static create(refreshInterval: Duration) {
-+ const clusterSupplier = new CustomClustersSupplier();
-+ // setup refresh, e.g. using a copy of https://github.com/backstage/backstage/blob/master/plugins/search-backend-node/src/runPeriodically.ts
-+ runPeriodically(
-+ () => clusterSupplier.refreshClusters(),
-+ refreshInterval.toMillis(),
-+ );
-+ return clusterSupplier;
-+ }
-+
-+ async refreshClusters(): Promise {
-+ this.clusterDetails = []; // fetch from somewhere
-+ }
-+
-+ async getClusters(): Promise {
-+ return this.clusterDetails;
-+ }
-+}
-
- export default async function createPlugin(
- env: PluginEnvironment,
- ): Promise {
-- const { router } = await KubernetesBuilder.createBuilder({
-+ const builder = await KubernetesBuilder.createBuilder({
- logger: env.logger,
- config: env.config,
-- }).build();
-+ });
-+ builder.setClusterSupplier(
-+ CustomClustersSupplier.create(Duration.fromObject({ minutes: 60 })),
-+ );
-+ const { router } = await builder.build();
-```
diff --git a/.changeset/hot-peaches-give.md b/.changeset/hot-peaches-give.md
new file mode 100644
index 0000000000..ac30e8d492
--- /dev/null
+++ b/.changeset/hot-peaches-give.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Add package global-agent to support behind a proxy for backstage-cli commands like versions:bump.
diff --git a/.changeset/itchy-candles-type.md b/.changeset/itchy-candles-type.md
deleted file mode 100644
index 3507ecd867..0000000000
--- a/.changeset/itchy-candles-type.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-'@backstage/plugin-org': patch
----
-
-Introduced a new MyGroupsSidebarItem SidebarItem that links to one or more groups based on the logged in user's membership.
-
-To use MyGroupsSidebarItem you'll need to add it to your `Root.tsx` like this:
-
-```diff
-// app/src/components/Root/Root.tsx
-+ import { MyGroupsSidebarItem } from '@backstage/plugin-org';
-+ import GroupIcon from '@material-ui/icons/People';
-
-
-
- //...
- }>
- {/* Global nav, not org-specific */}
- //...
-
-+
- //...
-
- Sidebar>
-
-```
diff --git a/.changeset/khaki-cougars-lick.md b/.changeset/khaki-cougars-lick.md
deleted file mode 100644
index 1723cd0636..0000000000
--- a/.changeset/khaki-cougars-lick.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
----
-
-Changed catalog filter components to only pay attention to query parameters relevant to the component.
diff --git a/.changeset/khaki-pears-march.md b/.changeset/khaki-pears-march.md
deleted file mode 100644
index 5626bf3ea5..0000000000
--- a/.changeset/khaki-pears-march.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend': minor
----
-
-**BREAKING**: All sign-in resolvers must now return a `token` in their sign-in result. Returning an `id` is no longer supported.
diff --git a/.changeset/large-coins-arrive.md b/.changeset/large-coins-arrive.md
deleted file mode 100644
index 3c0b3b9f97..0000000000
--- a/.changeset/large-coins-arrive.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-Adjust the error messages when entities fail validation, to clearly state what entity that failed it
diff --git a/.changeset/late-turtles-sparkle.md b/.changeset/late-turtles-sparkle.md
deleted file mode 100644
index f0b28cdb87..0000000000
--- a/.changeset/late-turtles-sparkle.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend': patch
----
-
-Declare oauth2 `clientSecret` with visibility secret
diff --git a/.changeset/lazy-zebras-pay.md b/.changeset/lazy-zebras-pay.md
new file mode 100644
index 0000000000..efcb62d7a9
--- /dev/null
+++ b/.changeset/lazy-zebras-pay.md
@@ -0,0 +1,39 @@
+---
+'@backstage/create-app': patch
+---
+
+Added some instruction comments to the generated config files, to clarify the
+usage of `backend.baseUrl` and `backend.listen.host`. Importantly, it also per
+default now listens on all IPv4 interfaces, to make it easier to take the step
+over to production. If you want to do the same, update your
+`app-config.production.yaml` as follows:
+
+```diff
+ backend:
+ listen:
+ port: 7007
++ host: 0.0.0.0
+```
+
+Also, updated the builtin backend Dockerfile to honor the
+`app-config.production.yaml` file. If you want to do the same, change
+`packages/backend/Dockerfile` as follows:
+
+```diff
+-COPY packages/backend/dist/bundle.tar.gz app-config.yaml ./
++COPY packages/backend/dist/bundle.tar.gz app-config*.yaml ./
+ RUN tar xzf bundle.tar.gz && rm bundle.tar.gz
+
+-CMD ["node", "packages/backend", "--config", "app-config.yaml"]
++CMD ["node", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.production.yaml"]
+```
+
+If you look carefully, this adds a glob match on app-config files. For those
+that try out the build flows locally, you also want to make sure that the docker
+daemon does NOT pick up any local/private config files that might contain
+secrets. You should therefore also update your local `.dockerignore` file at the
+same time:
+
+```diff
++*.local.yaml
+```
diff --git a/.changeset/lemon-ears-build.md b/.changeset/lemon-ears-build.md
deleted file mode 100644
index 87a04d150b..0000000000
--- a/.changeset/lemon-ears-build.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-aws': patch
----
-
-Corrected title and URL to setup documentation in README
diff --git a/.changeset/light-dragons-crash.md b/.changeset/light-dragons-crash.md
deleted file mode 100644
index 35dea73ae6..0000000000
--- a/.changeset/light-dragons-crash.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-'@backstage/create-app': patch
----
-
-Removed `@octokit/rest` and `@gitbeaker/node` from backend dependencies as these are unused in the default app.
-
-To apply these changes to your existing app, remove the following lines from the `dependencies` section of `packages/backend/package.json`
-
-```diff
- "@backstage/plugin-techdocs-backend": "^1.0.0",
-- "@gitbeaker/node": "^34.6.0",
-- "@octokit/rest": "^18.5.3",
-```
diff --git a/.changeset/light-drinks-rule.md b/.changeset/light-drinks-rule.md
deleted file mode 100644
index 2b99f5988c..0000000000
--- a/.changeset/light-drinks-rule.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-'@backstage/plugin-search-backend': patch
-'@backstage/plugin-search-backend-node': patch
-'@backstage/plugin-search-backend-module-elasticsearch': patch
-'@backstage/plugin-search-backend-module-pg': patch
----
-
-Use new `IndexableResultSet` type as return type of query method in `SearchEngine` implementation.
diff --git a/.changeset/little-moles-pull.md b/.changeset/little-moles-pull.md
deleted file mode 100644
index f52bc24bb2..0000000000
--- a/.changeset/little-moles-pull.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-'@backstage/create-app': patch
----
-
-Add type resolutions for `@types/react` and `types/react-dom`.
-
-The reason for this is the usage of `"@types/react": "*"` as a dependency which is very common practice in react packages. This recently resolves to react 18 which introduces several breaking changes in both internal and external packages.
-
-To apply these changes to your existing installation, add a resolutions block to your `package.json`
-
-```json
- "resolutions": {
- "@types/react": "^17",
- "@types/react-dom": "^17"
- },
-```
-
-If your existing app depends on react 16, use this resolution block instead.
-
-```json
- "resolutions": {
- "@types/react": "^16",
- "@types/react-dom": "^16"
- },
-```
diff --git a/.changeset/many-cameras-search.md b/.changeset/many-cameras-search.md
deleted file mode 100644
index 6998dfd713..0000000000
--- a/.changeset/many-cameras-search.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-Added `spec.profile.displayName` to search index for Group kinds
diff --git a/.changeset/mean-flowers-change.md b/.changeset/mean-flowers-change.md
new file mode 100644
index 0000000000..7634a20c84
--- /dev/null
+++ b/.changeset/mean-flowers-change.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+Override default commit message and author details in GitHub, Azure, bitbucket
diff --git a/.changeset/mean-pumas-search.md b/.changeset/mean-pumas-search.md
deleted file mode 100644
index 68a3aebc85..0000000000
--- a/.changeset/mean-pumas-search.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-app-api': patch
----
-
-fixed empty body issue for POST requests using FetchAPI with 'plugin://' prefix
diff --git a/.changeset/mean-rabbits-tell.md b/.changeset/mean-rabbits-tell.md
deleted file mode 100644
index 88d853d9b3..0000000000
--- a/.changeset/mean-rabbits-tell.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-stack-overflow-backend': minor
----
-
-Add stack overflow backend plugin
diff --git a/.changeset/mean-tomatoes-shout.md b/.changeset/mean-tomatoes-shout.md
deleted file mode 100644
index 446e66d386..0000000000
--- a/.changeset/mean-tomatoes-shout.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-'@backstage/plugin-permission-backend': patch
-'@backstage/plugin-permission-react': patch
-'@backstage/plugin-search-backend': patch
-'@backstage/test-utils': patch
----
-
-Use updated types from `@backstage/plugin-permission-common`
diff --git a/.changeset/metal-hairs-build.md b/.changeset/metal-hairs-build.md
new file mode 100644
index 0000000000..9ed8bba01b
--- /dev/null
+++ b/.changeset/metal-hairs-build.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-rollbar-backend': patch
+---
+
+Updated README to include clearer installation instructions on how to install and configure.
diff --git a/.changeset/metal-pants-fly.md b/.changeset/metal-pants-fly.md
new file mode 100644
index 0000000000..7db2014377
--- /dev/null
+++ b/.changeset/metal-pants-fly.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-home': patch
+---
+
+star icons now have the same yellow color as the other star icons when a entity is favourite
diff --git a/.changeset/metal-queens-cheat.md b/.changeset/metal-queens-cheat.md
deleted file mode 100644
index b2d152b3a9..0000000000
--- a/.changeset/metal-queens-cheat.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-catalog-common': patch
-'@backstage/plugin-jenkins-common': patch
----
-
-Use `createPermission` helper when creating permissions.
diff --git a/.changeset/mighty-suns-drop.md b/.changeset/mighty-suns-drop.md
deleted file mode 100644
index f8bb686aaf..0000000000
--- a/.changeset/mighty-suns-drop.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-org': patch
----
-
-add aggregated ownership type for kind group in OwnershipCard
diff --git a/.changeset/modern-actors-notice.md b/.changeset/modern-actors-notice.md
deleted file mode 100644
index 20dde7f42d..0000000000
--- a/.changeset/modern-actors-notice.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': minor
----
-
-**BREAKING:** Mark CatalogBuilder#addPermissionRules as @alpha.
diff --git a/.changeset/modern-pumas-join.md b/.changeset/modern-pumas-join.md
deleted file mode 100644
index d2995af986..0000000000
--- a/.changeset/modern-pumas-join.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-Enable internal batching of very large deletions, to not run into SQL binding limits
diff --git a/.changeset/moody-apes-tickle.md b/.changeset/moody-apes-tickle.md
deleted file mode 100644
index bdf593c9ad..0000000000
--- a/.changeset/moody-apes-tickle.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog': patch
----
-
-Added tableOptions property to CatalogTable and DefaultCatalogPage to support customization of the Catalog Table. Related issue #10453
diff --git a/.changeset/moody-ducks-return.md b/.changeset/moody-ducks-return.md
deleted file mode 100644
index 090b2f5db4..0000000000
--- a/.changeset/moody-ducks-return.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend': minor
----
-
-Add new `draft` option to the `publish:github:pull-request` action.
diff --git a/.changeset/moody-laws-boil.md b/.changeset/moody-laws-boil.md
new file mode 100644
index 0000000000..f481e84044
--- /dev/null
+++ b/.changeset/moody-laws-boil.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-api-docs': patch
+'@backstage/plugin-catalog': minor
+'@backstage/plugin-catalog-react': minor
+---
+
+Use InfoCardVariants on custom cards variant attribute
diff --git a/.changeset/moody-pigs-rush.md b/.changeset/moody-pigs-rush.md
deleted file mode 100644
index 37ae171382..0000000000
--- a/.changeset/moody-pigs-rush.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend': patch
----
-
-Applied the fix from version 0.12.3 of this package, which is part of the v1.0.1 release of Backstage.
diff --git a/.changeset/moody-sheep-marry.md b/.changeset/moody-sheep-marry.md
deleted file mode 100644
index 73f037db32..0000000000
--- a/.changeset/moody-sheep-marry.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder': minor
----
-
-The Template Preview page has been renamed to Template Editor, and is not available at the `/edit` path instead. There is a redirect in place from `/preview`.
diff --git a/.changeset/moody-suns-smell.md b/.changeset/moody-suns-smell.md
new file mode 100644
index 0000000000..b051335ad7
--- /dev/null
+++ b/.changeset/moody-suns-smell.md
@@ -0,0 +1,37 @@
+---
+'@backstage/integration': minor
+'@backstage/integration-react': minor
+---
+
+Split `bitbucket` integration into `bitbucketCloud` and `bitbucketServer`
+(backwards compatible).
+
+In order to migrate to the new integration configs,
+move your configs from `integrations.bitbucket`
+to `integrations.bitbucketCloud` or `integrations.bitbucketServer`.
+
+Migration example:
+
+**Before:**
+
+```yaml
+integrations:
+ bitbucket:
+ - host: bitbucket.org
+ username: bitbucket_user
+ appPassword: app-password
+ - host: bitbucket-server.company.com
+ token: my-token
+```
+
+**After:**
+
+```yaml
+integrations:
+ bitbucketCloud:
+ - username: bitbucket_user
+ appPassword: app-password
+ bitbucketServer:
+ - host: bitbucket-server.company.com
+ token: my-token
+```
diff --git a/.changeset/nasty-humans-give.md b/.changeset/nasty-humans-give.md
new file mode 100644
index 0000000000..85ce3149ba
--- /dev/null
+++ b/.changeset/nasty-humans-give.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog': minor
+---
+
+Added the prop `NotFoundComponent` to `EntityLayout` which can be used to include a custom component when an entity is not found in the catalog
diff --git a/.changeset/new-beds-argue.md b/.changeset/new-beds-argue.md
new file mode 100644
index 0000000000..8aa8acf09d
--- /dev/null
+++ b/.changeset/new-beds-argue.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-api-docs': patch
+---
+
+Bumped @asyncapi/react-component > openapi-sampler > json-pointer to resolve security vulnerability CVE-2021-23820
diff --git a/.changeset/new-lions-run.md b/.changeset/new-lions-run.md
deleted file mode 100644
index 8e830b33fa..0000000000
--- a/.changeset/new-lions-run.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-graph': patch
----
-
-Added renderNode and renderLabel property to EntityRelationsGraph to support customization using CustomNode and CustomLabel components
diff --git a/.changeset/new-singers-lie.md b/.changeset/new-singers-lie.md
deleted file mode 100644
index d7101db4d0..0000000000
--- a/.changeset/new-singers-lie.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-tech-insights-backend': patch
----
-
-Updated README.md with better install instructions
diff --git a/.changeset/nine-geese-rest.md b/.changeset/nine-geese-rest.md
new file mode 100644
index 0000000000..da91c6234b
--- /dev/null
+++ b/.changeset/nine-geese-rest.md
@@ -0,0 +1,6 @@
+---
+'@backstage/cli': patch
+---
+
+Changed Rollup configuration for TypeScript definition plugin to ignore `css`,
+`scss`, `sass`, `svg`, `eot`, `woff`, `woff2` and `ttf` files.
diff --git a/.changeset/nine-grapes-turn.md b/.changeset/nine-grapes-turn.md
deleted file mode 100644
index 263618722c..0000000000
--- a/.changeset/nine-grapes-turn.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-common': patch
----
-
-Added the GerritUrlReader that implements "readUrl".
diff --git a/.changeset/ninety-eggs-argue.md b/.changeset/ninety-eggs-argue.md
deleted file mode 100644
index 6fd221b722..0000000000
--- a/.changeset/ninety-eggs-argue.md
+++ /dev/null
@@ -1,84 +0,0 @@
----
-'@backstage/plugin-search-backend-node': minor
-'@backstage/create-app': patch
----
-
-**BREAKING**: `IndexBuilder.addCollator()` now requires a `schedule` parameter (replacing `defaultRefreshIntervalSeconds`) which is expected to be a `TaskRunner` that is configured with the desired search indexing schedule for the given collator.
-
-`Scheduler.addToSchedule()` now takes a new parameter object (`ScheduleTaskParameters`) with two new options `id` and `scheduledRunner` in addition to the migrated `task` argument.
-
-NOTE: The search backend plugin now creates a dedicated database for coordinating indexing tasks.
-
-To make this change to an existing app, make the following changes to `packages/backend/src/plugins/search.ts`:
-
-```diff
-+import { Duration } from 'luxon';
-
-/* ... */
-
-+ const schedule = env.scheduler.createScheduledTaskRunner({
-+ frequency: Duration.fromObject({ minutes: 10 }),
-+ timeout: Duration.fromObject({ minutes: 15 }),
-+ initialDelay: Duration.fromObject({ seconds: 3 }),
-+ });
-
- indexBuilder.addCollator({
-- defaultRefreshIntervalSeconds: 600,
-+ schedule,
- factory: DefaultCatalogCollatorFactory.fromConfig(env.config, {
- discovery: env.discovery,
- tokenManager: env.tokenManager,
- }),
- });
-
- indexBuilder.addCollator({
-- defaultRefreshIntervalSeconds: 600,
-+ schedule,
- factory: DefaultTechDocsCollatorFactory.fromConfig(env.config, {
- discovery: env.discovery,
- tokenManager: env.tokenManager,
- }),
- });
-
- const { scheduler } = await indexBuilder.build();
-- setTimeout(() => scheduler.start(), 3000);
-+ scheduler.start();
-/* ... */
-```
-
-NOTE: For scenarios where the `lunr` search engine is used in a multi-node configuration, a non-distributed `TaskRunner` like the following should be implemented to ensure consistency across nodes (alternatively, you can configure
-the search plugin to use a non-distributed DB such as [SQLite](https://backstage.io/docs/tutorials/configuring-plugin-databases#postgresql-and-sqlite-3)):
-
-```diff
-+import { TaskInvocationDefinition, TaskRunner } from '@backstage/backend-tasks';
-
-/* ... */
-
-+ const schedule: TaskRunner = {
-+ run: async (task: TaskInvocationDefinition) => {
-+ const startRefresh = async () => {
-+ while (!task.signal?.aborted) {
-+ try {
-+ await task.fn(task.signal);
-+ } catch {
-+ // ignore intentionally
-+ }
-+
-+ await new Promise(resolve => setTimeout(resolve, 600 * 1000));
-+ }
-+ };
-+ startRefresh();
-+ },
-+ };
-
- indexBuilder.addCollator({
-- defaultRefreshIntervalSeconds: 600,
-+ schedule,
- factory: DefaultCatalogCollatorFactory.fromConfig(env.config, {
- discovery: env.discovery,
- tokenManager: env.tokenManager,
- }),
- });
-
-/* ... */
-```
diff --git a/.changeset/ninety-fishes-vanish.md b/.changeset/ninety-fishes-vanish.md
deleted file mode 100644
index b0d3ac370f..0000000000
--- a/.changeset/ninety-fishes-vanish.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-search': patch
----
-
-Switch to `SearchDocument` type in `DefaultResultListItem` props
diff --git a/.changeset/ninety-islands-report.md b/.changeset/ninety-islands-report.md
deleted file mode 100644
index 4a515b75cd..0000000000
--- a/.changeset/ninety-islands-report.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend': patch
----
-
-Defensively encode URL parameters when fetching ELB keys
diff --git a/.changeset/ninety-radios-protect.md b/.changeset/ninety-radios-protect.md
deleted file mode 100644
index fa3fae281f..0000000000
--- a/.changeset/ninety-radios-protect.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-'@backstage/backend-tasks': patch
----
-
-Fixed the `initialDelay` parameter of tasks to properly make task workers
-_always_ wait before the first invocations on startup, not just the very first
-time that the task is ever created. This behavior is more in line with
-expectations. Callers to not need to update their code.
-
-Also clarified in the doc comment for the field that this wait applies only on
-an individual worker level. That is, if you have a cluster of workers then each
-individual machine may postpone its first task invocation by the given amount of
-time to leave room for the service to settle, but _other_ workers may still
-continue to invoke the task on the regular cadence in the meantime.
diff --git a/.changeset/old-bikes-study.md b/.changeset/old-bikes-study.md
new file mode 100644
index 0000000000..f2452fcce3
--- /dev/null
+++ b/.changeset/old-bikes-study.md
@@ -0,0 +1,5 @@
+---
+'@backstage/integration': minor
+---
+
+Gerrit Integration: Added the `getGerritProjectsApiUrl` function
diff --git a/.changeset/olive-geese-chew.md b/.changeset/olive-geese-chew.md
deleted file mode 100644
index a08b73b4a7..0000000000
--- a/.changeset/olive-geese-chew.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-'@backstage/backend-common': patch
-'@backstage/integration': patch
----
-
-Support external ID when assuming roles in S3 integration
-
-In order to assume a role created by a 3rd party as external
-ID is needed. This change adds an optional field to the s3
-integration configuration and consumes that in the AwsS3UrlReader.
diff --git a/.changeset/perfect-penguins-rescue.md b/.changeset/perfect-penguins-rescue.md
new file mode 100644
index 0000000000..ab55355121
--- /dev/null
+++ b/.changeset/perfect-penguins-rescue.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend-module-gerrit': minor
+---
+
+Initial version of the `plugin-catalog-backend-module-gerrit` plugin
diff --git a/.changeset/perfect-phones-roll.md b/.changeset/perfect-phones-roll.md
deleted file mode 100644
index c1f9ecdbc1..0000000000
--- a/.changeset/perfect-phones-roll.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/create-app': patch
----
-
-Add helpful README.md files in the original `packages` and `plugins` folders
diff --git a/.changeset/pink-mayflies-rhyme.md b/.changeset/pink-mayflies-rhyme.md
new file mode 100644
index 0000000000..fff17b28b3
--- /dev/null
+++ b/.changeset/pink-mayflies-rhyme.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-newrelic-dashboard': patch
+---
+
+Add `FetchApi` and related `fetchApiRef` which implement fetch. in order to included the Authorization Token to New Relic Dashboard Plugin, so that frontend can send an authenticated proxy call to backend
diff --git a/.changeset/polite-planets-learn.md b/.changeset/polite-planets-learn.md
new file mode 100644
index 0000000000..283af6e801
--- /dev/null
+++ b/.changeset/polite-planets-learn.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-org': patch
+---
+
+Fix linking ownership card to catalog owner filter when namespaces are used
diff --git a/.changeset/poor-knives-boil.md b/.changeset/poor-knives-boil.md
deleted file mode 100644
index dfdc09cdbe..0000000000
--- a/.changeset/poor-knives-boil.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-catalog': patch
-'@backstage/plugin-catalog-react': patch
----
-
-Columns in CatalogTable now change depending on the entity kind, ensuring only relevant columns are displayed.
diff --git a/.changeset/poor-pumpkins-fly.md b/.changeset/poor-pumpkins-fly.md
deleted file mode 100644
index d4462d0010..0000000000
--- a/.changeset/poor-pumpkins-fly.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-azure-devops-backend': patch
----
-
-Stop loading all teams when plugin is initialized
diff --git a/.changeset/popular-geese-prove.md b/.changeset/popular-geese-prove.md
deleted file mode 100644
index 1df79d06c7..0000000000
--- a/.changeset/popular-geese-prove.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Updated the plugin template to install version 14 of `@testing-library/user-event`.
-
-To apply this change to your own project, update the `devDependencies` section in your `package.json` files:
-
-```diff
- "devDependencies": {
- ... omitted dev dependencies ...
-- "@testing-library/user-event": "^13.1.8",
-+ "@testing-library/user-event": "^14.0.0",
- ... omitted dev dependencies ...
- }
-```
diff --git a/.changeset/pre.json b/.changeset/pre.json
index 27d3eeea2f..f598c9f725 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -2,258 +2,195 @@
"mode": "pre",
"tag": "next",
"initialVersions": {
- "example-app": "0.2.69",
- "@backstage/app-defaults": "1.0.0",
- "example-backend": "0.2.69",
- "@backstage/backend-common": "0.13.1",
- "@backstage/backend-tasks": "0.2.1",
- "@backstage/backend-test-utils": "0.1.22",
- "@backstage/catalog-client": "1.0.0",
- "@backstage/catalog-model": "1.0.0",
- "@backstage/cli": "0.16.0",
+ "example-app": "0.2.70",
+ "@backstage/app-defaults": "1.0.1",
+ "example-backend": "0.2.70",
+ "@backstage/backend-common": "0.13.2",
+ "@backstage/backend-tasks": "0.3.0",
+ "@backstage/backend-test-utils": "0.1.23",
+ "@backstage/catalog-client": "1.0.1",
+ "@backstage/catalog-model": "1.0.1",
+ "@backstage/cli": "0.17.0",
"@backstage/cli-common": "0.1.8",
- "@backstage/codemods": "0.1.36",
+ "@backstage/codemods": "0.1.37",
"@backstage/config": "1.0.0",
- "@backstage/config-loader": "1.0.0",
- "@backstage/core-app-api": "1.0.0",
- "@backstage/core-components": "0.9.2",
- "@backstage/core-plugin-api": "1.0.0",
- "@backstage/create-app": "0.4.24",
- "@backstage/dev-utils": "1.0.0",
+ "@backstage/config-loader": "1.1.0",
+ "@backstage/core-app-api": "1.0.1",
+ "@backstage/core-components": "0.9.3",
+ "@backstage/core-plugin-api": "1.0.1",
+ "@backstage/create-app": "0.4.26",
+ "@backstage/dev-utils": "1.0.1",
"e2e-test": "0.2.0",
"@backstage/errors": "1.0.0",
- "@backstage/integration": "1.0.0",
- "@backstage/integration-react": "1.0.0",
+ "@backstage/integration": "1.1.0",
+ "@backstage/integration-react": "1.0.1",
"@backstage/release-manifests": "0.0.2",
- "@backstage/search-common": "0.3.2",
- "@techdocs/cli": "1.0.0",
- "techdocs-cli-embedded-app": "0.2.68",
- "@backstage/techdocs-common": "0.11.13",
- "@backstage/test-utils": "1.0.0",
+ "@backstage/search-common": "0.3.3",
+ "@techdocs/cli": "1.1.0",
+ "techdocs-cli-embedded-app": "0.2.69",
+ "@backstage/techdocs-common": "0.11.14",
+ "@backstage/test-utils": "1.0.1",
"@backstage/theme": "0.2.15",
"@backstage/types": "1.0.0",
- "@backstage/version-bridge": "1.0.0",
- "@backstage/plugin-airbrake": "0.3.3",
- "@backstage/plugin-airbrake-backend": "0.2.3",
- "@backstage/plugin-allure": "0.1.19",
- "@backstage/plugin-analytics-module-ga": "0.1.14",
- "@backstage/plugin-apache-airflow": "0.1.11",
- "@backstage/plugin-api-docs": "0.8.3",
- "@backstage/plugin-app-backend": "0.3.30",
- "@backstage/plugin-auth-backend": "0.12.2",
- "@backstage/plugin-auth-node": "0.1.6",
- "@backstage/plugin-azure-devops": "0.1.19",
- "@backstage/plugin-azure-devops-backend": "0.3.9",
+ "@backstage/version-bridge": "1.0.1",
+ "@backstage/plugin-airbrake": "0.3.4",
+ "@backstage/plugin-airbrake-backend": "0.2.4",
+ "@backstage/plugin-allure": "0.1.20",
+ "@backstage/plugin-analytics-module-ga": "0.1.15",
+ "@backstage/plugin-apache-airflow": "0.1.12",
+ "@backstage/plugin-api-docs": "0.8.4",
+ "@backstage/plugin-app-backend": "0.3.31",
+ "@backstage/plugin-auth-backend": "0.13.0",
+ "@backstage/plugin-auth-node": "0.2.0",
+ "@backstage/plugin-azure-devops": "0.1.20",
+ "@backstage/plugin-azure-devops-backend": "0.3.10",
"@backstage/plugin-azure-devops-common": "0.2.2",
- "@backstage/plugin-badges": "0.2.27",
- "@backstage/plugin-badges-backend": "0.1.24",
- "@backstage/plugin-bazaar": "0.1.18",
- "@backstage/plugin-bazaar-backend": "0.1.14",
- "@backstage/plugin-bitrise": "0.1.30",
- "@backstage/plugin-catalog": "1.0.0",
- "@backstage/plugin-catalog-backend": "1.0.0",
- "@backstage/plugin-catalog-backend-module-aws": "0.1.3",
- "@backstage/plugin-catalog-backend-module-azure": "0.1.1",
- "@backstage/plugin-catalog-backend-module-bitbucket": "0.1.1",
- "@backstage/plugin-catalog-backend-module-github": "0.1.1",
- "@backstage/plugin-catalog-backend-module-gitlab": "0.1.1",
- "@backstage/plugin-catalog-backend-module-ldap": "0.4.1",
- "@backstage/plugin-catalog-backend-module-msgraph": "0.3.0",
- "@backstage/plugin-catalog-common": "1.0.0",
- "@backstage/plugin-catalog-graph": "0.2.15",
- "@backstage/plugin-catalog-graphql": "0.3.7",
- "@backstage/plugin-catalog-import": "0.8.6",
- "@backstage/plugin-catalog-react": "1.0.0",
- "@backstage/plugin-cicd-statistics": "0.1.5",
- "@backstage/plugin-circleci": "0.3.3",
- "@backstage/plugin-cloudbuild": "0.3.3",
- "@backstage/plugin-code-climate": "0.1.3",
- "@backstage/plugin-code-coverage": "0.1.30",
- "@backstage/plugin-code-coverage-backend": "0.1.28",
- "@backstage/plugin-config-schema": "0.1.26",
- "@backstage/plugin-cost-insights": "0.11.25",
- "@backstage/plugin-explore": "0.3.34",
- "@backstage/plugin-explore-react": "0.0.15",
- "@backstage/plugin-firehydrant": "0.1.20",
- "@backstage/plugin-fossa": "0.2.35",
- "@backstage/plugin-gcalendar": "0.2.0",
- "@backstage/plugin-gcp-projects": "0.3.22",
- "@backstage/plugin-git-release-manager": "0.3.16",
- "@backstage/plugin-github-actions": "0.5.3",
- "@backstage/plugin-github-deployments": "0.1.34",
- "@backstage/plugin-gitops-profiles": "0.3.21",
- "@backstage/plugin-gocd": "0.1.9",
- "@backstage/plugin-graphiql": "0.2.35",
- "@backstage/plugin-graphql-backend": "0.1.20",
- "@backstage/plugin-home": "0.4.19",
- "@backstage/plugin-ilert": "0.1.29",
- "@backstage/plugin-jenkins": "0.7.2",
- "@backstage/plugin-jenkins-backend": "0.1.19",
- "@backstage/plugin-jenkins-common": "0.1.2",
- "@backstage/plugin-kafka": "0.3.3",
- "@backstage/plugin-kafka-backend": "0.2.23",
- "@backstage/plugin-kubernetes": "0.6.3",
- "@backstage/plugin-kubernetes-backend": "0.4.13",
- "@backstage/plugin-kubernetes-common": "0.2.8",
- "@backstage/plugin-lighthouse": "0.3.3",
- "@backstage/plugin-newrelic": "0.3.21",
- "@backstage/plugin-newrelic-dashboard": "0.1.11",
- "@backstage/plugin-org": "0.5.3",
- "@backstage/plugin-pagerduty": "0.3.30",
- "@backstage/plugin-periskop": "0.1.1",
- "@backstage/plugin-periskop-backend": "0.1.1",
- "@backstage/plugin-permission-backend": "0.5.5",
- "@backstage/plugin-permission-common": "0.5.3",
- "@backstage/plugin-permission-node": "0.5.5",
- "@backstage/plugin-permission-react": "0.3.4",
- "@backstage/plugin-proxy-backend": "0.2.24",
- "@backstage/plugin-rollbar": "0.4.3",
- "@backstage/plugin-rollbar-backend": "0.1.27",
- "@backstage/plugin-scaffolder": "1.0.0",
- "@backstage/plugin-scaffolder-backend": "1.0.0",
- "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.5",
- "@backstage/plugin-scaffolder-backend-module-rails": "0.3.5",
- "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.3",
- "@backstage/plugin-scaffolder-common": "1.0.0",
- "@backstage/plugin-search": "0.7.4",
- "@backstage/plugin-search-backend": "0.4.8",
- "@backstage/plugin-search-backend-module-elasticsearch": "0.1.2",
- "@backstage/plugin-search-backend-module-pg": "0.3.1",
- "@backstage/plugin-search-backend-node": "0.5.2",
- "@backstage/plugin-search-common": "0.3.2",
- "@backstage/plugin-sentry": "0.3.41",
- "@backstage/plugin-shortcuts": "0.2.4",
- "@backstage/plugin-sonarqube": "0.3.3",
- "@backstage/plugin-splunk-on-call": "0.3.27",
- "@backstage/plugin-tech-insights": "0.1.13",
- "@backstage/plugin-tech-insights-backend": "0.2.10",
- "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.14",
+ "@backstage/plugin-badges": "0.2.28",
+ "@backstage/plugin-badges-backend": "0.1.25",
+ "@backstage/plugin-bazaar": "0.1.19",
+ "@backstage/plugin-bazaar-backend": "0.1.15",
+ "@backstage/plugin-bitrise": "0.1.31",
+ "@backstage/plugin-catalog": "1.1.0",
+ "@backstage/plugin-catalog-backend": "1.1.0",
+ "@backstage/plugin-catalog-backend-module-aws": "0.1.4",
+ "@backstage/plugin-catalog-backend-module-azure": "0.1.2",
+ "@backstage/plugin-catalog-backend-module-bitbucket": "0.1.2",
+ "@backstage/plugin-catalog-backend-module-github": "0.1.2",
+ "@backstage/plugin-catalog-backend-module-gitlab": "0.1.2",
+ "@backstage/plugin-catalog-backend-module-ldap": "0.4.2",
+ "@backstage/plugin-catalog-backend-module-msgraph": "0.3.1",
+ "@backstage/plugin-catalog-common": "1.0.1",
+ "@backstage/plugin-catalog-graph": "0.2.16",
+ "@backstage/plugin-catalog-graphql": "0.3.8",
+ "@backstage/plugin-catalog-import": "0.8.7",
+ "@backstage/plugin-catalog-react": "1.0.1",
+ "@backstage/plugin-cicd-statistics": "0.1.6",
+ "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.0",
+ "@backstage/plugin-circleci": "0.3.4",
+ "@backstage/plugin-cloudbuild": "0.3.4",
+ "@backstage/plugin-code-climate": "0.1.4",
+ "@backstage/plugin-code-coverage": "0.1.31",
+ "@backstage/plugin-code-coverage-backend": "0.1.29",
+ "@backstage/plugin-config-schema": "0.1.27",
+ "@backstage/plugin-cost-insights": "0.11.26",
+ "@backstage/plugin-explore": "0.3.35",
+ "@backstage/plugin-explore-react": "0.0.16",
+ "@backstage/plugin-firehydrant": "0.1.21",
+ "@backstage/plugin-fossa": "0.2.36",
+ "@backstage/plugin-gcalendar": "0.3.0",
+ "@backstage/plugin-gcp-projects": "0.3.23",
+ "@backstage/plugin-git-release-manager": "0.3.17",
+ "@backstage/plugin-github-actions": "0.5.4",
+ "@backstage/plugin-github-deployments": "0.1.35",
+ "@backstage/plugin-gitops-profiles": "0.3.22",
+ "@backstage/plugin-gocd": "0.1.10",
+ "@backstage/plugin-graphiql": "0.2.36",
+ "@backstage/plugin-graphql-backend": "0.1.21",
+ "@backstage/plugin-home": "0.4.20",
+ "@backstage/plugin-ilert": "0.1.30",
+ "@backstage/plugin-jenkins": "0.7.3",
+ "@backstage/plugin-jenkins-backend": "0.1.20",
+ "@backstage/plugin-jenkins-common": "0.1.3",
+ "@backstage/plugin-kafka": "0.3.4",
+ "@backstage/plugin-kafka-backend": "0.2.24",
+ "@backstage/plugin-kubernetes": "0.6.4",
+ "@backstage/plugin-kubernetes-backend": "0.5.0",
+ "@backstage/plugin-kubernetes-common": "0.2.9",
+ "@backstage/plugin-lighthouse": "0.3.4",
+ "@backstage/plugin-newrelic": "0.3.22",
+ "@backstage/plugin-newrelic-dashboard": "0.1.12",
+ "@backstage/plugin-org": "0.5.4",
+ "@backstage/plugin-pagerduty": "0.3.31",
+ "@backstage/plugin-periskop": "0.1.2",
+ "@backstage/plugin-periskop-backend": "0.1.2",
+ "@backstage/plugin-permission-backend": "0.5.6",
+ "@backstage/plugin-permission-common": "0.6.0",
+ "@backstage/plugin-permission-node": "0.6.0",
+ "@backstage/plugin-permission-react": "0.4.0",
+ "@backstage/plugin-proxy-backend": "0.2.25",
+ "@backstage/plugin-rollbar": "0.4.4",
+ "@backstage/plugin-rollbar-backend": "0.1.28",
+ "@backstage/plugin-scaffolder": "1.1.0",
+ "@backstage/plugin-scaffolder-backend": "1.1.0",
+ "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.6",
+ "@backstage/plugin-scaffolder-backend-module-rails": "0.3.6",
+ "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.4",
+ "@backstage/plugin-scaffolder-common": "1.0.1",
+ "@backstage/plugin-search": "0.8.0",
+ "@backstage/plugin-search-backend": "0.5.0",
+ "@backstage/plugin-search-backend-module-elasticsearch": "0.1.3",
+ "@backstage/plugin-search-backend-module-pg": "0.3.2",
+ "@backstage/plugin-search-backend-node": "0.6.0",
+ "@backstage/plugin-search-common": "0.3.3",
+ "@backstage/plugin-search-react": "0.1.0",
+ "@backstage/plugin-sentry": "0.3.42",
+ "@backstage/plugin-shortcuts": "0.2.5",
+ "@backstage/plugin-sonarqube": "0.3.4",
+ "@backstage/plugin-splunk-on-call": "0.3.28",
+ "@backstage/plugin-stack-overflow": "0.1.0",
+ "@backstage/plugin-stack-overflow-backend": "0.1.0",
+ "@backstage/plugin-tech-insights": "0.2.0",
+ "@backstage/plugin-tech-insights-backend": "0.3.0",
+ "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.15",
"@backstage/plugin-tech-insights-common": "0.2.4",
- "@backstage/plugin-tech-insights-node": "0.2.8",
- "@backstage/plugin-tech-radar": "0.5.10",
- "@backstage/plugin-techdocs": "1.0.0",
- "@backstage/plugin-techdocs-backend": "1.0.0",
- "@backstage/plugin-techdocs-node": "1.0.0",
- "@backstage/plugin-todo": "0.2.5",
- "@backstage/plugin-todo-backend": "0.1.27",
- "@backstage/plugin-user-settings": "0.4.2",
- "@backstage/plugin-xcmetrics": "0.2.23",
- "@backstage/plugin-stack-overflow": "0.0.0",
- "@backstage/plugin-stack-overflow-backend": "0.0.0"
+ "@backstage/plugin-tech-insights-node": "0.2.9",
+ "@backstage/plugin-tech-radar": "0.5.11",
+ "@backstage/plugin-techdocs": "1.1.0",
+ "@backstage/plugin-techdocs-backend": "1.1.0",
+ "@backstage/plugin-techdocs-node": "1.1.0",
+ "@backstage/plugin-techdocs-react": "0.1.0",
+ "@backstage/plugin-todo": "0.2.6",
+ "@backstage/plugin-todo-backend": "0.1.28",
+ "@backstage/plugin-user-settings": "0.4.3",
+ "@backstage/plugin-xcmetrics": "0.2.24",
+ "@backstage/plugin-catalog-backend-module-gerrit": "0.0.0",
+ "@backstage/plugin-techdocs-module-addons-contrib": "0.0.0"
},
"changesets": [
- "afraid-boats-check",
- "angry-pens-begin",
- "beige-avocados-matter",
- "beige-baboons-walk",
- "big-buses-clap",
- "big-mayflies-sin",
- "blue-beers-kiss",
- "brave-chairs-stare",
- "breezy-schools-compete",
- "calm-walls-heal",
- "clean-lions-taste",
- "clever-donuts-teach",
- "dependabot-05b19b9",
- "dependabot-2b68456",
- "dependabot-51da438",
- "dependabot-6754062",
- "dependabot-7272684",
- "dependabot-84caed8",
- "dependabot-c1fe92f",
- "dependabot-c762551",
- "dependabot-ebb092c",
- "dry-fans-arrive",
- "eleven-days-brush",
- "eleven-frogs-promise",
- "eleven-pens-collect",
- "empty-pens-invent",
- "fair-dingos-glow",
- "fair-lamps-leave",
- "famous-seas-flash",
- "fast-cheetahs-grow",
- "few-buttons-breathe",
- "few-mayflies-divide",
- "forty-poets-tie",
- "four-birds-peel",
- "fresh-bulldogs-own",
- "fresh-cobras-admire",
- "fresh-dodos-rush",
- "grumpy-parents-prove",
- "happy-foxes-arrive",
- "happy-mugs-camp",
- "hip-poems-breathe",
- "itchy-candles-type",
- "khaki-cougars-lick",
- "khaki-pears-march",
- "large-coins-arrive",
- "light-drinks-rule",
- "mean-pumas-search",
- "mean-rabbits-tell",
- "mean-tomatoes-shout",
- "metal-queens-cheat",
- "mighty-suns-drop",
- "modern-actors-notice",
- "modern-pumas-join",
- "moody-apes-tickle",
- "moody-ducks-return",
- "moody-pigs-rush",
- "new-lions-run",
- "new-singers-lie",
- "nine-grapes-turn",
- "ninety-fishes-vanish",
- "ninety-radios-protect",
- "olive-geese-chew",
- "perfect-phones-roll",
- "poor-knives-boil",
- "poor-pumpkins-fly",
- "pretty-ghosts-scream",
- "purple-boats-punch",
- "purple-laws-give",
- "rare-waves-hammer",
- "red-snakes-float",
- "rich-maps-hear",
- "rotten-planes-watch",
- "rude-toes-compare",
- "seven-apricots-sell",
- "sharp-terms-tap",
- "shiny-seas-yell",
- "short-knives-wave",
- "silent-bobcats-matter",
- "silly-llamas-relax",
- "silver-drinks-study",
- "silver-panthers-occur",
- "silver-pots-call",
- "smart-phones-exist",
- "sour-cameras-deliver",
- "sour-lobsters-sniff",
- "stale-carrots-smile",
- "strange-wasps-whisper",
- "stupid-ways-think",
- "swift-fans-shout",
- "swift-trees-rest",
- "tame-cars-press",
- "tasty-beans-clap",
- "tasty-emus-hunt",
- "tasty-goats-shout",
- "tasty-pears-shake",
- "techdocs-coats-obey",
- "techdocs-head-shoulders-knees-toes",
- "techdocs-parents-suffer",
- "thick-comics-fold",
- "thin-deers-turn",
- "thin-lizards-battle",
- "tidy-days-warn",
- "tidy-emus-stare",
- "twelve-birds-wait",
- "twelve-buses-nail",
- "unlucky-schools-heal",
- "unlucky-snakes-turn",
- "warm-actors-attend",
- "warm-mangos-compete",
- "wicked-beds-return",
- "wicked-feet-clap",
- "witty-years-sniff",
- "yellow-hats-remember"
+ "breezy-days-prove",
+ "cool-ties-share",
+ "curly-parrots-applaud",
+ "dirty-eagles-hunt",
+ "eighty-chicken-retire",
+ "fair-kings-retire",
+ "fuzzy-seahorses-teach",
+ "giant-cheetahs-thank",
+ "hip-adults-collect",
+ "honest-kids-live",
+ "hot-peaches-give",
+ "lazy-zebras-pay",
+ "mean-flowers-change",
+ "metal-pants-fly",
+ "moody-laws-boil",
+ "moody-suns-smell",
+ "nasty-humans-give",
+ "new-beds-argue",
+ "old-bikes-study",
+ "perfect-penguins-rescue",
+ "pink-mayflies-rhyme",
+ "renovate-bf43c44",
+ "search-dry-wolves-join",
+ "search-heavy-llamas-worry",
+ "seven-deers-rule",
+ "shiny-students-approve",
+ "short-dodos-sparkle",
+ "short-flies-collect",
+ "silver-readers-deliver",
+ "sixty-llamas-change",
+ "spotty-plums-rule",
+ "stale-pigs-reply",
+ "strong-mangos-sell",
+ "swift-bugs-share",
+ "swift-parrots-hammer",
+ "tasty-drinks-teach",
+ "techdocs-changeset-not-found",
+ "techdocs-nice-boats-wonder",
+ "techdocs-quick-owls-smile",
+ "techdocs-touch-screen-wipes",
+ "thick-bees-brush",
+ "tough-forks-carry",
+ "violet-steaks-knock",
+ "wild-pigs-work",
+ "wise-emus-wait"
]
}
diff --git a/.changeset/pretty-ghosts-scream.md b/.changeset/pretty-ghosts-scream.md
deleted file mode 100644
index 7a604d75b6..0000000000
--- a/.changeset/pretty-ghosts-scream.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-test-utils': patch
----
-
-`TestDatabases.create` will no longer set up an `afterAll` test handler if no databases are supported.
diff --git a/.changeset/proud-news-perform.md b/.changeset/proud-news-perform.md
deleted file mode 100644
index 9d5cbae8ab..0000000000
--- a/.changeset/proud-news-perform.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-cicd-statistics-module-gitlab': minor
----
-
-Created a module to extract the CI/CD statistics from a Gitlab repository.
-Read the `README.md` in the `cicd-statistics-module-gitlab` plugin folder on how to set it up.
diff --git a/.changeset/proud-teachers-draw.md b/.changeset/proud-teachers-draw.md
deleted file mode 100644
index dbce78c3c2..0000000000
--- a/.changeset/proud-teachers-draw.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
----
-
-Updated the "unregister location" behavior in `UnregisterEntityDialog`. Removed unnecessary entity deletion requests that were sent after successfully deleting a location.
diff --git a/.changeset/purple-boats-punch.md b/.changeset/purple-boats-punch.md
deleted file mode 100644
index 817f0a79bc..0000000000
--- a/.changeset/purple-boats-punch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend': patch
----
-
-**DEPRECATION**: The `tokenIssuer` option for `OAuthAdapter` is no longer needed and has been deprecated.
diff --git a/.changeset/purple-laws-give.md b/.changeset/purple-laws-give.md
deleted file mode 100644
index 7e985092e2..0000000000
--- a/.changeset/purple-laws-give.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
----
-
-Removed broken link from Labels section of entity inspector.
diff --git a/.changeset/quick-avocados-sell.md b/.changeset/quick-avocados-sell.md
deleted file mode 100644
index 74014dca66..0000000000
--- a/.changeset/quick-avocados-sell.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Fixed a bug were the `react-hot-loader` transform was being applied to backend development builds.
diff --git a/.changeset/quiet-ties-happen.md b/.changeset/quiet-ties-happen.md
deleted file mode 100644
index ece2ff7e23..0000000000
--- a/.changeset/quiet-ties-happen.md
+++ /dev/null
@@ -1,67 +0,0 @@
----
-'@backstage/app-defaults': patch
-'@backstage/cli': patch
-'@backstage/codemods': patch
-'@backstage/config-loader': patch
-'@backstage/core-app-api': patch
-'@backstage/core-components': patch
-'@backstage/core-plugin-api': patch
-'@backstage/create-app': patch
-'@backstage/integration-react': patch
-'@techdocs/cli': patch
-'@backstage/test-utils': patch
-'@backstage/plugin-airbrake': patch
-'@backstage/plugin-allure': patch
-'@backstage/plugin-analytics-module-ga': patch
-'@backstage/plugin-apache-airflow': patch
-'@backstage/plugin-api-docs': patch
-'@backstage/plugin-azure-devops': patch
-'@backstage/plugin-badges': patch
-'@backstage/plugin-bitrise': patch
-'@backstage/plugin-circleci': patch
-'@backstage/plugin-cloudbuild': patch
-'@backstage/plugin-code-climate': patch
-'@backstage/plugin-code-coverage': patch
-'@backstage/plugin-config-schema': patch
-'@backstage/plugin-cost-insights': patch
-'@backstage/plugin-explore': patch
-'@backstage/plugin-explore-react': patch
-'@backstage/plugin-firehydrant': patch
-'@backstage/plugin-fossa': patch
-'@backstage/plugin-gcalendar': patch
-'@backstage/plugin-gcp-projects': patch
-'@backstage/plugin-git-release-manager': patch
-'@backstage/plugin-github-actions': patch
-'@backstage/plugin-github-deployments': patch
-'@backstage/plugin-gitops-profiles': patch
-'@backstage/plugin-gocd': patch
-'@backstage/plugin-graphiql': patch
-'@backstage/plugin-home': patch
-'@backstage/plugin-ilert': patch
-'@backstage/plugin-jenkins': patch
-'@backstage/plugin-kafka': patch
-'@backstage/plugin-kubernetes': patch
-'@backstage/plugin-lighthouse': patch
-'@backstage/plugin-newrelic': patch
-'@backstage/plugin-org': patch
-'@backstage/plugin-pagerduty': patch
-'@backstage/plugin-periskop': patch
-'@backstage/plugin-rollbar': patch
-'@backstage/plugin-scaffolder': patch
-'@backstage/plugin-scaffolder-backend-module-rails': patch
-'@backstage/plugin-search': patch
-'@backstage/plugin-search-backend-node': patch
-'@backstage/plugin-sentry': patch
-'@backstage/plugin-shortcuts': patch
-'@backstage/plugin-sonarqube': patch
-'@backstage/plugin-splunk-on-call': patch
-'@backstage/plugin-stack-overflow': patch
-'@backstage/plugin-tech-insights': patch
-'@backstage/plugin-tech-radar': patch
-'@backstage/plugin-techdocs': patch
-'@backstage/plugin-todo': patch
-'@backstage/plugin-user-settings': patch
-'@backstage/plugin-xcmetrics': patch
----
-
-Bump to using `@types/node` v16
diff --git a/.changeset/rare-emus-agree.md b/.changeset/rare-emus-agree.md
deleted file mode 100644
index 423d4c6259..0000000000
--- a/.changeset/rare-emus-agree.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-jenkins-backend': patch
----
-
-feature: provide access token to JenkinsInstanceConfig. It can be passed to other backend calls if authentication enabled. DefaultJenkinsInfoProvider sends always this token to catalog api if access token exists.
diff --git a/.changeset/rare-parents-pretend.md b/.changeset/rare-parents-pretend.md
deleted file mode 100644
index f211a85efe..0000000000
--- a/.changeset/rare-parents-pretend.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-'@backstage/create-app': patch
----
-
-Accept `PermissionEvaluator` instead of the deprecated `PermissionAuthorizer`.
-
-Apply the following to `packages/backend/src/types.ts`:
-
-```diff
-- import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
-+ import { PermissionEvaluator } from '@backstage/plugin-permission-common';
-
- export type PluginEnvironment = {
- ...
- discovery: PluginEndpointDiscovery;
- tokenManager: TokenManager;
- scheduler: PluginTaskScheduler;
-- permissions: PermissionAuthorizer;
-+ permissions: PermissionEvaluator;
- };
-```
diff --git a/.changeset/rare-waves-hammer.md b/.changeset/rare-waves-hammer.md
deleted file mode 100644
index 5b9f7c845d..0000000000
--- a/.changeset/rare-waves-hammer.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-common': patch
----
-
-Add `@alpha` `CatalogEntityPermission` convenience type, available for import from `@backstage/plugin-catalog-common/alpha`.
diff --git a/.changeset/red-snakes-float.md b/.changeset/red-snakes-float.md
deleted file mode 100644
index f1bd16d84c..0000000000
--- a/.changeset/red-snakes-float.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
----
-
-Add support for string refs to the `EntityRefLinks` component
diff --git a/.changeset/renovate-05696d1.md b/.changeset/renovate-05696d1.md
new file mode 100644
index 0000000000..cd9fe676b0
--- /dev/null
+++ b/.changeset/renovate-05696d1.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-api-docs': patch
+---
+
+Updated dependency `@asyncapi/react-component` to `1.0.0-next.37`.
diff --git a/.changeset/renovate-b063c4b.md b/.changeset/renovate-b063c4b.md
new file mode 100644
index 0000000000..89292d03a0
--- /dev/null
+++ b/.changeset/renovate-b063c4b.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': patch
+---
+
+Updated dependency `@codemirror/legacy-modes` to `^0.20.0`.
diff --git a/.changeset/renovate-bf43c44.md b/.changeset/renovate-bf43c44.md
new file mode 100644
index 0000000000..696017c72b
--- /dev/null
+++ b/.changeset/renovate-bf43c44.md
@@ -0,0 +1,18 @@
+---
+'@backstage/backend-common': patch
+'@backstage/cli': patch
+'@backstage/config-loader': patch
+'@backstage/create-app': patch
+'@backstage/plugin-app-backend': patch
+'@backstage/plugin-auth-backend': patch
+'@backstage/plugin-catalog-backend-module-gerrit': patch
+'@backstage/plugin-catalog-backend': patch
+'@backstage/plugin-kubernetes-backend': patch
+'@backstage/plugin-rollbar-backend': patch
+'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch
+'@backstage/plugin-scaffolder-backend': patch
+'@backstage/plugin-techdocs-backend': patch
+'@backstage/plugin-techdocs-node': patch
+---
+
+Updated dependency `fs-extra` to `10.1.0`.
diff --git a/.changeset/rich-maps-hear.md b/.changeset/rich-maps-hear.md
deleted file mode 100644
index 390da8b6bb..0000000000
--- a/.changeset/rich-maps-hear.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-scaffolder': patch
----
-
-Added a new `NextScaffolderRouter` which will eventually replace the exiting router
diff --git a/.changeset/rotten-planes-watch.md b/.changeset/rotten-planes-watch.md
deleted file mode 100644
index 25aa6b83df..0000000000
--- a/.changeset/rotten-planes-watch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend': patch
----
-
-Handle trailing slashes on GitHub `enterpriseInstanceUrl` settings
diff --git a/.changeset/rude-bees-rest.md b/.changeset/rude-bees-rest.md
deleted file mode 100644
index 7ca4e7492c..0000000000
--- a/.changeset/rude-bees-rest.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-search-react': minor
----
-
-New search package to hold things the search plugin itself and other frontend plugins (e.g. techdocs, home) depend on.
diff --git a/.changeset/rude-toes-compare.md b/.changeset/rude-toes-compare.md
deleted file mode 100644
index 3a767ec95b..0000000000
--- a/.changeset/rude-toes-compare.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-org': patch
----
-
-Added the `metadata.description` to the bottom of each member on the MembersListCard
diff --git a/.changeset/search-dry-wolves-join.md b/.changeset/search-dry-wolves-join.md
new file mode 100644
index 0000000000..2eb613b642
--- /dev/null
+++ b/.changeset/search-dry-wolves-join.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search': patch
+---
+
+Fix issue with `HomePageSearchBar` requiring `SearchContext`
diff --git a/.changeset/search-heavy-llamas-worry.md b/.changeset/search-heavy-llamas-worry.md
new file mode 100644
index 0000000000..2d77d6c4d6
--- /dev/null
+++ b/.changeset/search-heavy-llamas-worry.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-react': patch
+---
+
+Export `useSearchContextCheck` hook to check if the search context is available
diff --git a/.changeset/selfish-actors-walk.md b/.changeset/selfish-actors-walk.md
deleted file mode 100644
index 755f1c3de6..0000000000
--- a/.changeset/selfish-actors-walk.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-components': patch
----
-
-Exported `IdentityProviders` type.
diff --git a/.changeset/seven-deers-rule.md b/.changeset/seven-deers-rule.md
new file mode 100644
index 0000000000..6b1976cbfa
--- /dev/null
+++ b/.changeset/seven-deers-rule.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-backend-module-elasticsearch': patch
+---
+
+Prevent orphaned stale indices by permanently marking them for deletion so removal can be re-attempted if it failed previously
diff --git a/.changeset/sharp-terms-tap.md b/.changeset/sharp-terms-tap.md
deleted file mode 100644
index 72e888a94e..0000000000
--- a/.changeset/sharp-terms-tap.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-components': patch
----
-
-Adding a name to the core-components Tab styles so can customise in the theme settings
diff --git a/.changeset/shiny-students-approve.md b/.changeset/shiny-students-approve.md
new file mode 100644
index 0000000000..77de3ffc04
--- /dev/null
+++ b/.changeset/shiny-students-approve.md
@@ -0,0 +1,21 @@
+---
+'@backstage/plugin-scaffolder-backend': minor
+---
+
+Split `publish:bitbucket` into `publish:bitbucketCloud` and `publish:bitbucketServer`.
+
+In order to migrate from the deprecated action, you need to replace the use of action
+`publish:bitbucket` in your templates with the use of either `publish:bitbucketCloud`
+or `publish:bitbucketServer` - depending on which destination SCM provider you use.
+
+Additionally, these actions will not utilize `integrations.bitbucket` anymore,
+but `integrations.bitbucketCloud` or `integrations.bitbucketServer` respectively.
+You may or may not have migrated to these already.
+
+As described in a previous changeset, using these two replacement integrations configs
+will not compromise use cases which still rely on `integrations.bitbucket` as this was
+set up in a backwards compatible way.
+
+Additionally, please mind that the option `enableLFS` is only available (and always was)
+for Bitbucket Server use cases and therefore, is not even part of the schema for
+`publish:bitbucketCloud` anymore.
diff --git a/.changeset/short-dodos-sparkle.md b/.changeset/short-dodos-sparkle.md
new file mode 100644
index 0000000000..342b8cc22b
--- /dev/null
+++ b/.changeset/short-dodos-sparkle.md
@@ -0,0 +1,10 @@
+---
+'@backstage/plugin-catalog-backend-module-aws': patch
+---
+
+Fix S3 object URL creation at AwsS3EntityProvider by
+
+- handle absence of region config,
+- handle regions with region-less URIs (us-east-1),
+- apply URI encoding,
+- and simplify the logic overall.
diff --git a/.changeset/short-flies-collect.md b/.changeset/short-flies-collect.md
new file mode 100644
index 0000000000..d393f92175
--- /dev/null
+++ b/.changeset/short-flies-collect.md
@@ -0,0 +1,5 @@
+---
+'@backstage/config-loader': patch
+---
+
+Handle empty config files gracefully
diff --git a/.changeset/short-knives-wave.md b/.changeset/short-knives-wave.md
deleted file mode 100644
index a7372618e2..0000000000
--- a/.changeset/short-knives-wave.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': minor
----
-
-export `locationSpecToLocationEntity`
diff --git a/.changeset/silent-bobcats-matter.md b/.changeset/silent-bobcats-matter.md
deleted file mode 100644
index f67f2d3ede..0000000000
--- a/.changeset/silent-bobcats-matter.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-'@backstage/cli': patch
-'@backstage/config-loader': patch
-'@backstage/core-app-api': patch
-'@backstage/plugin-catalog-backend-module-bitbucket': patch
-'@backstage/plugin-tech-insights-backend': patch
----
-
-Implemented changes suggested by Deepsource.io including multiple double non-null assertion operators and unexpected awaits for non-promise values.
diff --git a/.changeset/silly-forks-study.md b/.changeset/silly-forks-study.md
deleted file mode 100644
index d337aecec6..0000000000
--- a/.changeset/silly-forks-study.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-home': patch
----
-
-Updated the dependency on `@backstage/config` to `^1.0.0`.
diff --git a/.changeset/silly-llamas-relax.md b/.changeset/silly-llamas-relax.md
deleted file mode 100644
index f5a002d46d..0000000000
--- a/.changeset/silly-llamas-relax.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-tech-radar': patch
----
-
-Fix an issue where the Radar is not updated when switching between different radars
diff --git a/.changeset/silver-drinks-study.md b/.changeset/silver-drinks-study.md
deleted file mode 100644
index f6547057f2..0000000000
--- a/.changeset/silver-drinks-study.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-'@backstage/plugin-catalog-graph': patch
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-graphiql': patch
-'@backstage/plugin-home': patch
-'@backstage/plugin-org': patch
----
-
-Minor API report cleanup
diff --git a/.changeset/silver-panthers-occur.md b/.changeset/silver-panthers-occur.md
deleted file mode 100644
index 211e760d09..0000000000
--- a/.changeset/silver-panthers-occur.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-techdocs': patch
----
-
-Fix broken query selectors on techdocs
diff --git a/.changeset/silver-pots-call.md b/.changeset/silver-pots-call.md
deleted file mode 100644
index 42b3016545..0000000000
--- a/.changeset/silver-pots-call.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-components': patch
----
-
-fix support config ref to use backstage/backstage
diff --git a/.changeset/silver-readers-deliver.md b/.changeset/silver-readers-deliver.md
new file mode 100644
index 0000000000..ce175f97be
--- /dev/null
+++ b/.changeset/silver-readers-deliver.md
@@ -0,0 +1,8 @@
+---
+'@backstage/cli': patch
+'@backstage/codemods': patch
+'@backstage/create-app': patch
+'@techdocs/cli': patch
+---
+
+Bump `commander` to version 9.1.0
diff --git a/.changeset/sixty-llamas-change.md b/.changeset/sixty-llamas-change.md
new file mode 100644
index 0000000000..a0d183d45c
--- /dev/null
+++ b/.changeset/sixty-llamas-change.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-catalog-backend': patch
+'@backstage/plugin-jenkins-backend': patch
+'@backstage/plugin-search-backend': patch
+---
+
+Fixed issue in `PermissionEvaluator` instance check that would cause unexpected "invalid union" errors.
diff --git a/.changeset/smart-phones-exist.md b/.changeset/smart-phones-exist.md
deleted file mode 100644
index eb1c3d041a..0000000000
--- a/.changeset/smart-phones-exist.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Added a new experimental `repo list-deprecations` command, which scans the entire project for usage of deprecated APIs.
diff --git a/.changeset/soft-rice-remember.md b/.changeset/soft-rice-remember.md
deleted file mode 100644
index bf207a0dd5..0000000000
--- a/.changeset/soft-rice-remember.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-permission-react': patch
----
-
-**BREAKING:** Make `IdentityPermissionApi#authorize` typing more strict, using `AuthorizePermissionRequest` and `AuthorizePermissionResponse`.
diff --git a/.changeset/sour-cameras-deliver.md b/.changeset/sour-cameras-deliver.md
deleted file mode 100644
index 21e23e7833..0000000000
--- a/.changeset/sour-cameras-deliver.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-Handle changes to @alpha permission-related types.
-
-- All exported permission rules and conditions now have a `resourceType`.
-- `createCatalogConditionalDecision` now expects supplied conditions to have the appropriate `resourceType`.
-- `createCatalogPermissionRule` now expects `resourceType` as part of the supplied rule object.
-- Introduce new `CatalogPermissionRule` convenience type.
diff --git a/.changeset/sour-lobsters-sniff.md b/.changeset/sour-lobsters-sniff.md
deleted file mode 100644
index fb8d1f2076..0000000000
--- a/.changeset/sour-lobsters-sniff.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-permission-node': patch
----
-
-Fix signature of permission rule in test suites
diff --git a/.changeset/spotty-plums-rule.md b/.changeset/spotty-plums-rule.md
new file mode 100644
index 0000000000..45d1c8280f
--- /dev/null
+++ b/.changeset/spotty-plums-rule.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-search-react': patch
+'@backstage/plugin-techdocs': patch
+---
+
+Removed dependency on `@backstage/core-app-api`.
diff --git a/.changeset/stale-carrots-smile.md b/.changeset/stale-carrots-smile.md
deleted file mode 100644
index 20b77dd834..0000000000
--- a/.changeset/stale-carrots-smile.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-permission-common': patch
----
-
-Add `isPermission` helper method.
diff --git a/.changeset/stale-pigs-reply.md b/.changeset/stale-pigs-reply.md
new file mode 100644
index 0000000000..645648c93f
--- /dev/null
+++ b/.changeset/stale-pigs-reply.md
@@ -0,0 +1,5 @@
+---
+'@backstage/create-app': patch
+---
+
+Added a link to the `${GITHUB_TOKEN}` to document how to generate a token
diff --git a/.changeset/strange-wasps-whisper.md b/.changeset/strange-wasps-whisper.md
deleted file mode 100644
index bef72e276a..0000000000
--- a/.changeset/strange-wasps-whisper.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-common': patch
----
-
-The logger returned from `getVoidLogger` is now uses a silenced console transport instead.
diff --git a/.changeset/strong-mangos-sell.md b/.changeset/strong-mangos-sell.md
new file mode 100644
index 0000000000..614d36cf52
--- /dev/null
+++ b/.changeset/strong-mangos-sell.md
@@ -0,0 +1,16 @@
+---
+'@backstage/plugin-auth-backend': patch
+---
+
+Add more common predefined sign-in resolvers to auth providers.
+
+Add the existing resolver to more providers (already available at `google`):
+
+- `providers.microsoft.resolvers.emailLocalPartMatchingUserEntityName()`
+- `providers.okta.resolvers.emailLocalPartMatchingUserEntityName()`
+
+Add a new resolver for simple email-to-email matching:
+
+- `providers.google.resolvers.emailMatchingUserEntityProfileEmail()`
+- `providers.microsoft.resolvers.emailMatchingUserEntityProfileEmail()`
+- `providers.okta.resolvers.emailMatchingUserEntityProfileEmail()`
diff --git a/.changeset/stupid-ways-think.md b/.changeset/stupid-ways-think.md
deleted file mode 100644
index 19e68fba90..0000000000
--- a/.changeset/stupid-ways-think.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Fixed misleading log message during frontend plugin creation.
diff --git a/.changeset/swift-bugs-share.md b/.changeset/swift-bugs-share.md
new file mode 100644
index 0000000000..c018bdfacf
--- /dev/null
+++ b/.changeset/swift-bugs-share.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Updated the `create-github-app` command to throw an error if the organization argument is a user or a non existing organization.
diff --git a/.changeset/swift-fans-shout.md b/.changeset/swift-fans-shout.md
deleted file mode 100644
index 7a11b70592..0000000000
--- a/.changeset/swift-fans-shout.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-gocd': patch
----
-
-Add pagination controls to GoCD build table
diff --git a/.changeset/swift-parrots-hammer.md b/.changeset/swift-parrots-hammer.md
new file mode 100644
index 0000000000..1b26742937
--- /dev/null
+++ b/.changeset/swift-parrots-hammer.md
@@ -0,0 +1,9 @@
+---
+'@backstage/backend-tasks': patch
+---
+
+Scheduled tasks now have an optional `scope` field. If unset, or having the
+value `'global'`, the old behavior with cross-worker locking is retained. If
+having the value `'local'`, there is no coordination across workers and the
+behavior is more like `setInterval`. This can be used to replace usages of
+`runPeriodically` helpers.
diff --git a/.changeset/swift-trees-rest.md b/.changeset/swift-trees-rest.md
deleted file mode 100644
index 2e76195997..0000000000
--- a/.changeset/swift-trees-rest.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': minor
----
-
-Added `/validate-entity` endpoint
diff --git a/.changeset/tame-cars-press.md b/.changeset/tame-cars-press.md
deleted file mode 100644
index d95edad332..0000000000
--- a/.changeset/tame-cars-press.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-scaffolder': patch
-'@backstage/plugin-techdocs': patch
----
-
-Applied the fix from version 1.0.1 of this package, which is part of the v1.0.2 release of Backstage.
diff --git a/.changeset/tasty-beans-clap.md b/.changeset/tasty-beans-clap.md
deleted file mode 100644
index f171617860..0000000000
--- a/.changeset/tasty-beans-clap.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-bitbucket': patch
----
-
-split BitbucketClient into BitbucketCloudClient, BitbucketServerClient
diff --git a/.changeset/tasty-drinks-teach.md b/.changeset/tasty-drinks-teach.md
new file mode 100644
index 0000000000..4b4a5a748d
--- /dev/null
+++ b/.changeset/tasty-drinks-teach.md
@@ -0,0 +1,7 @@
+---
+'@backstage/backend-common': patch
+'@backstage/plugin-auth-backend': patch
+'@backstage/plugin-auth-node': patch
+---
+
+Update to `jose` 4.6.0
diff --git a/.changeset/tasty-emus-hunt.md b/.changeset/tasty-emus-hunt.md
deleted file mode 100644
index d3b9430bf4..0000000000
--- a/.changeset/tasty-emus-hunt.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog': minor
----
-
-Expose 'initalFilter' through initialKind prop on Catalog Page.
diff --git a/.changeset/tasty-goats-shout.md b/.changeset/tasty-goats-shout.md
deleted file mode 100644
index 5b9356122f..0000000000
--- a/.changeset/tasty-goats-shout.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-gcalendar': minor
----
-
-Fixed issue when not all calendars were fetched for some accounts
diff --git a/.changeset/tasty-pears-shake.md b/.changeset/tasty-pears-shake.md
deleted file mode 100644
index 565cb02b77..0000000000
--- a/.changeset/tasty-pears-shake.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-components': patch
----
-
-Updated ProxiedSignInPageProps docs
diff --git a/.changeset/techdocs-changeset-not-found.md b/.changeset/techdocs-changeset-not-found.md
new file mode 100644
index 0000000000..7ee5ec2b85
--- /dev/null
+++ b/.changeset/techdocs-changeset-not-found.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': patch
+---
+
+Fixed bugs that prevented a 404 error from being shown when it should have been.
diff --git a/.changeset/techdocs-coats-obey.md b/.changeset/techdocs-coats-obey.md
deleted file mode 100644
index 0c2c2b5ac2..0000000000
--- a/.changeset/techdocs-coats-obey.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-techdocs': patch
----
-
-Fix permalink scrolling for anchors where the id starts with a number.
diff --git a/.changeset/techdocs-fresh-panthers-kick.md b/.changeset/techdocs-fresh-panthers-kick.md
deleted file mode 100644
index a35d36a0a8..0000000000
--- a/.changeset/techdocs-fresh-panthers-kick.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@techdocs/cli': patch
----
-
-Adds a new flag to override the entrypoint when using a custom docker image. It could be used to reuse existing images with different entrypoints.
diff --git a/.changeset/techdocs-head-shoulders-knees-toes.md b/.changeset/techdocs-head-shoulders-knees-toes.md
deleted file mode 100644
index f96b624897..0000000000
--- a/.changeset/techdocs-head-shoulders-knees-toes.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-techdocs-backend': patch
----
-
-Fixed a bug affecting those with cache enabled that would result in empty content being cached if the first attempt to load a static asset from storage were made via a `HEAD` request, rather than a `GET` request.
diff --git a/.changeset/techdocs-nice-boats-wonder.md b/.changeset/techdocs-nice-boats-wonder.md
new file mode 100644
index 0000000000..434cde841e
--- /dev/null
+++ b/.changeset/techdocs-nice-boats-wonder.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs-node': patch
+---
+
+Allow usage of custom tags with sequence node type (such as the !ENV tag) in the techdocs mkdocs config.
diff --git a/.changeset/techdocs-parents-suffer.md b/.changeset/techdocs-parents-suffer.md
deleted file mode 100644
index 8e366dd506..0000000000
--- a/.changeset/techdocs-parents-suffer.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-'@backstage/plugin-techdocs': patch
----
-
-Some documentation layout tweaks:
-
-- drawer toggle margins
-- code block margins
-- sidebar drawer width
-- inner content width
-- footer link width
-- sidebar table of contents scroll
diff --git a/.changeset/techdocs-quick-owls-smile.md b/.changeset/techdocs-quick-owls-smile.md
new file mode 100644
index 0000000000..db4202fb5b
--- /dev/null
+++ b/.changeset/techdocs-quick-owls-smile.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-techdocs-module-addons-contrib': minor
+---
+
+A package for contributed TechDocs addons.
+
+In this release it will introduce the ReportIssue addon, which lets you select text and open a GitHub/Gitlab issue.
diff --git a/.changeset/techdocs-swift-weeks-admire.md b/.changeset/techdocs-swift-weeks-admire.md
deleted file mode 100644
index 8a747a8bb3..0000000000
--- a/.changeset/techdocs-swift-weeks-admire.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-'@techdocs/cli': minor
-'@backstage/plugin-techdocs-backend': minor
-'@backstage/plugin-techdocs-node': minor
----
-
-BREAKING: The default Techdocs behavior will no longer attempt to copy `docs/README.md` or `README.md` to `docs/index.md` (if not found). To retain this behavior in your instance, you can set the following config in your `app-config.yaml`:
-
-```yaml
-techdocs:
- generator:
- mkdocs:
- legacyCopyReadmeMdToIndexMd: true
-```
diff --git a/.changeset/techdocs-touch-screen-wipes.md b/.changeset/techdocs-touch-screen-wipes.md
new file mode 100644
index 0000000000..b6467a4232
--- /dev/null
+++ b/.changeset/techdocs-touch-screen-wipes.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-techdocs-react': patch
+'@backstage/plugin-techdocs-module-addons-contrib': patch
+---
+
+Updated the return type of `createTechDocsAddonExtension` to better reflect the fact that passing children to Addon components is not a valid use-case.
diff --git a/.changeset/thick-bees-brush.md b/.changeset/thick-bees-brush.md
new file mode 100644
index 0000000000..4ec068e0a1
--- /dev/null
+++ b/.changeset/thick-bees-brush.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-gcalendar': patch
+---
+
+fixed google API types dependencies
diff --git a/.changeset/thick-comics-fold.md b/.changeset/thick-comics-fold.md
deleted file mode 100644
index 5faf2fd399..0000000000
--- a/.changeset/thick-comics-fold.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-'@backstage/plugin-tech-insights': patch
-'@backstage/plugin-tech-insights-backend': patch
----
-
-Improved the Tech-Insights documentation:
-
-- `lifecycle` examples used `ttl` when it should be `timeToLive`
-- Added list of included FactRetrievers
-- Added full backend example using all included FactRetrievers
-- Added boolean scorecard example image showing results of backend example
diff --git a/.changeset/thin-deers-turn.md b/.changeset/thin-deers-turn.md
deleted file mode 100644
index d148c3fcdf..0000000000
--- a/.changeset/thin-deers-turn.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-components': patch
----
-
-`` now accepts additional props `sidebarOptions` and `submenuOptions` to allow further customization
diff --git a/.changeset/thin-lizards-battle.md b/.changeset/thin-lizards-battle.md
deleted file mode 100644
index de3658f042..0000000000
--- a/.changeset/thin-lizards-battle.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-scaffolder': patch
----
-
-Update `usePermission` usage.
diff --git a/.changeset/thirty-icons-buy.md b/.changeset/thirty-icons-buy.md
deleted file mode 100644
index dd5a9eec19..0000000000
--- a/.changeset/thirty-icons-buy.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/config-loader': minor
----
-
-Added `ignoreSchemaErrors` to `schema.process`.
diff --git a/.changeset/thirty-sloths-knock.md b/.changeset/thirty-sloths-knock.md
deleted file mode 100644
index 1ad559e368..0000000000
--- a/.changeset/thirty-sloths-knock.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-'@backstage/plugin-search': patch
----
-
-The following exports has been moved to `@backstage/plugin-search-react` and will be removed in the next release. import from `@backstage/plugin-search-react` instead.
-
-- `SearchApi` interface.
-- `searchApiRef`
-- `SearchContext`
-- `SearchContextProvider`
-- `useSearch`
diff --git a/.changeset/three-rivers-remain.md b/.changeset/three-rivers-remain.md
deleted file mode 100644
index d6bfeba093..0000000000
--- a/.changeset/three-rivers-remain.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-user-settings': patch
----
-
-Added the ability to render extra setting tabs
diff --git a/.changeset/tidy-days-warn.md b/.changeset/tidy-days-warn.md
deleted file mode 100644
index e84d563f01..0000000000
--- a/.changeset/tidy-days-warn.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/integration': minor
----
-
-Gerrit integration: Added an optional configuration to set the Gitiles base url.
diff --git a/.changeset/tidy-emus-stare.md b/.changeset/tidy-emus-stare.md
deleted file mode 100644
index 93f3dccde7..0000000000
--- a/.changeset/tidy-emus-stare.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-add gitlab to AnnotateScmSlugEntityProcessor
diff --git a/.changeset/tough-forks-carry.md b/.changeset/tough-forks-carry.md
new file mode 100644
index 0000000000..88fd82b55d
--- /dev/null
+++ b/.changeset/tough-forks-carry.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-org': patch
+---
+
+Fix ref to filtered catalog table view when using aggregated relations.
diff --git a/.changeset/twelve-birds-wait.md b/.changeset/twelve-birds-wait.md
deleted file mode 100644
index 6f71ed2cf7..0000000000
--- a/.changeset/twelve-birds-wait.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-'@backstage/catalog-model': patch
----
-
-Added a connection between www-artist and artist-lookup components
-
-
- Screenshots
-
-
-
-
-
-
diff --git a/.changeset/twelve-boats-count.md b/.changeset/twelve-boats-count.md
deleted file mode 100644
index c62309870a..0000000000
--- a/.changeset/twelve-boats-count.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-The `versions:*` commands no longer warns about duplicate plugin libraries, such as `@backstage/plugin-catalog-common`.
diff --git a/.changeset/twelve-buses-nail.md b/.changeset/twelve-buses-nail.md
deleted file mode 100644
index ddeb7f1413..0000000000
--- a/.changeset/twelve-buses-nail.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-'@backstage/cli': minor
----
-
-**BREAKING**: Bump the version range of `jest` from `^26.0.1` to `^27.5.1`. You can find the complete list of breaking changes [here](https://github.com/facebook/jest/releases/tag/v27.0.0).
-
-We strongly recommend to have completed the [package role migration](https://backstage.io/docs/tutorials/package-role-migration) before upgrading to this version, as the package roles are used to automatically determine the testing environment for each package. If you instead want to set an explicit test environment for each package, you can do so for example in the `"jest"` section in `package.json`. The default test environment for all packages is now `node`, which is also the new Jest default.
-
-Note that one of the breaking changes of Jest 27 is that the `jsdom` environment no longer includes `setImmediate` and `clearImmediate`, which means you might need to update some of your frontend packages. Another notable change is that `jest.useFakeTimers` now defaults to the `'modern'` implementation, which also mocks microtasks.
diff --git a/.changeset/unlucky-schools-heal.md b/.changeset/unlucky-schools-heal.md
deleted file mode 100644
index 55daf4e65c..0000000000
--- a/.changeset/unlucky-schools-heal.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-permission-backend': patch
----
-
-- Add more specific check for policies which return conditional decisions for non-resource permissions.
-- Refine permission validation in authorize endpoint to differentiate between `BasicPermission` and `ResourcePermission` instances.
diff --git a/.changeset/unlucky-snakes-turn.md b/.changeset/unlucky-snakes-turn.md
deleted file mode 100644
index bcb31feb40..0000000000
--- a/.changeset/unlucky-snakes-turn.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-jenkins-backend': patch
----
-
-Fixed possible type error if jenkins response contains null values
diff --git a/.changeset/violet-steaks-knock.md b/.changeset/violet-steaks-knock.md
new file mode 100644
index 0000000000..66139be422
--- /dev/null
+++ b/.changeset/violet-steaks-knock.md
@@ -0,0 +1,5 @@
+---
+'@backstage/test-utils': patch
+---
+
+Added missing `Routes` element to wrap the `Route` elements of the test app wrapping.
diff --git a/.changeset/warm-actors-attend.md b/.changeset/warm-actors-attend.md
deleted file mode 100644
index 9b5927dffe..0000000000
--- a/.changeset/warm-actors-attend.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/create-app': patch
----
-
-Tweaked `.eslintrc.js` files in the template to avoid having them apply during development. This change does not affect create apps.
diff --git a/.changeset/warm-mangos-compete.md b/.changeset/warm-mangos-compete.md
deleted file mode 100644
index 3215b36d22..0000000000
--- a/.changeset/warm-mangos-compete.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-permission-common': patch
----
-
-- Add more specific `Permission` types.
-- Add `createPermission` helper to infer the appropriate type for some permission input.
-- Add `isResourcePermission` helper to refine Permissions to ResourcePermissions.
diff --git a/.changeset/weak-buttons-play.md b/.changeset/weak-buttons-play.md
deleted file mode 100644
index 491b510f77..0000000000
--- a/.changeset/weak-buttons-play.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-gocd': patch
----
-
-Add DORA metrics insights to GoCD builds page
diff --git a/.changeset/wicked-beds-return.md b/.changeset/wicked-beds-return.md
deleted file mode 100644
index add952ba0a..0000000000
--- a/.changeset/wicked-beds-return.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-kubernetes': patch
----
-
-Fix division by zero in currentToDeclaredResourceToPerc when pod resources weren't set
diff --git a/.changeset/wicked-feet-clap.md b/.changeset/wicked-feet-clap.md
deleted file mode 100644
index e27f641820..0000000000
--- a/.changeset/wicked-feet-clap.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-common': patch
----
-
-Updated the visibility of database connection fields in config to be secret
diff --git a/.changeset/wild-emus-film.md b/.changeset/wild-emus-film.md
deleted file mode 100644
index abb77c5ddc..0000000000
--- a/.changeset/wild-emus-film.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-tech-insights': minor
----
-
-Add checksId option to EntityTechInsightsScorecardContent component
diff --git a/.changeset/wild-pigs-work.md b/.changeset/wild-pigs-work.md
new file mode 100644
index 0000000000..462b3b7233
--- /dev/null
+++ b/.changeset/wild-pigs-work.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-api-docs': patch
+---
+
+Updated the rendering of AsyncApi definitions to be able to resolve absolute HTTP $ref references.
diff --git a/.changeset/wise-emus-wait.md b/.changeset/wise-emus-wait.md
new file mode 100644
index 0000000000..6f0e5348c7
--- /dev/null
+++ b/.changeset/wise-emus-wait.md
@@ -0,0 +1,5 @@
+---
+'@backstage/test-utils': patch
+---
+
+The internal elements created as part of the `mountedRoutes` implementation are now hidden during rendering.
diff --git a/.changeset/witty-years-sniff.md b/.changeset/witty-years-sniff.md
deleted file mode 100644
index f8d8acf5c1..0000000000
--- a/.changeset/witty-years-sniff.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-stack-overflow': minor
----
-
-Add stack overflow plugin
diff --git a/.changeset/yellow-hats-remember.md b/.changeset/yellow-hats-remember.md
deleted file mode 100644
index 1a9064f94e..0000000000
--- a/.changeset/yellow-hats-remember.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-jenkins-backend': patch
----
-
-Make `resourceRef` required in `JenkinsApi` to match usage.
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index 202d7ecd14..0000000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-version: 2
-updates:
- - package-ecosystem: npm
- directory: '/'
- schedule:
- interval: daily
- time: '04:00'
- open-pull-requests-limit: 10
- labels:
- - dependencies
- - package-ecosystem: npm
- directory: '/microsite/'
- schedule:
- interval: daily
- time: '04:00'
- open-pull-requests-limit: 5
- labels:
- - dependencies
- - package-ecosystem: npm
- directory: '/storybook/'
- schedule:
- interval: daily
- time: '04:00'
- open-pull-requests-limit: 5
- labels:
- - dependencies
diff --git a/.github/renovate.json5 b/.github/renovate.json5
index aaf292f8cc..ff351a5e0f 100644
--- a/.github/renovate.json5
+++ b/.github/renovate.json5
@@ -2,4 +2,18 @@
labels: ['dependencies'],
extends: ['config:base', ':disableDependencyDashboard', ':gitSignOff'],
rangeStrategy: 'update-lockfile',
+ // @elastic/elasticsearch is ignored due to licensing issues. See #10992
+ ignoreDeps: ['@elastic/elasticsearch'],
+ packageRules: [
+ {
+ matchSourceUrlPrefixes: ['https://github.com/spotify/web-scripts'],
+ groupName: 'Spotify web-scripts monorepo packages',
+ rangeStrategy: 'replace',
+ },
+ {
+ matchSourceUrlPrefixes: ['https://github.com/microsoft/rushstack'],
+ groupName: 'API Extractor / Rush Stack monorepo packages',
+ rangeStrategy: 'replace',
+ },
+ ],
}
diff --git a/.github/styles/vocab.txt b/.github/vale/Vocab/Backstage/accept.txt
similarity index 98%
rename from .github/styles/vocab.txt
rename to .github/vale/Vocab/Backstage/accept.txt
index 72864d2c9f..caf27d4593 100644
--- a/.github/styles/vocab.txt
+++ b/.github/vale/Vocab/Backstage/accept.txt
@@ -8,9 +8,6 @@ airbrake
Anddddd
Apdex
api
-Api
-apis
-args
asciidoc
async
Atlassian
@@ -19,7 +16,6 @@ autoscaling
Autoscaling
autoselect
Avro
-aws
backported
backporting
Bigtable
@@ -38,7 +34,6 @@ changesets
Changesets
chanwit
Chanwit
-ci
CI/CD
classname
cli
@@ -108,6 +103,7 @@ Firekube
Firestore
Fiverr
Francesco
+gerrit
Gerrit
gitbeaker
github
@@ -128,7 +124,6 @@ hoc
horizontalpodautoscalers
Hostname
hotspots
-html
http
https
Iain
@@ -315,7 +310,6 @@ templaters
Templaters
theia
thumbsup
-toc
todo
tolerations
Tolerations
@@ -323,7 +317,7 @@ toolchain
toolsets
tooltip
tooltips
-touchpoints
+touchpoint
transpilation
transpiled
transpiler
@@ -340,7 +334,7 @@ unregistration
untracked
upsert
upvote
-url
+URIs
URLs
utils
validator
diff --git a/.github/vale/config.ini b/.github/vale/config.ini
new file mode 100644
index 0000000000..36acb2c058
--- /dev/null
+++ b/.github/vale/config.ini
@@ -0,0 +1,6 @@
+StylesPath = .
+Vocab = Backstage
+
+[*.md]
+BasedOnStyles = Vale
+Vale.Terms = NO
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 796df14ac7..31a315d044 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -155,6 +155,7 @@ jobs:
if: ${{ steps.yarn-lock.outcome == 'success' }}
run: yarn lerna -- run test --since origin/master -- --coverage --runInBand
env:
+ BACKSTAGE_NEXT_TESTS: 1
BACKSTAGE_TEST_DISABLE_DOCKER: 1
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] }}
@@ -166,6 +167,7 @@ jobs:
yarn lerna -- run test -- --coverage --runInBand
bash <(curl -s https://codecov.io/bash) -N $(git rev-parse FETCH_HEAD)
env:
+ BACKSTAGE_NEXT_TESTS: 1
BACKSTAGE_TEST_DISABLE_DOCKER: 1
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] }}
diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml
index d5d3659625..85668bdc3a 100644
--- a/.github/workflows/deploy_nightly.yml
+++ b/.github/workflows/deploy_nightly.yml
@@ -79,7 +79,7 @@ jobs:
- name: Discord notification
if: ${{ failure() }}
- uses: Ilshidur/action-discord@0.2.0
+ uses: Ilshidur/action-discord@0.3.2
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
with:
diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml
index fd9ed216be..bcb4016ab9 100644
--- a/.github/workflows/deploy_packages.yml
+++ b/.github/workflows/deploy_packages.yml
@@ -122,6 +122,7 @@ jobs:
bash <(curl -s https://codecov.io/bash) -f packages/core-components/coverage/* -F core-components
bash <(curl -s https://codecov.io/bash) -f packages/core-plugin-api/coverage/* -F core-plugin-api
env:
+ BACKSTAGE_NEXT_TESTS: 1
BACKSTAGE_TEST_DISABLE_DOCKER: 1
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] }}
@@ -129,7 +130,7 @@ jobs:
- name: Discord notification
if: ${{ failure() }}
- uses: Ilshidur/action-discord@0.2.0
+ uses: Ilshidur/action-discord@0.3.2
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
with:
@@ -220,7 +221,7 @@ jobs:
# Notify everyone about this great new release :D
- name: Discord notification
- uses: Ilshidur/action-discord@0.2.0
+ uses: Ilshidur/action-discord@0.3.2
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
TAG_NAME: ${{ steps.create_tag.outputs.tag_name }}
diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml
index 75c154792c..c1a4b9e1d0 100644
--- a/.github/workflows/sync_code-formatting.yml
+++ b/.github/workflows/sync_code-formatting.yml
@@ -43,7 +43,7 @@ jobs:
# End of yarn setup
- name: Run Prettier on ADOPTERS.md
- uses: creyD/prettier_action@v3.1
+ uses: creyD/prettier_action@v3.3
with:
# Modifies commit only if prettier autofixed the ADOPTERS.md
prettier_options: --config docs/prettier.config.js --write ADOPTERS.md
diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml
index 58d715c5a8..a6a544e6a5 100644
--- a/.github/workflows/sync_version-packages.yml
+++ b/.github/workflows/sync_version-packages.yml
@@ -11,11 +11,12 @@ jobs:
steps:
- uses: actions/checkout@v2
with:
+ fetch-depth: 0
token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
- name: Install Dependencies
run: yarn --frozen-lockfile
- name: Create Release Pull Request
- uses: changesets/action@master
+ uses: backstage/changesets-action@v2
with:
# Calls out to `changeset version`, but also runs prettier
version: yarn release
diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml
index 55c1c23587..ad2e92799f 100644
--- a/.github/workflows/verify_docs-quality.yml
+++ b/.github/workflows/verify_docs-quality.yml
@@ -12,10 +12,18 @@ jobs:
steps:
- uses: actions/checkout@v2
+
+ # Vale does not support file excludes, so we use the script to generate a list of files instead
+ # The action also does not allow args or a local config file to be passed in, so the files array
+ # also contains an "--config=.github/vale/config.ini" option
+ - name: generate vale args
+ id: generate
+ run: echo "::set-output name=args::$(node scripts/check-docs-quality.js --ci-args)"
+
- name: documentation quality check
- uses: errata-ai/vale-action@v1.4.0
- # Whitelist excluding ADOPTERS, CHANGELOG and OWNERS (no exclude flag exists)
+ uses: errata-ai/vale-action@v1.5.0
with:
- files: '[".changeset", ".github", "contrib", "docs", "microsite", "packages", "plugins", "CONTRIBUTING.md", "CODE_OF_CONDUCT.md", "GOVERNANCE.md", "README.md"]'
+ # This also contains --config=.github/vale/config.ini ... :/
+ files: '${{ steps.generate.outputs.args }}'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml
index 8dc621ebf7..becff56953 100644
--- a/.github/workflows/verify_e2e-windows.yml
+++ b/.github/workflows/verify_e2e-windows.yml
@@ -44,7 +44,7 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- name: Add msbuild to PATH
- uses: microsoft/setup-msbuild@v1.0.2
+ uses: microsoft/setup-msbuild@v1.0.3
- name: setup chrome
uses: browser-actions/setup-chrome@latest
- name: yarn install
diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml
index 6899b6ec2b..7156bec4f6 100644
--- a/.github/workflows/verify_windows.yml
+++ b/.github/workflows/verify_windows.yml
@@ -58,6 +58,7 @@ jobs:
- name: test
run: yarn lerna -- run test
env:
+ BACKSTAGE_NEXT_TESTS: 1
BACKSTAGE_TEST_DISABLE_DOCKER: 1
# credit: https://github.com/appleboy/discord-action/issues/3#issuecomment-731426861
diff --git a/ADOPTERS.md b/ADOPTERS.md
index 1a1c3686d4..845dd1b208 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -26,7 +26,7 @@ _If you're using Backstage in your organization, please try to add your company
| [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/) | [Matt Waldron](https://github.com/daftgopher) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. |
+| [Peloton](https://www.onepeloton.com/) | [Matt Waldron](https://github.com/daftgopher) | 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. |
@@ -34,7 +34,7 @@ _If you're using Backstage in your organization, please try to add your company
| [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 🌕🚀🧑🚀 |
+| [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. |
@@ -113,3 +113,12 @@ _If you're using Backstage in your organization, please try to add your company
| [SIX](https://www.six-group.com/) | [@jbadeau](https://github.com/jbadeau), [@tomassatka](https://github.com/tomassatka) | Internal DevOps portal hosting our software and dataset catalog, as well as custom plugins for observability, service virtualization, deployments, incident managment and quality metrics. |
| [Raiffeisen Bank International](https://www.rbinternational.com/) | [Daniel Baumgartner](https://github.com/dabarbi) | From developers for developers: software catalog, techdocs and heavy use of scaffolder to drive reuse on engineering level forward. Part of inner source initiative. Multi national setup coming. |
| [Spread Group](https://www.spreadgroup.com/) | [Luna Stadler](https://github.com/heyLu), [Iván González](https://github.com/ivangonzalezacuna) | Internal Developer Portal, an overview of all running software, architecture documentation and more; replacing and unifying a variety of internal tools. |
+| [RD Station](https://rdstation.com) | [Rogerio Angeliski](https://github.com/angeliski), [Paula Assis](https://github.com/paulassis), [Guilherme Eric](https://github.com/guilhermeeric), [Daniela Adamatti](https://github.com/daniadamatti), [Luana Negreiros](https://github.com/luananegreiros) | Developer portal, scaffolding, services catalog. We are looking to centralize automations and information for the whole engineering team . |
+| [Resuelve Tu Deuda](https://resuelve.mx) | [Iván Álvarez](https://github.com/ivanhoe), [Jorge Medina](https://github.com/jorgearma1982) | Internal developer portal, service catalog, tech docs, api doc |
+| [Pachama](https://pachama.com/) | [Aron Gates](https://github.com/agates4) | Internal Developer Portal, a catalog of all microservices, architecture documentation, and templates to generate developer resources. |
+| [SEEK](https://www.seek.com.au) | [Jahred Hope](https://github.com/jahredhope) | Developer portal for developer tooling and technical documentation. |
+| [Marks & Spencer](https://www.marksandspencer.com/) | [Kamal Cheriyath](https://github.com/kcheriyath) | Centralised discovery, adoption and devops automation hub for Engineering & Architecture. |
+| [McKesson](https://www.mckesson.com/) | [Agnel Antony](https://github.com/aantony2) | Internal Developer Platform for developer gated CI/CD templates, technical documentation, cloud automation service catalog, etc. |
+| [World Fuel Services](https://www.wfscorp.com/) | [Anirudh Kurapathi](https://github.com/anirudhkurapati), [Alex Kwon](https://github.com/alexkwon), [Lester Hernandez](https://github.com/lhernandez-wfscorp), [Avi Boru](https://github.com/aviboru), [Vardhan Annapureddy](https://github.com/harshaaws) | Internal Developer Portal, service catalog product, API's, Software Templates, tech docs and more. |
+| [leboncoin](https://www.leboncoin.fr/) | [Andy Ladjadj](https://github.com/aladjadj) | Centralize our multiple UI in a single portal. Simplify onbording, new features and harmonize how people search information. Core features (catalog,api,docs,scafolder) are good to start the adoption. status: internal beta. |
+| [Contentful](https://www.contentful.com) | [James Bourne](https://github.com/jamesmbourne) | Centralized documentation of service ownership, APIs, and documentation, and new service creation with a custom scaffolder - [full case study with Roadie](https://roadie.io/case-studies/maintaining-velocity-through-hypergrowth-contentful/). |
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e4aad09207..ca7af55d3b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -78,7 +78,7 @@ If you're contributing to the backend or CLI tooling, be mindful of cross-platfo
Also be sure to skim through our [ADRs](docs/architecture-decisions) to see if they cover what you're working on. In particular [ADR006: Avoid React.FC and React.SFC](docs/architecture-decisions/adr006-avoid-react-fc.md) is one to look out for.
-If there are any updates in `markdown` file please make sure to run `yarn run lint:docs`. Though it is checked on `lint-staged`. It is required to install [vale](https://docs.errata.ai/vale/install) `1.4.0` separately and make sure it is accessed by global command.
+If there are any updates in `markdown` file please make sure to run `yarn run lint:docs`. Though it is checked on `lint-staged`. It is required to install [vale](https://docs.errata.ai/vale/install) separately and make sure it is accessed by global command.
## Developer Certificate of Origin
diff --git a/STYLE.md b/STYLE.md
index 391b31ce50..b28c5da4fa 100644
--- a/STYLE.md
+++ b/STYLE.md
@@ -146,7 +146,7 @@ There are a few things to pay attention to, in order to make the documentation s
API documenter will not recognize arrow functions as functions, but rather as a constant that shows up in the list of exported variables. By declaring functions using the `function` keyword, they will show up in the list of functions. They will also get a much nicer documentation page for the individual function that shows information about parameters and return types.
-This also extends to React components, since API documenter doesn't have any special handling of those. By always defining exported React components using the `function` keyword, we make them show up among the list of functions in the API reference, where they are then easily discoverable through the `(props)` args (which you should be sure to include!).
+This also extends to React components, since API documenter doesn't have any special handling of those. By always defining exported React components using the `function` keyword, we make them show up among the list of functions in the API reference, where they are then easily discoverable through the `(props)` argument (which you should be sure to include!).

diff --git a/contrib/chart/backstage/Chart.lock b/contrib/chart/backstage/Chart.lock
index e390bf21ba..d18a48a655 100644
--- a/contrib/chart/backstage/Chart.lock
+++ b/contrib/chart/backstage/Chart.lock
@@ -1,6 +1,6 @@
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
- version: 9.4.1
-digest: sha256:f949ec0fe7d146610ce2ee78fbfb4e52d235883a797968b0a1e61aa88ada2786
-generated: "2020-09-25T08:59:54.255582519+02:00"
+ version: 9.8.12
+digest: sha256:549b9a0cdf7b2e0ad949ebad853a467bf320928970a946fb0ef7e13e9bdb7a10
+generated: "2022-04-21T07:02:48.301491565Z"
diff --git a/contrib/chart/backstage/Chart.yaml b/contrib/chart/backstage/Chart.yaml
index 21f7084415..9770ef665c 100644
--- a/contrib/chart/backstage/Chart.yaml
+++ b/contrib/chart/backstage/Chart.yaml
@@ -18,7 +18,7 @@ sources:
dependencies:
- name: postgresql
condition: postgresql.enabled
- version: 9.4.1
+ version: 9.8.12
repository: https://charts.bitnami.com/bitnami
maintainers:
diff --git a/contrib/docker/cookiecutter-with-jinja2-extensions/Dockerfile b/contrib/docker/cookiecutter-with-jinja2-extensions/Dockerfile
index 4f5f72bdf8..b854a00675 100644
--- a/contrib/docker/cookiecutter-with-jinja2-extensions/Dockerfile
+++ b/contrib/docker/cookiecutter-with-jinja2-extensions/Dockerfile
@@ -1,4 +1,4 @@
-FROM alpine:3.7
+FROM alpine:3.15
RUN apk add --update \
git \
diff --git a/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md b/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md
index 8a4d6fb273..9ec3f1ca64 100644
--- a/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md
+++ b/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md
@@ -64,8 +64,8 @@ if (process.env.HTTPS_PROXY) {
If your development environment is in the cloud (like with [AWS Cloud9](https://aws.amazon.com/cloud9/) or an instance of [Theia](https://theia-ide.org/)), you will need to update your configuration.
-You will probably need to make some changes in `app-config.yaml` (or another config file like `app-config.local.yaml` if you've created it, see the [configuration doc](https://backstage.io/docs/conf/#supplying-configuration)).
-The exact values will depend on your setup but for instance, if your public url is `https://your-public-url.com` and the port `3000` and `8080` are open:
+You will probably need to make some changes in `app-config.yaml` (or another config file like `app-config.local.yaml` if you've created it, see the [configuration doc](https://backstage.io/docs/conf/#supplying-configuration)).
+The exact values will depend on your setup but for instance, if your public URL is `https://your-public-url.com` and the port `3000` and `8080` are open:
```yaml
app:
diff --git a/cypress/.npmrc b/cypress/.npmrc
new file mode 100644
index 0000000000..c3c66347fd
--- /dev/null
+++ b/cypress/.npmrc
@@ -0,0 +1,2 @@
+registry=https://registry.npmjs.org/
+engine-strict=true
diff --git a/cypress/.yarnrc b/cypress/.yarnrc
new file mode 100644
index 0000000000..a2c82b2833
--- /dev/null
+++ b/cypress/.yarnrc
@@ -0,0 +1,5 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+registry "https://registry.npmjs.org/"
+network-timeout 300000
diff --git a/cypress/README.md b/cypress/README.md
index 2bb310e300..15338fe371 100644
--- a/cypress/README.md
+++ b/cypress/README.md
@@ -18,6 +18,17 @@ yarn install
yarn cypress run
```
+Note that the tests expect to run against a built application, so you'll want to
+run a Docker image and either create an `app-config.cypress.yaml` or pass the
+necessary environment variables:
+
+```sh
+yarn tsc
+yarn build
+yarn workspace example-backend build-image
+docker run -p 7007:7007 example-backend
+```
+
You can open up the `cypress` console by using `yarn cypress open`.
You can also run towards any Backstage installation by using the Cypress Environment Variable overrides.
diff --git a/cypress/fixtures/mkdocs.yml b/cypress/fixtures/mkdocs.yml
index 2362fab898..071d147509 100644
--- a/cypress/fixtures/mkdocs.yml
+++ b/cypress/fixtures/mkdocs.yml
@@ -1,5 +1,8 @@
site_name: e2e Fixture Documentation
site_description: Documentation used for end-to-end tests of TechDocs in Backstage.
+repo_url: https://github.com/backstage/backstage
+edit_uri: edit/master/cypress/fixtures/docs
+
nav:
- Home: index.md
- Sub-page 1: sub-page-one.md
diff --git a/cypress/yarn.lock b/cypress/yarn.lock
index f301e87d3a..bb9aaecb89 100644
--- a/cypress/yarn.lock
+++ b/cypress/yarn.lock
@@ -2,15 +2,10 @@
# yarn lockfile v1
-"@cypress/listr-verbose-renderer@^0.4.1":
- version "0.4.1"
- resolved "https://registry.npmjs.org/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a"
- integrity sha1-p3SS9LEdzHxEajSz4ochr9M8ZCo=
- dependencies:
- chalk "^1.1.3"
- cli-cursor "^1.0.2"
- date-fns "^1.27.2"
- figures "^1.7.0"
+"@colors/colors@1.5.0":
+ version "1.5.0"
+ resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
+ integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
"@cypress/request@^2.88.5":
version "2.88.10"
@@ -44,81 +39,74 @@
debug "^3.1.0"
lodash.once "^4.1.1"
-"@samverschueren/stream-to-observable@^0.3.0":
- version "0.3.1"
- resolved "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301"
- integrity sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==
- dependencies:
- any-observable "^0.3.0"
+"@types/node@*":
+ version "17.0.25"
+ resolved "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz#527051f3c2f77aa52e5dc74e45a3da5fb2301448"
+ integrity sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w==
"@types/node@^14.14.31":
- version "14.17.0"
- resolved "https://registry.npmjs.org/@types/node/-/node-14.17.0.tgz#3ba770047723b3eeb8dc9fca02cce8a7fb6378da"
- integrity sha512-w8VZUN/f7SSbvVReb9SWp6cJFevxb4/nkG65yLAya//98WgocKm5PLDAtSs5CtJJJM+kHmJjO/6mmYW4MHShZA==
+ version "14.18.13"
+ resolved "https://registry.npmjs.org/@types/node/-/node-14.18.13.tgz#6ad4d9db59e6b3faf98dcfe4ca9d2aec84443277"
+ integrity sha512-Z6/KzgyWOga3pJNS42A+zayjhPbf2zM3hegRQaOPnLOzEi86VV++6FLDWgR1LGrVCRufP/ph2daa3tEa5br1zA==
"@types/sinonjs__fake-timers@^6.0.2":
- version "6.0.2"
- resolved "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz#3a84cf5ec3249439015e14049bd3161419bf9eae"
- integrity sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==
+ version "6.0.4"
+ resolved "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.4.tgz#0ecc1b9259b76598ef01942f547904ce61a6a77d"
+ integrity sha512-IFQTJARgMUBF+xVd2b+hIgXWrZEjND3vJtRCvIelcFB5SIXfjV4bOHbHJ0eXKh+0COrBRc8MqteKAz/j88rE0A==
"@types/sizzle@^2.3.2":
- version "2.3.2"
- resolved "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47"
- integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==
+ version "2.3.3"
+ resolved "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef"
+ integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==
-ansi-escapes@^3.0.0:
- version "3.2.0"
- resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
- integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
-
-ansi-regex@^2.0.0:
- version "2.1.1"
- resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
- integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-
-ansi-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
- integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
-
-ansi-regex@^5.0.0:
- version "5.0.0"
- resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
- integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
-
-ansi-styles@^2.2.1:
- version "2.2.1"
- resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
- integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
-
-ansi-styles@^3.2.1:
- version "3.2.1"
- resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
- integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+"@types/yauzl@^2.9.1":
+ version "2.10.0"
+ resolved "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599"
+ integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==
dependencies:
- color-convert "^1.9.0"
+ "@types/node" "*"
-ansi-styles@^4.1.0:
+aggregate-error@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
+ integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
+ dependencies:
+ clean-stack "^2.0.0"
+ indent-string "^4.0.0"
+
+ansi-colors@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
+ integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
+
+ansi-escapes@^4.3.0:
+ version "4.3.2"
+ resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
+ integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
+ dependencies:
+ type-fest "^0.21.3"
+
+ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
-any-observable@^0.3.0:
- version "0.3.0"
- resolved "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b"
- integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==
-
arch@^2.2.0:
version "2.2.0"
resolved "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==
asn1@~0.2.3:
- version "0.2.4"
- resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
- integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
+ version "0.2.6"
+ resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d"
+ integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==
dependencies:
safer-buffer "~2.1.0"
@@ -127,10 +115,15 @@ assert-plus@1.0.0, assert-plus@^1.0.0:
resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
+astral-regex@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
+ integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
+
async@^3.2.0:
- version "3.2.0"
- resolved "https://registry.npmjs.org/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
- integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
+ version "3.2.3"
+ resolved "https://registry.npmjs.org/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9"
+ integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==
asynckit@^0.4.0:
version "0.4.0"
@@ -153,9 +146,9 @@ aws4@^1.8.0:
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
balanced-match@^1.0.0:
- version "1.0.0"
- resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
- integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
@@ -187,11 +180,6 @@ buffer-crc32@~0.2.3:
resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
-buffer-from@^1.0.0:
- version "1.1.1"
- resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
- integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-
cachedir@^2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8"
@@ -202,30 +190,10 @@ caseless@~0.12.0:
resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-chalk@^1.0.0, chalk@^1.1.3:
- version "1.1.3"
- resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
- integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
- dependencies:
- ansi-styles "^2.2.1"
- escape-string-regexp "^1.0.2"
- has-ansi "^2.0.0"
- strip-ansi "^3.0.0"
- supports-color "^2.0.0"
-
-chalk@^2.4.1:
- version "2.4.2"
- resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
- integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
-chalk@^4.0.0, chalk@^4.1.0:
- version "4.1.0"
- resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
- integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
+chalk@^4.1.0:
+ version "4.1.2"
+ resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
@@ -235,54 +203,39 @@ check-more-types@^2.24.0:
resolved "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600"
integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=
-ci-info@^3.1.1:
- version "3.1.1"
- resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.1.1.tgz#9a32fcefdf7bcdb6f0a7e1c0f8098ec57897b80a"
- integrity sha512-kdRWLBIJwdsYJWYJFtAFFYxybguqeF91qpZaggjG5Nf8QKdizFG2hjqvaTXbxFIcYbSaD74KpAXv6BSm17DHEQ==
+ci-info@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2"
+ integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==
-cli-cursor@^1.0.2:
- version "1.0.2"
- resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
- integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=
- dependencies:
- restore-cursor "^1.0.1"
+clean-stack@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
+ integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
-cli-cursor@^2.0.0, cli-cursor@^2.1.0:
- version "2.1.0"
- resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
- integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
+cli-cursor@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
+ integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
dependencies:
- restore-cursor "^2.0.0"
+ restore-cursor "^3.1.0"
cli-table3@~0.6.0:
- version "0.6.0"
- resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee"
- integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==
+ version "0.6.2"
+ resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz#aaf5df9d8b5bf12634dc8b3040806a0c07120d2a"
+ integrity sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==
dependencies:
- object-assign "^4.1.0"
string-width "^4.2.0"
optionalDependencies:
- colors "^1.1.2"
+ "@colors/colors" "1.5.0"
-cli-truncate@^0.2.1:
- version "0.2.1"
- resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574"
- integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=
+cli-truncate@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"
+ integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==
dependencies:
- slice-ansi "0.0.4"
- string-width "^1.0.1"
-
-code-point-at@^1.0.0:
- version "1.1.0"
- resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
- integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-
-color-convert@^1.9.0:
- version "1.9.3"
- resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
- integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
- dependencies:
- color-name "1.1.3"
+ slice-ansi "^3.0.0"
+ string-width "^4.2.0"
color-convert@^2.0.1:
version "2.0.1"
@@ -291,20 +244,15 @@ color-convert@^2.0.1:
dependencies:
color-name "~1.1.4"
-color-name@1.1.3:
- version "1.1.3"
- resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
- integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-colors@^1.1.2:
- version "1.4.0"
- resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
- integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
+colorette@^2.0.16:
+ version "2.0.16"
+ resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da"
+ integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
@@ -319,26 +267,16 @@ commander@^5.1.0:
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
common-tags@^1.8.0:
- version "1.8.0"
- resolved "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
- integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==
+ version "1.8.2"
+ resolved "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
+ integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-concat-stream@^1.6.2:
- version "1.6.2"
- resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
- integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
- dependencies:
- buffer-from "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^2.2.2"
- typedarray "^0.0.6"
-
-core-util-is@1.0.2, core-util-is@~1.0.0:
+core-util-is@1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
@@ -353,11 +291,10 @@ cross-spawn@^7.0.0:
which "^2.0.1"
cypress@^7.3.0:
- version "7.3.0"
- resolved "https://registry.npmjs.org/cypress/-/cypress-7.3.0.tgz#17345b8d18681c120f033e7d8fd0f0271e9d0d51"
- integrity sha512-aseRCH1tRVCrM6oEfja6fR/bo5l6e4SkHRRSATh27UeN4f/ANC8U7tGIulmrISJVy9xuOkOdbYKbUb2MNM+nrw==
+ version "7.7.0"
+ resolved "https://registry.npmjs.org/cypress/-/cypress-7.7.0.tgz#0839ae28e5520536f9667d6c9ae81496b3836e64"
+ integrity sha512-uYBYXNoI5ym0UxROwhQXWTi8JbUEjpC6l/bzoGZNxoKGsLrC1SDPgIDJMgLX/MeEdPL0UInXLDUWN/rSyZUCjQ==
dependencies:
- "@cypress/listr-verbose-renderer" "^0.4.1"
"@cypress/request" "^2.88.5"
"@cypress/xvfb" "^1.2.4"
"@types/node" "^14.14.31"
@@ -369,21 +306,24 @@ cypress@^7.3.0:
cachedir "^2.3.0"
chalk "^4.1.0"
check-more-types "^2.24.0"
+ cli-cursor "^3.1.0"
cli-table3 "~0.6.0"
commander "^5.1.0"
common-tags "^1.8.0"
dayjs "^1.10.4"
- debug "4.3.2"
+ debug "^4.3.2"
+ enquirer "^2.3.6"
eventemitter2 "^6.4.3"
execa "4.1.0"
executable "^4.1.1"
- extract-zip "^1.7.0"
+ extract-zip "2.0.1"
+ figures "^3.2.0"
fs-extra "^9.1.0"
getos "^3.2.1"
is-ci "^3.0.0"
is-installed-globally "~0.4.0"
lazy-ass "^1.6.0"
- listr "^0.14.3"
+ listr2 "^3.8.3"
lodash "^4.17.21"
log-symbols "^4.0.0"
minimist "^1.2.5"
@@ -404,29 +344,10 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
-date-fns@^1.27.2:
- version "1.30.1"
- resolved "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
- integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
-
dayjs@^1.10.4:
- version "1.10.4"
- resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2"
- integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw==
-
-debug@4.3.2:
- version "4.3.2"
- resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
- integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
- dependencies:
- ms "2.1.2"
-
-debug@^2.6.9:
- version "2.6.9"
- resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
- integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
- dependencies:
- ms "2.0.0"
+ version "1.11.1"
+ resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.1.tgz#90b33a3dda3417258d48ad2771b415def6545eb0"
+ integrity sha512-ER7EjqVAMkRRsxNCC5YqJ9d9VQYuWdGt7aiH2qA5R5wt8ZmWaP2dLUSIK6y/kVzLMlmh1Tvu5xUf4M/wdGJ5KA==
debug@^3.1.0:
version "3.2.7"
@@ -435,6 +356,13 @@ debug@^3.1.0:
dependencies:
ms "^2.1.1"
+debug@^4.1.1, debug@^4.3.2:
+ version "4.3.4"
+ resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -448,11 +376,6 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
-elegant-spinner@^1.0.1:
- version "1.0.1"
- resolved "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
- integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=
-
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
@@ -465,15 +388,22 @@ end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
-escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+enquirer@^2.3.6:
+ version "2.3.6"
+ resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
+ integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
+ dependencies:
+ ansi-colors "^4.1.1"
+
+escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
eventemitter2@^6.4.3:
- version "6.4.4"
- resolved "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.4.tgz#aa96e8275c4dbeb017a5d0e03780c65612a1202b"
- integrity sha512-HLU3NDY6wARrLCEwyGKRBvuWYyvW6mHYv72SJJAH3iJN3a6eVUvkjFkcxah1bcTgGVBBrFdIopBJPhCQFMLyXw==
+ version "6.4.5"
+ resolved "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz#97380f758ae24ac15df8353e0cc27f8b95644655"
+ integrity sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==
execa@4.1.0:
version "4.1.0"
@@ -497,25 +427,21 @@ executable@^4.1.1:
dependencies:
pify "^2.2.0"
-exit-hook@^1.0.0:
- version "1.1.1"
- resolved "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
- integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=
-
extend@~3.0.2:
version "3.0.2"
resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-extract-zip@^1.7.0:
- version "1.7.0"
- resolved "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927"
- integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==
+extract-zip@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
+ integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
dependencies:
- concat-stream "^1.6.2"
- debug "^2.6.9"
- mkdirp "^0.5.4"
+ debug "^4.1.1"
+ get-stream "^5.1.0"
yauzl "^2.10.0"
+ optionalDependencies:
+ "@types/yauzl" "^2.9.1"
extsprintf@1.3.0:
version "1.3.0"
@@ -523,9 +449,9 @@ extsprintf@1.3.0:
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
extsprintf@^1.2.0:
- version "1.4.0"
- resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
- integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
+ version "1.4.1"
+ resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
+ integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
fd-slicer@~1.1.0:
version "1.1.0"
@@ -534,18 +460,10 @@ fd-slicer@~1.1.0:
dependencies:
pend "~1.2.0"
-figures@^1.7.0:
- version "1.7.0"
- resolved "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
- integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=
- dependencies:
- escape-string-regexp "^1.0.5"
- object-assign "^4.1.0"
-
-figures@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
- integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
+figures@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
+ integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
dependencies:
escape-string-regexp "^1.0.5"
@@ -578,7 +496,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-get-stream@^5.0.0:
+get-stream@^5.0.0, get-stream@^5.1.0:
version "5.2.0"
resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
@@ -600,9 +518,9 @@ getpass@^0.1.1:
assert-plus "^1.0.0"
glob@^7.1.3:
- version "7.1.6"
- resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
- integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+ version "7.2.0"
+ resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
+ integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
@@ -619,21 +537,9 @@ global-dirs@^3.0.0:
ini "2.0.0"
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
- version "4.2.5"
- resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.5.tgz#bc18864a6c9fc7b303f2e2abdb9155ad178fbe29"
- integrity sha512-kBBSQbz2K0Nyn+31j/w36fUfxkBW9/gfwRWdUY1ULReH3iokVJgddZAFcD1D0xlgTmFxJCbUkUclAlc6/IDJkw==
-
-has-ansi@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
- integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
- dependencies:
- ansi-regex "^2.0.0"
-
-has-flag@^3.0.0:
- version "3.0.0"
- resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
- integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+ version "4.2.10"
+ resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
+ integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
has-flag@^4.0.0:
version "4.0.0"
@@ -654,10 +560,10 @@ human-signals@^1.1.1:
resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
-indent-string@^3.0.0:
- version "3.2.0"
- resolved "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
- integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
+indent-string@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
inflight@^1.0.4:
version "1.0.6"
@@ -667,7 +573,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@^2.0.3, inherits@~2.0.3:
+inherits@2:
version "2.0.4"
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -678,23 +584,11 @@ ini@2.0.0:
integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
is-ci@^3.0.0:
- version "3.0.0"
- resolved "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz#c7e7be3c9d8eef7d0fa144390bd1e4b88dc4c994"
- integrity sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ==
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867"
+ integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==
dependencies:
- ci-info "^3.1.1"
-
-is-fullwidth-code-point@^1.0.0:
- version "1.0.0"
- resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
- integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
- dependencies:
- number-is-nan "^1.0.0"
-
-is-fullwidth-code-point@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
- integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
+ ci-info "^3.2.0"
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
@@ -709,42 +603,25 @@ is-installed-globally@~0.4.0:
global-dirs "^3.0.0"
is-path-inside "^3.0.2"
-is-observable@^1.1.0:
- version "1.1.0"
- resolved "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e"
- integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==
- dependencies:
- symbol-observable "^1.1.0"
-
is-path-inside@^3.0.2:
version "3.0.3"
resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
-is-promise@^2.1.0:
- version "2.2.2"
- resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
- integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
-
-is-stream@^1.1.0:
- version "1.1.0"
- resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
- integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
-
is-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
- integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
+ integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-isarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
- integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
+is-unicode-supported@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
+ integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
isexe@^2.0.0:
version "2.0.0"
@@ -795,49 +672,19 @@ lazy-ass@^1.6.0:
resolved "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513"
integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM=
-listr-silent-renderer@^1.1.1:
- version "1.1.1"
- resolved "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e"
- integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=
-
-listr-update-renderer@^0.5.0:
- version "0.5.0"
- resolved "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2"
- integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==
+listr2@^3.8.3:
+ version "3.14.0"
+ resolved "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e"
+ integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==
dependencies:
- chalk "^1.1.3"
- cli-truncate "^0.2.1"
- elegant-spinner "^1.0.1"
- figures "^1.7.0"
- indent-string "^3.0.0"
- log-symbols "^1.0.2"
- log-update "^2.3.0"
- strip-ansi "^3.0.1"
-
-listr-verbose-renderer@^0.5.0:
- version "0.5.0"
- resolved "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db"
- integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==
- dependencies:
- chalk "^2.4.1"
- cli-cursor "^2.1.0"
- date-fns "^1.27.2"
- figures "^2.0.0"
-
-listr@^0.14.3:
- version "0.14.3"
- resolved "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586"
- integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==
- dependencies:
- "@samverschueren/stream-to-observable" "^0.3.0"
- is-observable "^1.1.0"
- is-promise "^2.1.0"
- is-stream "^1.1.0"
- listr-silent-renderer "^1.1.1"
- listr-update-renderer "^0.5.0"
- listr-verbose-renderer "^0.5.0"
- p-map "^2.0.0"
- rxjs "^6.3.3"
+ cli-truncate "^2.1.0"
+ colorette "^2.0.16"
+ log-update "^4.0.0"
+ p-map "^4.0.0"
+ rfdc "^1.3.0"
+ rxjs "^7.5.1"
+ through "^2.3.8"
+ wrap-ansi "^7.0.0"
lodash.once@^4.1.1:
version "4.1.1"
@@ -849,50 +696,40 @@ lodash@^4.17.21:
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-log-symbols@^1.0.2:
- version "1.0.2"
- resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
- integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=
- dependencies:
- chalk "^1.0.0"
-
log-symbols@^4.0.0:
- version "4.0.0"
- resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920"
- integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
+ integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
dependencies:
- chalk "^4.0.0"
+ chalk "^4.1.0"
+ is-unicode-supported "^0.1.0"
-log-update@^2.3.0:
- version "2.3.0"
- resolved "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708"
- integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg=
+log-update@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1"
+ integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==
dependencies:
- ansi-escapes "^3.0.0"
- cli-cursor "^2.0.0"
- wrap-ansi "^3.0.1"
+ ansi-escapes "^4.3.0"
+ cli-cursor "^3.1.0"
+ slice-ansi "^4.0.0"
+ wrap-ansi "^6.2.0"
merge-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
-mime-db@1.45.0:
- version "1.45.0"
- resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea"
- integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.12, mime-types@~2.1.19:
- version "2.1.28"
- resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd"
- integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==
+ version "2.1.35"
+ resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies:
- mime-db "1.45.0"
-
-mimic-fn@^1.0.0:
- version "1.2.0"
- resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
- integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+ mime-db "1.52.0"
mimic-fn@^2.1.0:
version "2.1.0"
@@ -900,9 +737,9 @@ mimic-fn@^2.1.0:
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
minimatch@^3.0.4:
- version "3.0.4"
- resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
- integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+ version "3.1.2"
+ resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies:
brace-expansion "^1.1.7"
@@ -911,18 +748,6 @@ minimist@^1.2.5:
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
-mkdirp@^0.5.4:
- version "0.5.5"
- resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
- integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
- dependencies:
- minimist "^1.2.5"
-
-ms@2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
- integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
-
ms@2.1.2:
version "2.1.2"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
@@ -940,16 +765,6 @@ npm-run-path@^4.0.0:
dependencies:
path-key "^3.0.0"
-number-is-nan@^1.0.0:
- version "1.0.1"
- resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
- integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-
-object-assign@^4.1.0:
- version "4.1.1"
- resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
- integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
-
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -957,18 +772,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
-onetime@^1.0.0:
- version "1.1.0"
- resolved "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
- integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=
-
-onetime@^2.0.0:
- version "2.0.1"
- resolved "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
- integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
- dependencies:
- mimic-fn "^1.0.0"
-
onetime@^5.1.0:
version "5.1.2"
resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
@@ -981,10 +784,12 @@ ospath@^1.2.2:
resolved "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b"
integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=
-p-map@^2.0.0:
- version "2.1.0"
- resolved "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
- integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
+p-map@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
+ integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
+ dependencies:
+ aggregate-error "^3.0.0"
path-is-absolute@^1.0.0:
version "1.0.1"
@@ -1016,11 +821,6 @@ pretty-bytes@^5.6.0:
resolved "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
-process-nextick-args@~2.0.0:
- version "2.0.1"
- resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
- integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-
psl@^1.1.28:
version "1.8.0"
resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
@@ -1045,9 +845,9 @@ punycode@^2.1.1:
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qs@~6.5.2:
- version "6.5.2"
- resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
- integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
+ version "6.5.3"
+ resolved "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
+ integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
querystring@0.2.0:
version "0.2.0"
@@ -1055,22 +855,9 @@ querystring@0.2.0:
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
ramda@~0.27.1:
- version "0.27.1"
- resolved "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9"
- integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==
-
-readable-stream@^2.2.2:
- version "2.3.7"
- resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
- integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.3"
- isarray "~1.0.0"
- process-nextick-args "~2.0.0"
- safe-buffer "~5.1.1"
- string_decoder "~1.1.1"
- util-deprecate "~1.0.1"
+ version "0.27.2"
+ resolved "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1"
+ integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==
request-progress@^3.0.0:
version "3.0.0"
@@ -1079,22 +866,19 @@ request-progress@^3.0.0:
dependencies:
throttleit "^1.0.0"
-restore-cursor@^1.0.1:
- version "1.0.1"
- resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
- integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=
+restore-cursor@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
+ integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
dependencies:
- exit-hook "^1.0.0"
- onetime "^1.0.0"
-
-restore-cursor@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
- integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
- dependencies:
- onetime "^2.0.0"
+ onetime "^5.1.0"
signal-exit "^3.0.2"
+rfdc@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
+ integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
+
rimraf@^3.0.0:
version "3.0.2"
resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@@ -1102,23 +886,18 @@ rimraf@^3.0.0:
dependencies:
glob "^7.1.3"
-rxjs@^6.3.3:
- version "6.6.3"
- resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552"
- integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==
+rxjs@^7.5.1:
+ version "7.5.5"
+ resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f"
+ integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==
dependencies:
- tslib "^1.9.0"
+ tslib "^2.1.0"
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
version "5.2.1"
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
-safe-buffer@~5.1.0, safe-buffer@~5.1.1:
- version "5.1.2"
- resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
- integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@@ -1137,19 +916,32 @@ shebang-regex@^3.0.0:
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
signal-exit@^3.0.2:
- version "3.0.3"
- resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
- integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
+ version "3.0.7"
+ resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
+ integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
-slice-ansi@0.0.4:
- version "0.0.4"
- resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
- integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=
+slice-ansi@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787"
+ integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==
+ dependencies:
+ ansi-styles "^4.0.0"
+ astral-regex "^2.0.0"
+ is-fullwidth-code-point "^3.0.0"
+
+slice-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
+ integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
+ dependencies:
+ ansi-styles "^4.0.0"
+ astral-regex "^2.0.0"
+ is-fullwidth-code-point "^3.0.0"
sshpk@^1.14.1:
- version "1.16.1"
- resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
- integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
+ version "1.17.0"
+ resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5"
+ integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
@@ -1161,77 +953,27 @@ sshpk@^1.14.1:
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
-string-width@^1.0.1:
- version "1.0.2"
- resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
- integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
- dependencies:
- code-point-at "^1.0.0"
- is-fullwidth-code-point "^1.0.0"
- strip-ansi "^3.0.0"
-
-string-width@^2.1.1:
- version "2.1.1"
- resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
- integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
- dependencies:
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^4.0.0"
-
-string-width@^4.2.0:
- version "4.2.0"
- resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
- integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
+string-width@^4.1.0, string-width@^4.2.0:
+ version "4.2.3"
+ resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.0"
+ strip-ansi "^6.0.1"
-string_decoder@~1.1.1:
- version "1.1.1"
- resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
- integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
- safe-buffer "~5.1.0"
-
-strip-ansi@^3.0.0, strip-ansi@^3.0.1:
- version "3.0.1"
- resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
- integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
- dependencies:
- ansi-regex "^2.0.0"
-
-strip-ansi@^4.0.0:
- version "4.0.0"
- resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
- integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
- dependencies:
- ansi-regex "^3.0.0"
-
-strip-ansi@^6.0.0:
- version "6.0.0"
- resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
- integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
- dependencies:
- ansi-regex "^5.0.0"
+ ansi-regex "^5.0.1"
strip-final-newline@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
-supports-color@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
- integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-
-supports-color@^5.3.0:
- version "5.5.0"
- resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
- integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
- dependencies:
- has-flag "^3.0.0"
-
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
@@ -1246,16 +988,16 @@ supports-color@^8.1.1:
dependencies:
has-flag "^4.0.0"
-symbol-observable@^1.1.0:
- version "1.2.0"
- resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
- integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
-
throttleit@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"
integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=
+through@^2.3.8:
+ version "2.3.8"
+ resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+ integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
+
tmp@~0.2.1:
version "0.2.1"
resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
@@ -1271,10 +1013,10 @@ tough-cookie@~2.5.0:
psl "^1.1.28"
punycode "^2.1.1"
-tslib@^1.9.0:
- version "1.14.1"
- resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
- integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+tslib@^2.1.0:
+ version "2.4.0"
+ resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
+ integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
tunnel-agent@^0.6.0:
version "0.6.0"
@@ -1288,10 +1030,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-typedarray@^0.0.6:
- version "0.0.6"
- resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
- integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
+type-fest@^0.21.3:
+ version "0.21.3"
+ resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
+ integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
typescript@^4.1.3:
version "4.1.3"
@@ -1316,11 +1058,6 @@ url@^0.11.0:
punycode "1.3.2"
querystring "0.2.0"
-util-deprecate@~1.0.1:
- version "1.0.2"
- resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-
uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
@@ -1342,13 +1079,23 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
-wrap-ansi@^3.0.1:
- version "3.0.1"
- resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba"
- integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=
+wrap-ansi@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
+ integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
dependencies:
- string-width "^2.1.1"
- strip-ansi "^4.0.0"
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
wrappy@1:
version "1.0.2"
diff --git a/docs/assets/techdocs/addon-locations.png b/docs/assets/techdocs/addon-locations.png
new file mode 100644
index 0000000000..e535fe61aa
Binary files /dev/null and b/docs/assets/techdocs/addon-locations.png differ
diff --git a/docs/auth/add-auth-provider.md b/docs/auth/add-auth-provider.md
index 07d6869fe3..282088fef9 100644
--- a/docs/auth/add-auth-provider.md
+++ b/docs/auth/add-auth-provider.md
@@ -74,7 +74,7 @@ export class ProviderAAuthProvider implements OAuthProviderHandlers {
clientID: options.clientId,
clientSecret: options.clientSecret,
callbackURL: options.callbackUrl,
- passReqToCallback: false as true,
+ passReqToCallback: false,
response_type: 'code',
/// ... etc
}
@@ -230,7 +230,7 @@ name.
### Test the new provider
You can `curl -i localhost:7007/api/auth/providerA/start` and which should
-provide a `302` redirect with a `Location` header. Paste the url from that
+provide a `302` redirect with a `Location` header. Paste the URL from that
header into a web browser and you should be able to trigger the authorization
flow.
diff --git a/docs/auth/github/provider.md b/docs/auth/github/provider.md
index 14b99bfea5..a8c6020cae 100644
--- a/docs/auth/github/provider.md
+++ b/docs/auth/github/provider.md
@@ -50,7 +50,7 @@ The GitHub provider is a structure with three configuration keys:
- `clientSecret`: The client secret tied to the generated client ID.
- `enterpriseInstanceUrl` (optional): The base URL for a GitHub Enterprise
instance, e.g. `https://ghe..com`. Only needed for GitHub Enterprise.
-- `callbackUrl` (optional): The callback url that GitHub will use when
+- `callbackUrl` (optional): The callback URL that GitHub will use when
initiating an OAuth flow, e.g.
`https://your-intermediate-service.com/handler`. Only needed if Backstage is
not the immediate receiver (e.g. one OAuth app for many backstage instances).
diff --git a/docs/auth/identity-resolver.md b/docs/auth/identity-resolver.md
index fea82894c8..686c9a9dab 100644
--- a/docs/auth/identity-resolver.md
+++ b/docs/auth/identity-resolver.md
@@ -1,77 +1,123 @@
---
id: identity-resolver
-title: Identity resolver
-description: Identity resolvers of Backstage users after they sign-in
+title: Sign-in Identities and Resolvers
+description: An introduction to Backstage user identities and sign-in resolvers
---
-This guide explains how the identity of a Backstage user is stored inside their
-Backstage Identity Token and how you can customize the Sign-In resolvers to
-include identity and group membership information of the user from other
-external systems. This ultimately helps with determining the ownership of a
-Backstage entity by a user. The ideas here were originally proposed in the RFC
-[#4089](https://github.com/backstage/backstage/issues/4089).
+By default, every Backstage auth provider is configured only for the use-case of
+access delegation. This enables Backstage to request resources and actions from
+external systems on behalf of the user, for example re-triggering a build in CI.
-When a user signs in to Backstage, inside the `claims` field of their Backstage
-Token (which are standard JWT tokens) a special `ent` claim is set. `ent`
-contains a list of
-[entity references](../features/software-catalog/references.md), each of which
-denotes an identity or a membership that is relevant to the user. There is no
-guarantee that these correspond to actual existing catalog entities.
+If you want to use an auth provider to sign in users, you need to explicitly configure
+it have sign-in enabled and also tell it how the external identities should
+be mapped to user identities within Backstage.
-Let's take an example sign-in resolver for the Google auth provider and explore
-how the `ent` field inside `claims` can be set.
+## Backstage User Identity
-Inside your `packages/backend/src/plugins/auth.ts` file, you can provide custom
-sign-in resolvers and set them for any of the Authentication providers inside
-`providerFactories` of the `createRouter` imported from the
-`@backstage/plugin-auth-backend` plugin.
+A user identity within Backstage is built up from two pieces of information, a
+user [entity reference](../features/software-catalog/references.md), and a
+set of ownership entity references.
+When a user signs in, a Backstage token is generated with these two pieces of information,
+which is then used to identity the user within the Backstage ecosystem.
+
+The user entity reference should uniquely identify the logged in user in Backstage.
+It is encouraged that a matching user entity also exists within the Software Catalog,
+but it is not required. If the user entity exists in the catalog it can be used to
+store additional data about the user. There may even be some plugins that require
+this for them to be able to function.
+
+The ownership references are also entity references, and it is likewise
+encouraged that these entities exist within the catalog, but it is not a requirement.
+The ownership references are used to determine what the user owns, as a set
+of references that the user claims ownership though. For example, a user
+Jane (`user:default/jane`) might have the ownership references `user:default/jane`,
+`group:default/team-a`, and `group:default/admins`. Given these ownership claims,
+any entity that is marked as owned by either of `user:jane`, `team-a`, or `admins` would
+be considered owned by Jane.
+
+The ownership claims often contain the user entity reference itself, but it is not
+required. It is also worth noting that the ownership claims can also be used to
+resolve other relations similar to ownership, such as a claim for a `maintainer` or
+`operator` status.
+
+The Backstage token that encapsulates the user identity is a JWT. The user entity
+reference is stored in the `sub` claim of the payload, while the ownership references
+are stored in a custom `ent` claim. Both the user and ownership references should
+always be full entity references, as opposed to shorthands like just `jane` or `user:jane`.
+
+## Sign-in Resolvers
+
+Signing in a user into Backstage requires a mapping of the user identity from the
+third-party auth provider to a Backstage user identity. This mapping can vary quite
+a lot between different organizations and auth providers, and because of that there's
+no default way to resolve user identities. The auth provider that one wants to use
+for sign-in must instead be configured with a sign-in resolver, which is a function
+that is responsible for creating this user identity mapping.
+
+The input to the sign-in resolver function is the result of a successful log in with
+the given auth provider, as well as a context object that contains various helpers
+for looking up users and issuing tokens. There are also a number of built-in sign-in
+resolvers that can be used, which are covered a bit further down.
+
+### Custom Resolver Example
+
+Let's look at an example of a custom sign-in resolver for the Google auth provider.
+This all typically happens within your `packages/backend/src/plugins/auth.ts` file,
+which is responsible for setting up and configuring the auth backend plugin.
+
+You provide the resolver as part of the options you pass when creating a new auth
+provider factory. This means you need to replace the default Google provider with
+one that you create. Be sure to also include the existing `defaultAuthProviderFactories`
+if you want to keep all of the built-in auth providers installed.
+
+Now let's look at the example, with the rest of the commentary being made with in
+the code comments:
```ts
-import { DEFAULT_NAMESPACE, stringifyEntityRef } from '@backstage/catalog-model';
+import {
+ createRouter,
+ providers,
+ defaultAuthProviderFactories,
+} from '@backstage/plugin-auth-backend';
+import { Router } from 'express';
+import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise {
return await createRouter({
- ...
+ ...env,
providerFactories: {
- google: createGoogleProvider({
+ ...defaultAuthProviderFactories,
+ google: providers.google.create({
signIn: {
- resolver: async ({ profile: { email } }, ctx) => {
- // Call a custom validator function that checks that the email is
- // valid and on our own company's domain, and throws an Error if it
- // isn't.
- // TODO: Implement this function
- validateEmail(email);
+ resolver: async (info, ctx) => {
+ const {
+ profile: { email },
+ } = info;
+ // Profiles are not always guaranteed to to have an email address.
+ // You can also find more provider-specific information in `info.result`.
+ // It typically contains a `fullProfile` object as well as ID and/or access
+ // tokens that you can use for additional lookups.
+ if (!email) {
+ throw new Error('User profile contained no email');
+ }
- // List of entity references that denote the identity and
- // membership of the user
- const ent: string[] = [];
+ // You can add your own custom validation logic here.
+ // Logins can be prevented by throwing an error like the one above.
+ myEmailValidator(email);
- // Let's use the username in the email ID as the user's default
- // unique identifier inside Backstage.
- const [id] = email.split('@');
- const userEntityRef = stringifyEntityRef({
- kind: 'User',
- namespace: DEFAULT_NAMESPACE,
- name: id,
+ // This example resolver simply uses the local part of the email as the name.
+ const [name] = email.split('@');
+
+ // This helper function handles sign-in by looking up a user in the catalog.
+ // The lookup can be done either by reference, annotations, or custom filters.
+ //
+ // The helper also issues a token for the user, using the standard group
+ // membership logic to determine the ownership references of the user.
+ return ctx.signInWithCatalogUser({
+ entityRef: { name },
});
- ent.push(userEntityRef);
-
- // Let's call the internal LDAP provider to get a list of groups
- // that the user belongs to, and add those to the list as well
- const ldapGroups = await getLdapGroups(email);
- ldapGroups.forEach(group => ent.push(stringifyEntityRef({
- kind: 'Group',
- namespace: DEFAULT_NAMESPACE,
- name: group,
- })));
-
- // Issue the token containing the entity claims
- const token = await ctx.tokenIssuer.issueToken({
- claims: { sub: userEntityRef, ent },
- });
- return { id, token };
},
},
}),
@@ -80,97 +126,118 @@ export default async function createPlugin(
}
```
-As you can see, the generated Backstage Token now contains all the claims about
-the identity and membership of the user. Once the sign-in process is complete,
-and we need to find out if a user owns an Entity in the Software Catalog, these
-`ent` claims can be used to determine the ownership.
+### Built-in Resolvers
-According to the RFC, the definition of the ownership of an entity E, for a user
-U, is as follows:
-
-- Get all the `ownedBy` relations of E, and call them O
-- Get all the claims of the user U and call them C
-- If any C matches any O, return `true`
-- Get all Group entities that U is a member of, using the regular
- `memberOf`/`hasMember` relation mechanism, and call them G
-- If any G matches any O, return `true`
-- Otherwise, return `false`
-
-## Default sign-in resolvers
-
-Of course you don't have to customize the sign-in resolver if you don't need to.
-The Auth backend plugin comes with a set of default sign-in resolvers which you
-can use. For example - the Google provider has a default email-based sign-in
-resolver, which will search the catalog for a single user entity that has a
-matching `google.com/email` annotation.
-
-It can be enabled like this
+You don't always have to write your own custom resolver. The auth backend plugin provides
+build-in resolvers for many of the common sign-in patterns. You access these via the `resolvers`
+property of each of the auth provider integrations. For example, the Google provider has
+a built in resolver that works just like the one we defined above:
```ts
-// File: packages/backend/src/plugins/auth.ts
-import { googleEmailSignInResolver, createGoogleProvider } from '@backstage/plugin-auth-backend';
-
-export default async function createPlugin(
- env: PluginEnvironment,
-): Promise {
- return await createRouter({
- ...
- providerFactories: {
- google: createGoogleProvider({
- signIn: {
- resolver: googleEmailSignInResolver
- }
-...
+providers.google.create({
+ signIn: {
+ resolver: providers.google.resolvers.emailLocalPartMatchingUserEntityName(),
+ },
+});
```
-## Resolving membership through the catalog
-
-If you want to provide additional claims through Sign-In resolvers but still
-have the software catalog handle group (and transitive group) membership, you
-can do this using the `CatalogIdentityClient` provided as context to Sign-In
-resolvers:
+There are also other options, like the this one that looks up a user
+by matching the `google.com/email` annotation of user entities in the catalog:
```ts
-import { DEFAULT_NAMESPACE, stringifyEntityRef } from '@backstage/catalog-model';
-
-export default async function createPlugin(
- env: PluginEnvironment,
-): Promise {
- return await createRouter({
- ...
- providerFactories: {
- google: createGoogleProvider({
- signIn: {
- resolver: async ({ profile: { email } }, ctx) => {
- const [id] = email?.split('@') ?? '';
- const userEntityRef = stringifyEntityRef({
- kind: 'User',
- namespace: DEFAULT_NAMESPACE,
- name: id,
- });
- // Fetch from an external system that returns entity claims like:
- // ['user:default/breanna.davison', ...]
- const ent = await externalSystemClient.getUsernames(email);
-
- // 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: userEntityRef, ent: fullEnt },
- });
- return { id, token };
- },
- },
- }),
- ...
+providers.google.create({
+ signIn: {
+ resolver: providers.google.resolvers.emailMatchingUserEntityAnnotation(),
+ },
+});
```
-The `resolveCatalogMembership` method will retrieve the referenced entities from
-the catalog, if possible, and check for
-[memberOf](../features/software-catalog/well-known-relations.md#memberof-and-hasmember)
-relations to add additional entity claims.
+## Custom Ownership Resolution
+
+If you want to have more control over the membership resolution and token generation
+that happens during sign-in you can replace `ctx.signInWithCatalogUser` with a set
+of lower-level calls:
+
+```ts
+import { getDefaultOwnershipRefs } from '@backstage/plugin-auth-backend';
+
+// This example only shows the resolver function itself.
+async ({ profile: { email } }, ctx) => {
+ if (!email) {
+ throw new Error('User profile contained no email');
+ }
+
+ // This step calls the catalog to look up a user entity. You could for example
+ // replace it with a call to a different external system.
+ const { entity } = await ctx.findCatalogUser({
+ annotations: {
+ 'acme.org/email': email,
+ },
+ });
+
+ // In this step we extract the ownership references from the user entity using
+ // the standard logic. It uses a reference to the entity itself, as well as the
+ // target of each `memberOf` relation where the target is of the kind `Group`.
+ //
+ // If you replace the catalog lookup with something does not return
+ // an entity you will need to replace this step as well.
+ //
+ // You might also replace it if you for example want to filter out certain groups.
+ const ownershipRefs = getDefaultOwnershipRefs(entity);
+
+ // The last step is to issue the token, where we might provide more options in the future.
+ return ctx.issueToken({
+ claims: {
+ sub: stringifyEntityRef(entity),
+ ent: ownershipRefs,
+ },
+ });
+};
+```
+
+## Sign-In without Users in the Catalog
+
+While populating the catalog with organizational data unlocks more powerful ways
+to browse your software ecosystem, it might not always be a viable or prioritized
+option. However, even if you do not have user entities populated in your catalog, you
+can still sign in users. As there are currently no built-in sign-in resolvers for
+this scenario you will need to implement your own.
+
+Signing in a user that doesn't exist in the catalog is as simple as skipping the
+catalog lookup step from the above example. Rather than looking up the user, we
+instead immediately issue a token using whatever information is available. One caveat
+is that it can be tricky to determine the ownership references, although it can
+be achieved for example through a lookup to an external service. You typically
+want to at least use the user itself as a lone ownership reference.
+
+```ts
+import { DEFAULT_NAMESPACE, stringifyEntityRef, } from '@backstage/catalog-model';
+
+// This example only shows the resolver function itself.
+async ({ profile }, ctx) => {
+ if (!profile.email) {
+ throw new Error(
+ 'Login failed, user profile does not contain an email',
+ );
+ }
+ // We again use the local part of the email as the user name.
+ const [localPart] = profile.email.split('@');
+
+ // By using `stringifyEntityRef` we ensure that the reference is formatted correctly
+ const userEntityRef = stringifyEntityRef({
+ kind: 'User',
+ name: localPart,
+ namespace: DEFAULT_NAMESPACE,
+ });
+
+ return ctx.issueToken({
+ claims: {
+ sub: userEntityRef,
+ ent: [userEntityRef],
+ },
+ });
+},
+```
## AuthHandler
diff --git a/docs/auth/index.md b/docs/auth/index.md
index 6bda35232a..3beae72d0b 100644
--- a/docs/auth/index.md
+++ b/docs/auth/index.md
@@ -1,18 +1,16 @@
---
id: index
-title: Adding Authentication
-description: How to add authentication to a Backstage application
+title: Authentication in Backstage
+description: Introduction to authentication in Backstage
---
-Authentication in Backstage identifies the user, and provides a way for plugins
-to make requests on behalf of a user to third-party services. Backstage can have
-zero (guest access), one, or many authentication providers. The default
-`@backstage/create-app` template uses guest access for easy startup.
+The authentication system in Backstage serves two distinct purposes: sign-in and
+identification of users, as well as delegating access to third-party resources. It is possible to
+configure Backstage to have any number of authentication providers, but only
+one of these will typically be used for sign-in, with the rest being used to provide
+access external resources.
-See [Using authentication and identity](using-auth.md) for tips on using
-Backstage identity information in your app or plugins.
-
-## Adding an authentication provider
+## Built-in Authentication Providers
Backstage comes with many common authentication providers in the core library:
@@ -31,7 +29,7 @@ These built-in providers handle the authentication flow for a particular service
including required scopes, callbacks, etc. These providers are each added to a
Backstage app in a similar way.
-### Adding provider configuration
+## Configuring Authentication Providers
Each built-in provider has a configuration block under the `auth` section of
`app-config.yaml`. For example, the GitHub provider:
@@ -56,25 +54,37 @@ allows a single auth backend to serve multiple environments, such as running a
local frontend against a deployed backend. The provider configuration matching
the local `auth.environment` setting will be selected.
-## Using an authentication provider for sign-in
+## Sign-In Configuration
-If you want to use an authentication provider for sign-in, as opposed to just accessing external resources, you'll need to configure that in your app as well. This is done by providing a custom `SignInPage` component to the app, which will require the user to sign in before they can access the app. Note that this does not block access to the app, which you can read more about [here](./using-auth.md).
+> NOTE: Identity management and the `SignInPage` in Backstage is NOT a method
+> for blocking access for unauthorized users, that either requires additional
+> backend implementation or a separate service like Google's Identity-Aware
+> Proxy. The identity system only serves to provide a personalized experience
+> and access to a Backstage Identity Token, which can be passed to backend
+> plugins.
-If you want to, you can use the `SignInPage` component that is provided by `@backstage/core-components`, which takes either a `provider` or `providers` (array) prop of `SignInProviderConfig` definitions. These reference the `ApiRef` exported for the provider.
+Using an authentication provide for sign-in is something you need to configure
+both in the frontend app, as well as the `auth` backend plugin. For information
+on how to configure the backend app, see [Sign-in Identities and Resolvers](./identity-resolver.md).
+The rest of this section will focus on how to configure sign-in for the frontend app.
-Again, the following example for GitHub shows the additions needed to `packages/app/src/App.tsx`, and can be adapted to any of the built-in providers:
+Sign-in is configured by providing a custom `SignInPage` app component. It will
+rendered before any other routes in the app and is responsible for providing the
+identity of the current user. The `SignInPage` can render any number of pages and
+components, or just blank space with logic running in the background. In the end
+however it must provide a valid Backstage user identity through the `onSignInSuccess`
+callback prop, at which point the rest of the app is rendered.
+
+If you want to, you can use the `SignInPage` component that is provided by `@backstage/core-components`,
+which takes either a `provider` or `providers` (array) prop of `SignInProviderConfig` definitions.
+
+The following example for GitHub shows the additions needed to `packages/app/src/App.tsx`,
+and can be adapted to any of the built-in providers:
```diff
+ import { githubAuthApiRef } from '@backstage/core-plugin-api';
-+ import { SignInProviderConfig, SignInPage } from '@backstage/core-components';
++ import { SignInPage } from '@backstage/core-components';
-+ const githubProvider: SignInProviderConfig = {
-+ id: 'github-auth-provider',
-+ title: 'GitHub',
-+ message: 'Sign in using GitHub',
-+ apiRef: githubAuthApiRef,
-+};
-+
const app = createApp({
apis,
+ components: {
@@ -82,15 +92,20 @@ Again, the following example for GitHub shows the additions needed to `packages/
+
+ ),
+ },
bindRoutes({ bind }) {
```
-To also allow unauthenticated guest access, use the `providers` prop for
-`SignInPage`:
+You can also use the `providers` prop to enable multiple sign-in methods, for example
+allows allowing guest access:
```diff
const app = createApp({
@@ -99,14 +114,60 @@ To also allow unauthenticated guest access, use the `providers` prop for
+ SignInPage: props => (
+
+ ),
+ },
bindRoutes({ bind }) {
```
-## Adding a custom authentication provider
+## For Plugin Developers
+
+The Backstage frontend core APIs provide a set of Utility APIs for plugin developers
+to use, both to access the user identity, as well as third party resources.
+
+### Identity for Plugin Developers
+
+For plugin developers, there is one main touchpoint for accessing the user identity: the
+`IdentityApi` exported by `@backstage/core-plugin-api` via the `identityApiRef`.
+
+The `IdentityApi` gives access to the signed-in user's identity in the frontend.
+It provides access to the user's entity reference, lightweight profile information, and
+a Backstage token that identifies the user when making authenticated calls within Backstage.
+
+When making calls to backend plugins, we recommend that the `FetchApi` is used, which
+is exported via the `fetchApiRef` from `@backstage/core-plugin-api`. The `FetchApi` will
+automatically include a Backstage token in the request, meaning there is no need
+to interact directly with the `IdentityApi`.
+
+### Accessing Third Party Resources
+
+A common pattern for talking to third party services in Backstage is
+user-to-server requests, where short-lived OAuth Access Tokens are requested by
+plugins to authenticate calls to external services. These calls can be made
+either directly to the services or through a backend plugin or service.
+
+By relying on user-to-server calls we keep the coupling between the frontend and
+backend low, and provide a much lower barrier for plugins to make use of third
+party services. This is in comparison to for example a session-based system,
+where access tokens are stored server-side. Such a solution would require a much
+deeper coupling between the auth backend plugin, its session storage, and other
+backend plugins or separate services. A goal of Backstage is to make it as easy
+as possible to create new plugins, and an auth solution based on user-to-server
+OAuth helps in that regard.
+
+The method with which frontend plugins request access to third party services is
+through [Utility APIs](../api/utility-apis.md) for each service provider. These
+are all suffixed with `*AuthApiRef`, for example `githubAuthApiRef`. For a
+full list of providers, see the
+[@backstage/core-plugin-api](../reference/core-plugin-api.md#variables) reference.
+
+## Custom Authentication Provider
There are generic authentication providers for OAuth2 and SAML. These can reduce
the amount of code needed to implement a custom authentication provider that
diff --git a/docs/auth/using-auth.md b/docs/auth/using-auth.md
deleted file mode 100644
index 067c43e8a0..0000000000
--- a/docs/auth/using-auth.md
+++ /dev/null
@@ -1,98 +0,0 @@
----
-id: using-auth
-title: Using authentication and identity
-description: How to use authentication and identity in Backstage
----
-
-The Auth APIs in Backstage identify the user, and provide a way for plugins to
-request access to 3rd party services on behalf of the user (OAuth). This
-documentation focuses on the implementation of that solution and how to extend
-it.
-
-### Accessing Third Party Services
-
-The main pattern for talking to third party services in Backstage is
-user-to-server requests, where short-lived OAuth Access Tokens are requested by
-plugins to authenticate calls to external services. These calls can be made
-either directly to the services or through a backend plugin or service.
-
-By relying on user-to-server calls we keep the coupling between the frontend and
-backend low, and provide a much lower barrier for plugins to make use of third
-party services. This is in comparison to for example a session-based system,
-where access tokens are stored server-side. Such a solution would require a much
-deeper coupling between the auth backend plugin, its session storage, and other
-backend plugins or separate services. A goal of Backstage is to make it as easy
-as possible to create new plugins, and an auth solution based on user-to-server
-OAuth helps in that regard.
-
-The method with which frontend plugins request access to third party services is
-through [Utility APIs](../api/utility-apis.md) for each service provider. For a
-full list of providers, see the
-[@backstage/core-plugin-api](../reference/core-plugin-api.md#variables)
-reference.
-
-### Identity - WIP
-
-> NOTE: Identity management and the `SignInPage` in Backstage is NOT a method
-> for blocking access for unauthorized users, that either requires additional
-> backend implementation or a separate service like Google's Identity-Aware
-> Proxy. The identity system only serves to provide a personalized experience
-> and access to a Backstage Identity Token, which can be passed to backend
-> plugins.
-
-Identity management is still work in progress, but there are already a couple of
-pieces in place that can be used.
-
-#### Identity for Plugin Developers
-
-As a plugin developer, there are two main touchpoints for identities: the
-`IdentityApi` exported by `@backstage/core-plugin-api` via the `identityApiRef`,
-and a not yet existing middleware exported by `@backstage/backend-common`.
-
-The `IdentityApi` gives access to the signed-in user's identity in the frontend.
-It provides access to the user's ID, lightweight profile information, and an ID
-token used to make authenticated calls within Backstage.
-
-The middleware that will be provided by `@backstage/backend-common` allows
-verification of Backstage ID tokens, and optionally loading additional
-information about the user. The progress is tracked in
-https://github.com/backstage/backstage/issues/1435.
-
-#### Identity for App Developers
-
-If you're setting up your own Backstage app, or want to add a new identity
-provider, there are three touchpoints: the frontend auth APIs in
-`@backstage/core-app-api` and `@backstage/core-plugin-api`, the backend auth
-providers in `auth-backend`, and the `SignInPage` component configured in the
-Backstage app via `createApp`.
-
-The frontend APIs and backend providers are tightly coupled together for each
-auth provider, and together they implement an e2e auth flow. Only some auth
-providers also act as identity providers though. For example, at the moment of
-writing, the Google Auth provider is able to act as a Backstage identity
-provider, but the GitHub one can not. For an auth provider to also act as an
-identity provider, it needs to implement the `BackstageIdentityApi` in the
-frontend, and in the backend it needs to return a `BackstageIdentity` structure.
-
-It is up to each provider to implement the mapping between a provider identity
-and the corresponding Backstage identity. That is currently still work in
-progress, and as a stop-gap for example the Google provider returns the local
-part of the user's email as the user ID.
-
-The final piece of the puzzle is the `SignInPage` component that can be
-configured as part of the app. Without a sign-in page, Backstage will fall back
-to a `guest` identity for all users, without any ID token. To enable sign-in, a
-`SignInPage` needs to be configured, which in turn has to supply a user to the
-app. The `@backstage/core-components` package provides a basic sign-in page that
-allows both the user and the app developer to choose between a couple of
-different sign-in methods, or to designate a single provider that may also be
-logged in to automatically.
-
-## Further Reading
-
-More details are provided in dedicated sections of the documentation.
-
-- [OAuth](./oauth.md): Description of the generic OAuth flow implemented by the
- [auth-backend](https://github.com/backstage/backstage/tree/master/plugins/auth-backend).
-- [Glossary](./glossary.md): Glossary of some common terms related to the auth
- flows.
diff --git a/docs/conf/writing.md b/docs/conf/writing.md
index a4da1e3df0..aef9620373 100644
--- a/docs/conf/writing.md
+++ b/docs/conf/writing.md
@@ -161,7 +161,7 @@ $file: ./my-secret.txt
The `$include` keyword can be used to load configuration values from an external
file. It's able to load and parse data from `.json`, `.yml`, and `.yaml` files.
-It's also possible to include a url fragment (`#`) to point to a value at the
+It's also possible to include a URL fragment (`#`) to point to a value at the
given path in the file, using a dot-separated list of keys.
For example, the following would read `my-secret-key` from `my-secrets.json`:
diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md
index 0b99e81d64..01bc6279f2 100644
--- a/docs/deployment/docker.md
+++ b/docs/deployment/docker.md
@@ -59,18 +59,19 @@ Once the host build is complete, we are ready to build our image. The following
FROM node:16-bullseye-slim
WORKDIR /app
+
+# install sqlite3 dependencies, you can skip this if you don't use sqlite3 in the image
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \
+ rm -rf /var/lib/apt/lists/* && \
+ yarn config set python /usr/bin/python3
+
# Copy repo skeleton first, to avoid unnecessary docker cache invalidation.
# The skeleton contains the package.json of each package in the monorepo,
# and along with yarn.lock and the root package.json, that's enough to run yarn install.
COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./
RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz
-# install sqlite3 dependencies
-RUN apt-get update && \
- apt-get install -y libsqlite3-dev python3 cmake g++ && \
- rm -rf /var/lib/apt/lists/* && \
- yarn config set python /usr/bin/python3
-
RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)"
# Then copy the rest of the backend bundle, along with any other files we might want.
@@ -159,7 +160,8 @@ WORKDIR /app
COPY --from=packages /app .
# install sqlite3 dependencies
-RUN apt-get update && apt-get install -y libsqlite3-dev python3 cmake g++ && \
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \
yarn config set python /usr/bin/python3
RUN yarn install --frozen-lockfile --network-timeout 600000 && rm -rf "$(yarn cache dir)"
@@ -176,16 +178,16 @@ FROM node:16-bullseye-slim
WORKDIR /app
+# install sqlite3 dependencies, you can skip this if you don't use sqlite3 in the image
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \
+ rm -rf /var/lib/apt/lists/* && \
+ yarn config set python /usr/bin/python3
+
# Copy the install dependencies from the build stage and context
COPY --from=build /app/yarn.lock /app/package.json /app/packages/backend/dist/skeleton.tar.gz ./
RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz
-# install sqlite3 dependencies
-RUN apt-get update && \
- apt-get install -y libsqlite3-dev python3 cmake g++ && \
- rm -rf /var/lib/apt/lists/* && \
- yarn config set python /usr/bin/python3
-
RUN yarn install --frozen-lockfile --production --network-timeout 600000 && rm -rf "$(yarn cache dir)"
# Copy the built packages from the build stage
diff --git a/docs/features/kubernetes/configuration.md b/docs/features/kubernetes/configuration.md
index dd7e666be4..cb30451c7d 100644
--- a/docs/features/kubernetes/configuration.md
+++ b/docs/features/kubernetes/configuration.md
@@ -228,7 +228,13 @@ For example:
```yaml
- type: 'gke'
projectId: 'gke-clusters'
- region: 'europe-west1'
+ region: 'europe-west1' # optional
+ skipTLSVerify: false # optional
+ skipMetricsLookup: false # optional
+ exposeDashboard: false # optional
+ matchingResourceLabels: # optional
+ - key: 'environment'
+ value: 'production'
```
Will configure the Kubernetes plugin to connect to all GKE clusters in the
@@ -247,17 +253,17 @@ The Google Cloud project to look for Kubernetes clusters in.
The Google Cloud region to look for Kubernetes clusters in. Defaults to all
regions.
-##### `skipTLSVerify`
+##### `skipTLSVerify` (optional)
This determines whether the Kubernetes client verifies the TLS certificate
presented by the API server. Defaults to `false`.
-##### `skipMetricsLookup`
+##### `skipMetricsLookup` (optional)
This determines whether the Kubernetes client looks up resource metrics
CPU/Memory for pods returned by the API server. Defaults to `false`.
-##### `exposeDashboard`
+##### `exposeDashboard` (optional)
This determines whether the `dashboardApp` and `dashboardParameters` should be
automatically configured in order to expose the GKE dashboard from the
@@ -265,6 +271,11 @@ Kubernetes plugin.
Defaults to `false`.
+##### `matchingResourceLabels` (optional)
+
+Array of key value labels used to filter out clusters which don't have the matching
+[resource labels](https://cloud.google.com/resource-manager/docs/creating-managing-labels).
+
#### Custom `KubernetesClustersSupplier`
If the configuration-based cluster locators do not work for your use-case,
@@ -355,6 +366,16 @@ annotations:
'backstage.io/kubernetes-id': dice-roller
```
+#### Adding the namespace annotation
+
+Entities can have the `backstage.io/kubernetes-namespace` annotation, this will cause the entity's Kubernetes resources
+to by looked up via that namespace.
+
+```yaml
+annotations:
+ 'backstage.io/kubernetes-namespace': dice-space
+```
+
#### Labeling Kubernetes components
In order for Kubernetes components to show up in the software catalog as a part
diff --git a/docs/features/kubernetes/installation.md b/docs/features/kubernetes/installation.md
index e920bd44ea..ec0355c7d8 100644
--- a/docs/features/kubernetes/installation.md
+++ b/docs/features/kubernetes/installation.md
@@ -13,9 +13,7 @@ If you haven't setup Backstage already, read the
## Adding the Kubernetes frontend plugin
The first step is to add the Kubernetes frontend plugin to your Backstage
-application. Navigate to your new Backstage application directory, and then to
-your `packages/app` directory, and install the `@backstage/plugin-kubernetes`
-package.
+application.
```bash
# From your Backstage root directory
diff --git a/docs/features/search/README.md b/docs/features/search/README.md
index ed950d8ac8..a151da1736 100644
--- a/docs/features/search/README.md
+++ b/docs/features/search/README.md
@@ -24,15 +24,12 @@ Backstage ecosystem.
## Project roadmap
-| Version | Description |
-| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Backstage Search Pre-Alpha ✅ | Search Frontend letting you search through the entities of the software catalog. [See Pre-Alpha Use Cases.](#backstage-search-pre-alpha) |
-| Backstage Search Alpha ✅ | Basic “out-of-the-box” in-memory indexing process of entities, and their metadata, registered to the Software Catalog. [See Alpha Use Cases](#backstage-search-alpha). |
-| Backstage Search Beta ✅ | At least one production-ready search engine that supports the same use-cases as in the alpha. [See Beta Use Cases](#backstage-search-beta). |
-| [Backstage Search GA ⌛][ga] | A stable Search API for plugin developers to add search to their plugins, and app integrators to expose that to their users. [See GA Use Cases](#backstage-search-ga). |
-
-[beta]: https://github.com/backstage/backstage/milestone/27
-[ga]: https://github.com/backstage/backstage/milestone/28
+| Version | Description |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| Backstage Search Pre-Alpha ✅ | Search Frontend letting you search through the entities of the software catalog. [See Pre-Alpha Use Cases.](#backstage-search-pre-alpha) |
+| Backstage Search Alpha ✅ | Basic “out-of-the-box” in-memory indexing process of entities, and their metadata, registered to the Software Catalog. [See Alpha Use Cases](#backstage-search-alpha). |
+| Backstage Search Beta ✅ | At least one production-ready search engine that supports the same use-cases as in the alpha. [See Beta Use Cases](#backstage-search-beta). |
+| [Backstage Search 1.0 ⌛] | A stable Search API for plugin developers to add search to their plugins, and app integrators to expose that to their users. [See 1.0 Use Cases](#backstage-search-1.0). |
## Use Cases
@@ -82,9 +79,9 @@ are met, and can be deployed using a production-ready search engine.
search engine according to my organization's needs, but a sensible default
query should be in place so that I am not required to do so.
-#### Backstage Search GA
+#### Backstage Search 1.0
-We will consider Backstage Search to be generally available (GA) when the above
+We will consider Backstage Search to be 1.0 when the above
use-cases are met, and an ecosystem of search-enabled plugins are available and
stable.
@@ -113,22 +110,26 @@ search engines.
## Plugins Integrated with Search
-| Plugin | Support Status |
-| -------------------------------------------------------------- | -------------- |
-| Catalog | ✅ |
-| [TechDocs](./how-to-guides.md#how-to-index-techdocs-documents) | ✅ |
+| Plugin | Support Status |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- |
+| Catalog | ✅ |
+| [TechDocs](./how-to-guides.md#how-to-index-techdocs-documents) | ✅ |
+| [Stack Overflow](https://github.com/backstage/backstage/blob/master/plugins/stack-overflow-backend/README.md#index-stack-overflow-questions-to-search) | ✅ |
[Reach out to us](#get-involved) if you want to chat about support for more
plugins integrated to search.
## Tech Stack
-| Stack | Location |
-| --------------- | ------------------------------------- |
-| Frontend Plugin | @backstage/plugin-search |
-| Backend Plugin | @backstage/plugin-search-backend |
-| Indexer Plugin | @backstage/plugin-search-backend-node |
-| Common Code | @backstage/plugin-search-common |
+| Stack | Location |
+| ------------------------- | ----------------------------------------------------- |
+| Frontend Plugin | @backstage/plugin-search |
+| Frontend Plugin Library | @backstage/plugin-search-react |
+| Isomorphic Plugin Library | @backstage/plugin-search-common |
+| Backend Plugin | @backstage/plugin-search-backend |
+| Backend Plugin Library | @backstage/plugin-search-backend-node |
+| Backend Plugin Module | @backstage/plugin-search-backend-module-elasticsearch |
+| Backend Plugin Module | @backstage/plugin-search-backend-module-pg |
## Get Involved
diff --git a/docs/features/software-templates/writing-custom-field-extensions.md b/docs/features/software-templates/writing-custom-field-extensions.md
index 3ff08e6e73..8618e04781 100644
--- a/docs/features/software-templates/writing-custom-field-extensions.md
+++ b/docs/features/software-templates/writing-custom-field-extensions.md
@@ -74,17 +74,17 @@ export const myCustomValidation = (
This is where the magic happens and creates the custom field extension.
Note that if you're writing extensions part of a separate plugin,
- then please use `plugin.provide` from there instead and export it part of your `plugin.ts` rather than re-using the `scaffolder.plugin`.
+ then please use `scaffolderPlugin.provide` from there instead and export it part of your `plugin.ts` rather than re-using the `scaffolder.plugin`.
*/
import {
- plugin,
+ scaffolderPlugin,
createScaffolderFieldExtension,
} from '@backstage/plugin-scaffolder';
import { MyCustomExtension } from './MyCustomExtension';
import { myCustomValidation } from './validation';
-export const MyCustomFieldExtension = plugin.provide(
+export const MyCustomFieldExtension = scaffolderPlugin.provide(
createScaffolderFieldExtension({
name: 'MyCustomExtension',
component: MyCustomExtension,
diff --git a/docs/features/techdocs/README.md b/docs/features/techdocs/README.md
index 340c0d9396..c64d0b785d 100644
--- a/docs/features/techdocs/README.md
+++ b/docs/features/techdocs/README.md
@@ -76,30 +76,34 @@ TechDocs packages:
TechDocs promoted to v1.0! To understand how this change affects the package, please check out our [versioning policy](https://backstage.io/docs/overview/versioning-policy).
+**v1.2** 🚧
+
+With the Backstage 1.2 release, we plan to introduce the [TechDocs Addon Framework](https://github.com/backstage/backstage/issues/9636) for augmenting the TechDocs experience at read-time.
+
+In addition to the framework itself, we'll be open sourcing a `` addon, helping you to create a feedback loop that drives up documentation quality and fosters a documentation culture at your organization.
+
### **Future work 🔮**
Some of the following items are coming soon and some are potential ideas.
-- [TechDocs Addon Framework](https://github.com/backstage/backstage/issues/9636)
-- Contribute to and deploy from a marketplace of TechDocs Addons
-- Addon: Highlight text and raise an Issue to create a feedback loop to drive up documentation quality
-- Addon: MDX (allows you to use JSX in your Markdown content)
- Better integration with
[Scaffolder V2](https://github.com/backstage/backstage/issues/2771) (e.g. easy to choose and plug documentation template with Software Templates)
-- Static site generator agnostic
+- Static site generator agnostic, including possible support for MDX (allowing you to use JSX in your Markdown content)
- Possible to configure several aspects about TechDocs (e.g. URL, homepage,
theme)
## Tech stack
-| Stack | Location |
-| ----------------------------------------------- | -------------------------------------------------------- |
-| Frontend Plugin | [`@backstage/plugin-techdocs`][techdocs/frontend] |
-| Backend Plugin | [`@backstage/plugin-techdocs-backend`][techdocs/backend] |
-| CLI (for local development and generating docs) | [`@techdocs/cli`][techdocs/cli] |
-| Docker Container (for generating docs) | [`techdocs-container`][techdocs/container] |
+| Stack | Location |
+| ----------------------------------------------- | --------------------------------------------------------------- |
+| Frontend Plugin | [`@backstage/plugin-techdocs`][techdocs/frontend] |
+| Frontend Plugin Library | [`@backstage/plugin-techdocs-react`][techdocs/frontend-library] |
+| Backend Plugin | [`@backstage/plugin-techdocs-backend`][techdocs/backend] |
+| CLI (for local development and generating docs) | [`@techdocs/cli`][techdocs/cli] |
+| Docker Container (for generating docs) | [`techdocs-container`][techdocs/container] |
[techdocs/frontend]: https://github.com/backstage/backstage/blob/master/plugins/techdocs
+[techdocs/frontend-library]: https://github.com/backstage/backstage/blob/master/plugins/techdocs-react
[techdocs/backend]: https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend
[techdocs/container]: https://github.com/backstage/techdocs-container
[techdocs/cli]: https://github.com/backstage/techdocs-cli
diff --git a/docs/features/techdocs/addons.md b/docs/features/techdocs/addons.md
new file mode 100644
index 0000000000..0fba3b92e3
--- /dev/null
+++ b/docs/features/techdocs/addons.md
@@ -0,0 +1,218 @@
+---
+id: addons
+title: TechDocs Addons
+description: How to find, use, or create TechDocs Addons.
+---
+
+> Note: This page contains documentation for features that have not yet been
+> released on a [main-line version](https://backstage.io/docs/overview/versioning-policy#main-release-line)
+> of Backstage and TechDocs. We plan to make Addons generally available in
+> Backstage v1.2.
+
+## Concepts
+
+TechDocs is a centralized platform for publishing, viewing, and discovering
+technical documentation across an entire organization. It's a solid foundation!
+But it doesn't solve higher-order documentation needs on its own: how do you
+create and reinforce a culture of documentation? How do you build trust in the
+quality of technical documentation?
+
+TechDocs Addons are a mechanism by which you can customize the TechDocs
+experience in order to try and address some of these higher-order needs.
+
+### Addons
+
+An Addon is just a react component. Like any react component, it can retrieve
+and render data using normal Backstage or native hooks, APIs, and components.
+Props can be used to configure its behavior, where appropriate.
+
+### Locations
+
+Addons declare a `location` where they will be rendered. Most locations are
+representative of physical spaces in the TechDocs UI:
+
+- `Header`: For Addons which fill up the header from the right, on the same
+ line as the title.
+- `Subheader`: For Addons that sit below the header but above all content.
+ This is a great location for tooling/configuration of TechDocs display.
+- `PrimarySidebar`: Left of the content, above of the navigation.
+- `SecondarySidebar`: Right of the content, above the table of contents.
+- `Content`: A special location intended for Addons which augment the
+ statically generated content of the documentation itself.
+- `Component`: A [proposed-but-not-yet-implemented](https://github.com/backstage/backstage/issues/11109)
+ virtual location, aimed at simplifying a common type of Addon.
+
+
+
+### Addon Registry
+
+The installation and configuration of Addons happens within a Backstage app's
+frontend. Addons are imported from plugins and added underneath a registry
+component called ``. This registry can be configured for both
+the TechDocs Reader page as well as the Entity docs page.
+
+Addons are rendered in the order in which they are registered.
+
+## Installing and using Addons
+
+Addons can be installed and configured in much the same way as extensions for
+other Backstage plugins: by adding them underneath an extension registry
+component (``) under the route representing the TechDocs Reader
+page in your `App.tsx`:
+
+```tsx
+// packages/app/src/App.tsx
+
+import { TechDocsReaderPage } from '@backstage/plugin-techdocs';
+import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha';
+import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
+
+// ...
+
+}>
+
+
+ {/* Other addons can be added here. */}
+
+;
+```
+
+The process for configuring Addons on the documentation tab on the entity page
+is very similar; instead of adding the `` registry under a
+``, you'd add it as a child of ``:
+
+```tsx
+// packages/app/src/components/catalog/EntityPage.tsx
+
+import { EntityLayout } from '@backstage/plugin-catalog';
+import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
+import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha';
+import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
+
+// ...
+
+
+
+
+
+ {/* Other addons can be added here. */}
+
+
+;
+```
+
+Note that on the entity page, because the Catalog plugin is responsible for the
+page header, TechDocs Addons whose location is `Header` will not be rendered.
+
+## Available Addons
+
+Addons can, in principle, be provided by any plugin! To make it easier to
+discover available Addons, we've compiled a list of them here:
+
+| Addon | Package/Plugin | Description |
+| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.reportissue) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
+
+Got an Addon to contribute? Feel free to add a row above!
+
+## Creating an Addon
+
+The simplest Addons are plain old react components that get rendered in
+specific locations within a TechDocs site. To package such a react component as
+an Addon, follow these steps:
+
+1. Write the component in your plugin like any other component
+2. Create, provide, and export the component from your plugin
+
+```ts
+// plugins/your-plugin/src/plugin.ts
+
+import {
+ createTechDocsAddonExtension,
+ TechDocsAddonLocations,
+} from '@backstage/plugin-techdocs-react/alpha';
+import { CatGifComponent, CatGifComponentProps } from './addons';
+
+// ...
+
+// You must "provide" your Addon, just like any extension, via your plugin.
+export const CatGif = yourPlugin.provide(
+ // This function "creates" the Addon given a component and location. If your
+ // component can be configured via props, pass the prop type here too.
+ createTechDocsAddonExtension({
+ name: 'CatGif',
+ location: TechDocsAddonLocations.Header,
+ component: CatGifComponent,
+ }),
+);
+```
+
+### Addons in the Content location
+
+Beyond the "render a component in a region" use-case, it's also possible for
+Addons to access and manipulate a TechDocs site's DOM; this could be used to,
+for example, load and instantiate client-side diagramming libraries, replace
+elements with dynamically loaded content, etc.
+
+This type of Addon is still expressed as a react component, but instead of
+returning a react element to be rendered, it updates the DOM via side-effects
+(e.g. with `useEffect`). Access to the DOM is made available via utility hooks
+provided by the Addon framework.
+
+```tsx
+// plugins/your-plugin/src/addons/MakeAllImagesCatGifs.tsx
+
+import React, { useEffect } from 'react';
+import { useShadowRootElements } from '@backstage/plugin-techdocs-react/alpha';
+
+// This is a normal react component; in order to make it an Addon, you would
+// still create and provide it via your plugin as described above. The only
+// difference is that you'd set `location` to `TechDocsAddonLocations.Content`.
+export const MakeAllImagesCatGifsAddon = () => {
+ // This hook can be used to get references to specific elements. If you need
+ // access to the whole shadow DOM, use the the underlying useShadowRoot()
+ // hook instead.
+ const images = useShadowRootElements(['img']);
+
+ useEffect(() => {
+ images.forEach(img => {
+ if (img.src !== 'https://example.com/cat.gif') {
+ img.src = 'https://example.com/cat.gif';
+ }
+ });
+ }, [images]);
+
+ // Nothing to render directly, so we can just return null.
+ return null;
+};
+```
+
+### Testing Addons
+
+Install `@backstage/plugin-techdocs-addons-test-utils` as a `devDependency` in
+your plugin for access to utilities that make testing such Addons easier.
+
+A test for the above Addon might look something like this:
+
+```tsx
+// plugins/your-plugin/src/addons/MakeAllImagesCatGifs.test.tsx
+import { TechDocsAddonTester } from '@backstage/plugin-techdocs-addons-test-utils';
+
+// Note: import your actual addon (the one provided by your plugin).
+import { MakeAllImagesCatGifs } from '../plugin.ts';
+
+describe('MakeAllImagesCatGifs', () => {
+ it('replaces img srcs with cat gif', async () => {
+ const { getByTestId } = await TechDocsAddonTester.buildAddonsInTechDocs([
+ ,
+ ])
+ .withDom()
+ .renderWithEffects();
+
+ expect(getByTestId('fixture')).toHaveAttribute(
+ 'src',
+ 'https://example.com/cat.gif',
+ );
+ });
+});
+```
diff --git a/docs/features/techdocs/cli.md b/docs/features/techdocs/cli.md
index 6f6dbf7552..9a7dccd5a6 100644
--- a/docs/features/techdocs/cli.md
+++ b/docs/features/techdocs/cli.md
@@ -120,7 +120,7 @@ Generate TechDocs documentation site using MkDocs.
Options:
--source-dir Source directory containing mkdocs.yml and docs/ directory. (default: ".")
--output-dir Output directory containing generated TechDocs site. (default: "./site/")
- --docker-image The mkdocs docker container to use (default: "spotify/techdocs:v0.3.6")
+ --docker-image The mkdocs docker container to use (default: "spotify/techdocs:v1.0.2")
--no-pull Do not pull the latest docker image
--no-docker Do not use Docker, use MkDocs executable and plugins in current user environment.
--techdocs-ref The repository hosting documentation source files e.g.
diff --git a/docs/features/techdocs/concepts.md b/docs/features/techdocs/concepts.md
index e34f58bc70..2944197dfb 100644
--- a/docs/features/techdocs/concepts.md
+++ b/docs/features/techdocs/concepts.md
@@ -18,8 +18,8 @@ GitLab, etc.) and passes the files to the generator for next steps.
There are two kinds of preparers available -
-1. Common Git Preparer - Uses `git clone` on any repository url.
-2. Url Reader - Uses source code hosting provider's API to download files.
+1. Common Git Preparer - Uses `git clone` on any repository URL.
+2. URL Reader - Uses source code hosting provider's API to download files.
(Faster and recommended)
### TechDocs Generator
@@ -96,10 +96,6 @@ Documentation generated by TechDocs is generated as static HTML sites. The
TechDocs Reader was therefore created to be able to integrate pre-generated HTML
sites with the Backstage UI.
-The TechDocs Reader purpose is also to open up the opportunity to integrate
-TechDocs widgets for a customized full-featured TechDocs experience.
-([coming soon V.3](./README.md#project-roadmap))
-
[TechDocs Reader](https://github.com/backstage/backstage/blob/master/plugins/techdocs/src/reader/README.md)
## Transformers
@@ -110,3 +106,19 @@ transform the HTML content on pre and post render (e.g. rewrite docs links or
modify css).
[Transformers API docs](https://github.com/backstage/backstage/blob/master/plugins/techdocs/src/reader/README.md)
+
+## TechDocs Addons
+
+Addons (introduced in Backstage v1.2) are client-side, React-based extensions
+that can be used to augment the TechDocs experience at read-time. They offer a
+mechanism for configuring the TechDocs Reader to better suit your
+organization's needs.
+
+Addons can dynamically load and display information anywhere in the TechDocs
+Reader, including within the statically generated content itself.
+
+Addons should not be confused with `mkdocs` plugins, which may be used to
+customize a TechDocs site's content at build-time. While it's possible to take
+advantage of some `mkdocs` plugins, not all such plugins play well with
+TechDocs (primarily, but not exclusively, for security reasons). Addons offer
+an alternative.
diff --git a/docs/features/techdocs/configuring-ci-cd.md b/docs/features/techdocs/configuring-ci-cd.md
index a4da4e5d95..0f8044e9c9 100644
--- a/docs/features/techdocs/configuring-ci-cd.md
+++ b/docs/features/techdocs/configuring-ci-cd.md
@@ -29,7 +29,7 @@ cd repo
# Install @techdocs/cli, mkdocs and mkdocs plugins
npm install -g @techdocs/cli
-pip install mkdocs-techdocs-core==0.*
+pip install mkdocs-techdocs-core==1.*
# Generate
techdocs-cli generate --no-docker
@@ -167,7 +167,7 @@ jobs:
run: sudo npm install -g @techdocs/cli
- name: Install mkdocs and mkdocs plugins
- run: python -m pip install mkdocs-techdocs-core==0.*
+ run: python -m pip install mkdocs-techdocs-core==1.*
- name: Generate docs site
run: techdocs-cli generate --no-docker --verbose
diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md
index 30d846efda..1eeebae903 100644
--- a/docs/features/techdocs/getting-started.md
+++ b/docs/features/techdocs/getting-started.md
@@ -227,7 +227,7 @@ You can do so by including the following lines in the last step of your
```Dockerfile
RUN apt-get update && apt-get install -y python3 python3-pip
-RUN pip3 install mkdocs-techdocs-core==0.2.2
+RUN pip3 install mkdocs-techdocs-core==1.0.1
```
Please be aware that the version requirement could change, you need to check our
diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md
index 56ca2252d0..4f2dc6c348 100644
--- a/docs/features/techdocs/how-to-guides.md
+++ b/docs/features/techdocs/how-to-guides.md
@@ -162,20 +162,11 @@ The `techDocsPage` is a default techdocs reader page which lives in
having to set anything up.
```tsx
-
- {({ techdocsMetadataValue, entityMetadataValue, entityRef, onReady }) => (
- <>
-
-
-
-
- >
- )}
-
+
+
+
+
+
```
If you would like to compose your own `techDocsPage`, you can do so by replacing
@@ -183,42 +174,30 @@ the children of TechDocsPage with something else. Maybe you are _just_
interested in replacing the Header:
```tsx
-
- {({ entityRef, onReady }) => (
- <>
-
-
-
-
- >
- )}
-
+
+
+
+
```
Or maybe you want to disable the in-context search
```tsx
-
- {({ entityRef, onReady }) => (
- <>
-
-
-
-
- >
- )}
-
+
+
+
+
```
Or maybe you want to replace the entire TechDocs Page.
```tsx
-
+
my own content
-
+
```
## How to migrate from TechDocs Alpha to Beta
@@ -458,7 +437,7 @@ FROM python:3.8-alpine
RUN apk update && apk --no-cache add gcc musl-dev openjdk11-jdk curl graphviz ttf-dejavu fontconfig
-RUN pip install --upgrade pip && pip install mkdocs-techdocs-core==0.2.1
+RUN pip install --upgrade pip && pip install mkdocs-techdocs-core==1.0.1
RUN pip install mkdocs-kroki-plugin
diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md
index 66eaf00663..5a53961e81 100644
--- a/docs/features/techdocs/using-cloud-storage.md
+++ b/docs/features/techdocs/using-cloud-storage.md
@@ -461,7 +461,7 @@ Since the new SDK doesn't use the old way authentication, we don't need the keys
The new SDK needs the OpenStack Swift connection URL for connecting the Swift.
So you need to add a new key called `openStackSwift.swiftUrl` and give the
-OpenStack Swift url here. Example url should look like that:
+OpenStack Swift URL here. Example URL should look like that:
`https://example.com:6780/swift/v1`
##### That's it!
diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md
index 95fb2afc12..fc78217fbc 100644
--- a/docs/getting-started/configuration.md
+++ b/docs/getting-started/configuration.md
@@ -193,9 +193,7 @@ go to your Backstage portal in your browser, you should have your login prompt!
To learn more about Authentication in Backstage, here are some docs you
could read:
-- [Adding Authentication](../auth/)
-- [Adding a new Authentication Provider](../auth/add-auth-provider.md)
-- [Using authentication and identity](../auth/using-auth.md)
+- [Authentication in Backstage](../auth/)
- [Using organizational data from GitHub](../integrations/github/org.md)
### Setting up a GitHub Integration
@@ -203,7 +201,7 @@ could read:
The GitHub integration supports loading catalog entities from GitHub or GitHub
Enterprise. Entities can be added to static catalog configuration, registered
with the catalog-import plugin, or discovered from a GitHub organization. Users
-and Groups can also be loaded from an organization. While using GitHub Apps
+and Groups can also be loaded from an organization. While using [GitHub Apps](../integrations/github/github-apps.md)
might be the best way to set up integrations, for this tutorial you'll use a
Personal Access Token.
@@ -217,25 +215,35 @@ for 7 days, it's a lucky number.
-Set the scope to your likings. For this tutorial, selecting "repo" and "workflow" is required as the scaffolding job in this guide configures a GitHub actions workflow for the newly created project.
-enough.
+Set the scope to your likings. For this tutorial, selecting `repo` and `workflow` is required as the scaffolding job in this guide configures a GitHub actions workflow for the newly created project.
-In the `app-config.yaml`, search for `integrations:` and add your token, like we
-did in below example:
+For this tutorial, we will be writing the token to `app-config.local.yaml`. This file might not exist for you, so if it doesn't go ahead and create it alongside the `app-config.yaml` at the root of the project.
+This file should also be excluded in `.gitignore`, to avoid accidental committing of this file.
+
+In your `app-config.local.yaml` go ahead and add the following:
```yaml
integrations:
github:
- host: github.com
- token: ghp_urtokendeinfewinfiwebfweb
+ token: ghp_urtokendeinfewinfiwebfweb # this should be the token from GitHub
```
That's settled. This information will be leveraged by other plugins.
+If you're looking for a more production way to manage this secret, then you can do the following with the token being stored in an environment variable called `GITHUB_TOKEN`.
+
+```yaml
+integrations:
+ github:
+ - host: github.com
+ token: ${GITHUB_TOKEN} # this will use the environment variable GITHUB_TOKEN
+```
+
Some helpful links, for if you want to learn more about:
- [Other available integrations](../integrations/)
-- [Using GitHub Apps instead of a Personal Access Token](../plugins/github-apps.md#docsNav)
+- [Using GitHub Apps instead of a Personal Access Token](../integrations/github/github-apps.md#docsNav)
### Explore what we've done so far
diff --git a/docs/getting-started/project-structure.md b/docs/getting-started/project-structure.md
index b67e847272..cbe84db2e0 100644
--- a/docs/getting-started/project-structure.md
+++ b/docs/getting-started/project-structure.md
@@ -24,7 +24,7 @@ the code.
- [`.github/`](https://github.com/backstage/backstage/tree/master/.github) -
Standard GitHub folder. It contains - amongst other things - our workflow
definitions and templates. Worth noting is the
- [styles](https://github.com/backstage/backstage/tree/master/.github/styles)
+ [vale](https://github.com/backstage/backstage/tree/master/.github/vale)
sub-folder which is used for a markdown spellchecker.
- [`.yarn/`](https://github.com/backstage/backstage/tree/master/.yarn) -
@@ -212,9 +212,6 @@ future.
common for companies to have their own npm registry, and this file makes sure
that this folder always uses the public registry.
-- [`.vale.ini`](https://github.com/backstage/backstage/tree/master/.vale.ini) -
- [Spell checker](https://github.com/errata-ai/vale) for Markdown files.
-
- [`.yarnrc`](https://github.com/backstage/backstage/tree/master/.yarnrc) -
Enforces "our" version of Yarn.
diff --git a/docs/integrations/bitbucket/locations.md b/docs/integrations/bitbucket/locations.md
index 67c4dcac33..c0c6afc7a3 100644
--- a/docs/integrations/bitbucket/locations.md
+++ b/docs/integrations/bitbucket/locations.md
@@ -6,38 +6,51 @@ sidebar_label: Locations
description: Integrating source code stored in Bitbucket into the Backstage catalog
---
-The Bitbucket integration supports loading catalog entities from bitbucket.org
-or a self-hosted Bitbucket. Entities can be added to
+The Bitbucket integration supports loading catalog entities from bitbucket.org (Bitbucket Cloud)
+or Bitbucket Server. Entities can be added to
[static catalog configuration](../../features/software-catalog/configuration.md),
or registered with the
[catalog-import](https://github.com/backstage/backstage/tree/master/plugins/catalog-import)
plugin.
+## Bitbucket Cloud
+
```yaml
integrations:
- bitbucket:
- - host: bitbucket.org
- token: ${BITBUCKET_TOKEN}
+ bitbucketCloud:
+ - username: ${BITBUCKET_CLOUD_USERNAME}
+ appPassword: ${BITBUCKET_CLOUD_PASSWORD}
```
-> Note: A public Bitbucket provider is added automatically at startup for
-> convenience, so you only need to list it if you want to supply a
-> [token](https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html).
+> Note: A public Bitbucket Cloud provider is added automatically at startup for
+> convenience, so you only need to list it if you want to supply credentials.
-Directly under the `bitbucket` key is a list of provider configurations, where
-you can list the Bitbucket providers you want to fetch data from. Each entry is
-a structure with up to four elements:
+Directly under the `bitbucketCloud` key is a list of provider configurations, where
+you can list the Bitbucket Cloud providers you want to fetch data from.
+In the case of Bitbucket Cloud, you will have up to one entry.
-- `host`: The host of the Bitbucket instance, e.g. `bitbucket.company.com`.
-- `token` (optional): An personal access token as expected by Bitbucket. Either
- an access token **or** a username + appPassword may be supplied.
-- `username` (optional): The Bitbucket username to use in API requests. If
+This one entry will have the following elements:
+
+- `username`: The Bitbucket Cloud username to use in API requests. If
neither a username nor token are supplied, anonymous access will be used.
-- `appPassword` (optional): The password for the Bitbucket user. Only needed
- when using `username` instead of `token`.
-- `apiBaseUrl` (optional): The URL of the Bitbucket API. For self-hosted
- installations, it is commonly at `https:///rest/api/1.0`. For
- bitbucket.org, this configuration is not needed as it can be inferred.
+- `appPassword`: The app password for the Bitbucket Cloud user.
-> Note: If you are using Bitbucket server you MUST set the username as well as
-> the token or appPassword.
+## Bitbucket Server
+
+```yaml
+integrations:
+ bitbucketServer:
+ - host: bitbucket.company.com
+ token: ${BITBUCKET_SERVER_TOKEN}
+```
+
+Directly under the `bitbucketServer` key is a list of provider configurations, where
+you can list the Bitbucket Server providers you want to fetch data from. Each entry is
+a structure with the following elements:
+
+- `host`: The host of the Bitbucket Server instance, e.g. `bitbucket.company.com`.
+- `token` (optional):
+ An [personal access token](https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html)
+ as expected by Bitbucket Server.
+- `apiBaseUrl` (optional): The URL of the Bitbucket Server API. For self-hosted
+ installations, it is commonly at `https:///rest/api/1.0`.
diff --git a/docs/integrations/gerrit/discovery.md b/docs/integrations/gerrit/discovery.md
new file mode 100644
index 0000000000..5cd1f6204b
--- /dev/null
+++ b/docs/integrations/gerrit/discovery.md
@@ -0,0 +1,69 @@
+---
+id: discovery
+title: Gerrit Discovery
+sidebar_label: Discovery
+# prettier-ignore
+description: Automatically discovering catalog entities from Gerrit repositories
+---
+
+The Gerrit integration has a special entity provider for discovering catalog entities
+from Gerrit repositories. The provider uses the "List Projects" API in Gerrit to get
+a list of repositories and will automatically ingest all `catalog-info.yaml` files
+stored in the root of the matching projects.
+
+## Installation
+
+As this provider is not one of the default providers, you will first need to install
+the Gerrit provider plugin:
+
+```bash
+# From the Backstage root directory
+yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-gerrit
+```
+
+Then add the plugin to the plugin catalog `packages/backend/src/plugins/catalog.ts`:
+
+```ts
+/* packages/backend/src/plugins/catalog.ts */
+import { GerritEntityProvider } from '@backstage/plugin-catalog-backend-module-gerrit';
+import { Duration } from 'luxon';
+const builder = await CatalogBuilder.create(env);
+/** ... other processors and/or providers ... */
+builder.addEntityProvider(
+ ...GerritEntityProvider.fromConfig(env.config, {
+ logger: env.logger,
+ schedule: env.scheduler.createScheduledTaskRunner({
+ frequency: Duration.fromObject({ minutes: 30 }),
+ timeout: Duration.fromObject({ minutes: 3 }),
+ }),
+ }),
+);
+```
+
+## Configuration
+
+To use the discovery processor, you'll need a Gerrit integration
+[set up](locations.md). Then you can add any number of providers.
+
+```yaml
+# app-config.yaml
+catalog:
+ providers:
+ gerrit:
+ yourProviderId: # identifies your dataset / provider independent of config changes
+ host: gerrit-your-company.com
+ branch: master # Optional
+ query: 'state=ACTIVE&prefix=webapps'
+ backend:
+ host: gerrit-your-company.com
+ branch: master # Optional
+ query: 'state=ACTIVE&prefix=backend'
+```
+
+The provider configuration is composed of three parts:
+
+- host, the host of the Gerrit integration to use.
+- branch, the branch where we will look for catalog entities (defaults to "master").
+- query, this string is directly used as the argument to the "List Project" API.
+ Typically you will want to have some filter here to exclude projects that will
+ never contain any catalog files.
diff --git a/docs/integrations/gerrit/locations.md b/docs/integrations/gerrit/locations.md
index 8091de3a2e..9bff2385e3 100644
--- a/docs/integrations/gerrit/locations.md
+++ b/docs/integrations/gerrit/locations.md
@@ -19,7 +19,8 @@ To use this integration, add at least one Gerrit configuration to your root `app
integrations:
gerrit:
- host: gerrit.company.com
- apiBaseUrl: https://gerrit.company.com/gerrit
+ baseUrl: https://gerrit.company.com/gerrit
+ cloneUrl: https://gerrit.company.com/clone
gitilesBaseUrl: https://gerrit.company.com/gitiles
username: ${GERRIT_USERNAME}
password: ${GERRIT_PASSWORD}
@@ -27,13 +28,15 @@ integrations:
Directly under the `gerrit` key is a list of provider configurations, where
you can list the Gerrit instances you want to fetch data from. Each entry is
-a structure with up to four elements:
+a structure with up to six elements:
- `host`: The host of the Gerrit instance, e.g. `gerrit.company.com`.
-- `apiBaseUrl` (optional): Needed if the Gerrit instance is not reachable at
+- `baseUrl` (optional): Needed if the Gerrit instance is not reachable at
the base of the `host` option (e.g. `https://gerrit.company.com`) set the
address here. This is the address that you would open in a browser.
-- `gitilesBaseUrl` (optional): This is needed for creating a valid user-friendly url
+- `cloneUrl` (optional): The base URL for HTTP clones. Will default to `baseUrl` if
+ not set. The address used to clone a repo is the `cloneUrl` plus the repo name.
+- `gitilesBaseUrl` (optional): This is needed for creating a valid user-friendly URL
that can be used for browsing the content of the provider. If not set a default
value will be created in the same way as the "baseUrl" option. There is no
requirement to have Gitiles for the Backstage Gerrit integration but without it
diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md
index 1cbf8905a2..a0c3fed153 100644
--- a/docs/integrations/github/discovery.md
+++ b/docs/integrations/github/discovery.md
@@ -60,8 +60,9 @@ And then add the processors to your catalog builder:
## Configuration
To use the discovery processor, you'll need a GitHub integration
-[set up](locations.md) with a `GITHUB_TOKEN`. Then you can add a location target
-to the catalog configuration:
+[set up](locations.md) with either a [Personal Access Token](../../getting-started/configuration.md#setting-up-a-github-integration) or [GitHub Apps](./github-apps.md).
+
+Then you can add a location target to the catalog configuration:
```yaml
catalog:
@@ -96,14 +97,12 @@ When using a custom pattern, the target is composed of three parts:
## GitHub API Rate Limits
-GitHub [rate limits] API requests to 5,000 per hour (or more for Enterprise
+GitHub [rate limits](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting) API requests to 5,000 per hour (or more for Enterprise
accounts). The default Backstage catalog backend refreshes data every 100
seconds, which issues an API request for each discovered location.
This means if you have more than ~140 catalog entities, you may get throttled by
-rate limiting. This will soon be resolved once catalog refreshes make use of
-ETags; to work around this in the meantime, you can change the refresh rate of
-the catalog in your `packages/backend/src/plugins/catalog.ts` file:
+rate limiting. You can change the refresh rate of the catalog in your `packages/backend/src/plugins/catalog.ts` file:
```typescript
const builder = await CatalogBuilder.create(env);
@@ -112,11 +111,8 @@ const builder = await CatalogBuilder.create(env);
builder.setProcessingIntervalSeconds(300);
```
-Alternatively, or additionally, you can configure [github-apps] authentication
+Alternatively, or additionally, you can configure [github-apps](github-apps.md) authentication
which carries a much higher rate limit at GitHub.
This is true for any method of adding GitHub entities to the catalog, but
especially easy to hit with automatic discovery.
-
-[rate limits]: https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting
-[github-apps]: ../../plugins/github-apps.md
diff --git a/docs/plugins/github-apps.md b/docs/integrations/github/github-apps.md
similarity index 92%
rename from docs/plugins/github-apps.md
rename to docs/integrations/github/github-apps.md
index 434c9a4882..5725e67c7b 100644
--- a/docs/plugins/github-apps.md
+++ b/docs/integrations/github/github-apps.md
@@ -1,6 +1,6 @@
---
id: github-apps
-title: GitHub Apps for Backend Authentication
+title: GitHub Apps
description: Configure GitHub Apps for Backend Authentication
---
@@ -13,6 +13,8 @@ the OAuth apps and their respective scopes.
## Caveats
+- This authentication method is built for authenticating towards
+ organization repositories and not towards personal repositories.
- It's not possible to have multiple Backstage GitHub Apps installed in the same
GitHub organization, to be handled by Backstage. We currently don't check
through all the registered GitHub Apps to see which ones are installed for a
@@ -25,7 +27,7 @@ the OAuth apps and their respective scopes.
want for github.com but it's recommended to make your application public for
GitHub Enterprise in order to share application across your GHE organizations.
-A GitHub app created with `backstage-cli create-github-app` will have read
+A GitHub app created with the cli will have read
access by default. You have to manually update the GitHub App settings in GitHub
to grant the app more permissions if needed.
@@ -35,8 +37,12 @@ You can use the `backstage-cli` to create a GitHub App using a manifest file
that we provide. This gives us a way to automate some of the work required to
create a GitHub app.
+```console
+yarn backstage-cli create-github-app
+```
+
You can read more about the
-[`backstage-cli create-github-app` method](../local-dev/cli-commands.md#create-github-app).
+[`backstage-cli create-github-app`](../../local-dev/cli-commands.md#create-github-app) command.
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
diff --git a/docs/integrations/github/locations.md b/docs/integrations/github/locations.md
index 3395c61117..7d3ce632d6 100644
--- a/docs/integrations/github/locations.md
+++ b/docs/integrations/github/locations.md
@@ -75,8 +75,6 @@ your use of the integration:
## Authentication with GitHub Apps
-Alternatively, Backstage can use GitHub Apps for backend authentication. This
-has higher rate limits, and a clearer authorization model. See [github-apps] for
+Alternatively for GitHub organizations, Backstage can use GitHub Apps for backend authentication. This
+has higher rate limits, and a clearer authorization model. See [github-apps](github-apps.md) for
how to set this up.
-
-[github-apps]: ../../plugins/github-apps.md
diff --git a/docs/integrations/google-cloud-storage/locations.md b/docs/integrations/google-cloud-storage/locations.md
index 16e19ea350..e15cb6346c 100644
--- a/docs/integrations/google-cloud-storage/locations.md
+++ b/docs/integrations/google-cloud-storage/locations.md
@@ -48,7 +48,7 @@ you can check [this documentation page][google gcs docs].
To use this integration to import entities from a GCS bucket go to the Google
console and browse the file you would like to import. Then copy the
`Authenticated URL` and paste it into the text box in the `register component`
-form. This url should look like
+form. This URL should look like
`https://storage.cloud.google.com///catalog-info.yaml`.
[google gcs docs]: https://cloud.google.com/docs/authentication/production#auth-cloud-implicit-nodejs
diff --git a/docs/local-dev/cli-commands.md b/docs/local-dev/cli-commands.md
index 7157fad2bf..715d586545 100644
--- a/docs/local-dev/cli-commands.md
+++ b/docs/local-dev/cli-commands.md
@@ -326,8 +326,9 @@ in the package registry, and will update entries both in `yarn.lock` and
Usage: backstage-cli versions:bump [options]
Options:
- -h, --help display help for command
- -p, --pattern Override glob for matching packages to upgrade
+ -h, --help display help for command
+ --pattern <glob> Override glob for matching packages to upgrade
+ --release <version|next|main> Bump to a specific Backstage release line or version (default: "main")
```
## versions:check
@@ -361,7 +362,7 @@ Usage: backstage-cli build-workspace [options] <workspace-dir>
Creates a GitHub App in your GitHub organization. This is an alternative to
token-based [GitHub integration](../integrations/github/locations.md). See
-[GitHub Apps for Backstage Authentication](../plugins/github-apps.md).
+[GitHub Apps for Backstage Authentication](../integrations/github/github-apps.md).
Launches a browser to create the App through GitHub and saves the result as a
YAML file that can be referenced in the GitHub integration configuration.
diff --git a/docs/plugins/url-reader.md b/docs/plugins/url-reader.md
index 0072c34cfb..8a84f3e1ff 100644
--- a/docs/plugins/url-reader.md
+++ b/docs/plugins/url-reader.md
@@ -24,7 +24,7 @@ package provides a dedicated API for reading from such URL based remote
locations like GitHub, GitLab, Bitbucket, Google Cloud Storage, etc. This is
commonly referred to as "URL Reader". It takes care of making authenticated
requests to the remote host so that private files can be read securely. If users
-have [GitHub App based authentication](github-apps.md) set up, URL Reader even
+have [GitHub App based authentication](../integrations/github/github-apps.md) set up, URL Reader even
refreshes the token, to avoid reaching the GitHub API rate limit.
As a result, plugin authors do not have to worry about any of these problems
diff --git a/docs/releases/v1.1.0-changelog.md b/docs/releases/v1.1.0-changelog.md
new file mode 100644
index 0000000000..270f90b0d3
--- /dev/null
+++ b/docs/releases/v1.1.0-changelog.md
@@ -0,0 +1,2703 @@
+# Release v1.1.0
+
+## @backstage/backend-tasks@0.3.0
+
+### Minor Changes
+
+- ab008a0988: Adds the ability to manually trigger tasks which are registered
+
+### Patch Changes
+
+- bdd2773202: Refactored the internal `TaskWorker` class to make it easier to test.
+
+- a83babdd63: Fixed the `initialDelay` parameter of tasks to properly make task workers
+ _always_ wait before the first invocations on startup, not just the very first
+ time that the task is ever created. This behavior is more in line with
+ expectations. Callers to not need to update their code.
+
+ Also clarified in the doc comment for the field that this wait applies only on
+ an individual worker level. That is, if you have a cluster of workers then each
+ individual machine may postpone its first task invocation by the given amount of
+ time to leave room for the service to settle, but _other_ workers may still
+ continue to invoke the task on the regular cadence in the meantime.
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+
+## @backstage/cli@0.17.0
+
+### Minor Changes
+
+- 1f7d4763ab: **BREAKING**: Bump the version range of `jest` from `^26.0.1` to `^27.5.1`. You can find the complete list of breaking changes [here](https://github.com/facebook/jest/releases/tag/v27.0.0).
+
+ We strongly recommend to have completed the [package role migration](https://backstage.io/docs/tutorials/package-role-migration) before upgrading to this version, as the package roles are used to automatically determine the testing environment for each package. If you instead want to set an explicit test environment for each package, you can do so for example in the `"jest"` section in `package.json`. The default test environment for all packages is now `node`, which is also the new Jest default.
+
+ Note that one of the breaking changes of Jest 27 is that the `jsdom` environment no longer includes `setImmediate` and `clearImmediate`, which means you might need to update some of your frontend packages. Another notable change is that `jest.useFakeTimers` now defaults to the `'modern'` implementation, which also mocks microtasks.
+
+### Patch Changes
+
+- e80ecad93c: Bump the `rushstack` api generator libraries to their latest versions
+
+- c54ce828bd: build(deps): bump `eslint-plugin-jest` from 25.3.4 to 26.1.2
+
+- f151dfee5a: build(deps): bump `eslint-webpack-plugin` from 2.6.0 to 3.1.1
+
+- 7e7ba704be: build(deps): bump `@spotify/eslint-config-base` from 12.0.0 to 13.0.0
+
+- ecd72391fb: build(deps): bump `@spotify/eslint-config-typescript`
+
+- 6a341b2d87: build(deps): bump `@spotify/eslint-config-react` from 12.0.0 to 13.0.0
+
+- 3c26b2edb5: build(deps): bump `npm-packlist` from 3.0.0 to 5.0.0
+
+- ed3551b7be: Introduced a new experimental test configuration with a number of changes. It switches the coverage provider from `v8` to the default Babel provider, along with always enabling source maps in the Sucrase transform. It also adds a custom module loader that caches both file transforms and VM script objects across all projects in a test run, which provides a big performance boost when running tests from the project root, increasing speed and reducing memory usage.
+
+ This new configuration is not enabled by default. It is enabled by setting the environment variable `BACKSTAGE_NEXT_TESTS` to a non-empty value.
+
+- 6ad0c45648: Added an experimental `package fix` command which applies automated fixes to the target package. The initial fix that is available is to add missing monorepo dependencies to the target package.
+
+- 5b3079694e: Stop logging "Stopped watcher" when shutting down the development backend.
+
+- f512554910: Updated the plugin template to install version 14 of `@testing-library/user-event`.
+
+ To apply this change to your own project, update the `devDependencies` section in your `package.json` files:
+
+ ```diff
+ "devDependencies": {
+ ... omitted dev dependencies ...
+ - "@testing-library/user-event": "^13.1.8",
+ + "@testing-library/user-event": "^14.0.0",
+ ... omitted dev dependencies ...
+ }
+ ```
+
+- df7862cfa6: Fixed a bug were the `react-hot-loader` transform was being applied to backend development builds.
+
+- 230ad0826f: Bump to using `@types/node` v16
+
+- c47509e1a0: Implemented changes suggested by Deepsource.io including multiple double non-null assertion operators and unexpected awaits for non-promise values.
+
+- 948a56f401: Added a new experimental `repo list-deprecations` command, which scans the entire project for usage of deprecated APIs.
+
+- 4782f9e925: Fixed misleading log message during frontend plugin creation.
+
+- 0383cd0228: The `versions:*` commands no longer warns about duplicate plugin libraries, such as `@backstage/plugin-catalog-common`.
+
+- Updated dependencies
+ - @backstage/config-loader@1.1.0
+
+## @backstage/config-loader@1.1.0
+
+### Minor Changes
+
+- 19f6c6c32a: Added `ignoreSchemaErrors` to `schema.process`.
+
+### Patch Changes
+
+- e0a51384ac: build(deps): bump `ajv` from 7.0.3 to 8.10.0
+- 230ad0826f: Bump to using `@types/node` v16
+- c47509e1a0: Implemented changes suggested by Deepsource.io including multiple double non-null assertion operators and unexpected awaits for non-promise values.
+
+## @backstage/integration@1.1.0
+
+### Minor Changes
+
+- b7436743cb: Gerrit integration: Added an optional configuration to set the Gitiles base url.
+
+### Patch Changes
+
+- 1691c6c5c2: Clarify that config locations that emit User and Group kinds now need to declare so in the `catalog.locations.[].rules`
+
+- 3ef123bbf0: Support external ID when assuming roles in S3 integration
+
+ In order to assume a role created by a 3rd party as external
+ ID is needed. This change adds an optional field to the s3
+ integration configuration and consumes that in the AwsS3UrlReader.
+
+- d26e1b0146: Exported `replaceGitLabUrlType` from package
+
+## @techdocs/cli@1.1.0
+
+### Minor Changes
+
+- 733187987b: Removed an undocumented, broken behavior where `README.md` files would be copied to `index.md` if it did not exist, leading to broken links in the TechDocs UI.
+
+ **WARNING**: If you notice 404s in TechDocs after updating, check to make sure that all markdown files referenced in your `mkdocs.yml`s' `nav` sections exist. The following flag may be passed to the `generate` command to temporarily revert to the broken behavior.
+
+ ```sh
+ techdocs-cli generate --legacyCopyReadmeMdToIndexMd
+ ```
+
+### Patch Changes
+
+- 230ad0826f: Bump to using `@types/node` v16
+- eb470ea54c: Adds a new flag to override the entrypoint when using a custom docker image. It could be used to reuse existing images with different entrypoints.
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-techdocs-node@1.1.0
+
+## @backstage/plugin-auth-backend@0.13.0
+
+### Minor Changes
+
+- 15d3a3c39a: **BREAKING**: All sign-in resolvers must now return a `token` in their sign-in result. Returning an `id` is no longer supported.
+- c5aeaf339d: **BREAKING**: All auth providers have had their default sign-in resolvers removed. This means that if you want to use a particular provider for sign-in, you must provide an explicit sign-in resolver. For more information on how to configure sign-in resolvers, see the [sign-in resolver documentation](https://backstage.io/docs/auth/identity-resolver).
+
+### Patch Changes
+
+- c5aeaf339d: **DEPRECATION**: The `AuthProviderFactoryOptions` type has been deprecated, as the options are now instead inlined in the `AuthProviderFactory` type. This will make it possible to more easily introduce new options in the future without a possibly breaking change.
+
+- 794f7542b6: Updated openid-client from 4.1.2 to 5.1.3
+
+- c5aeaf339d: **DEPRECATION**: The `getEntityClaims` helper has been deprecated, with `getDefaultOwnershipEntityRefs` being added to replace it.
+
+- de231e5b06: Declare oauth2 `clientSecret` with visibility secret
+
+- c5aeaf339d: **DEPRECATION**: All `createProvider` and `*SignInResolver` have been deprecated. Instead, a single `providers` object is exported which contains all built-in auth providers.
+
+ If you have a setup that currently looks for example like this:
+
+ ```ts
+ import {
+ createRouter,
+ defaultAuthProviderFactories,
+ createGoogleProvider,
+ googleEmailSignInResolver,
+ } from '@backstage/plugin-auth-backend';
+ import { Router } from 'express';
+ import { PluginEnvironment } from '../types';
+
+ export default async function createPlugin(
+ env: PluginEnvironment,
+ ): Promise {
+ return await createRouter({
+ ...env,
+ providerFactories: {
+ ...defaultAuthProviderFactories,
+ google: createGoogleProvider({
+ signIn: {
+ resolver: googleEmailSignInResolver,
+ },
+ }),
+ },
+ });
+ }
+ ```
+
+ You would migrate it to something like this:
+
+ ```ts
+ import {
+ createRouter,
+ providers,
+ defaultAuthProviderFactories,
+ } from '@backstage/plugin-auth-backend';
+ import { Router } from 'express';
+ import { PluginEnvironment } from '../types';
+
+ export default async function createPlugin(
+ env: PluginEnvironment,
+ ): Promise {
+ return await createRouter({
+ ...env,
+ providerFactories: {
+ ...defaultAuthProviderFactories,
+ google: providers.google.create({
+ signIn: {
+ resolver:
+ providers.google.resolvers.emailMatchingUserEntityAnnotation(),
+ },
+ }),
+ },
+ });
+ }
+ ```
+
+- 2cc1d1b235: Applied the fix from version 0.12.3 of this package, which is part of the v1.0.1 release of Backstage.
+
+- c5aeaf339d: **DEPRECATION** The `AuthResolverContext` has received a number of changes, which is the context used by auth handlers and sign-in resolvers.
+
+ The following fields deprecated: `logger`, `tokenIssuer`, `catalogIdentityClient`. If you need to access the `logger`, you can do so through a closure instead. The `tokenIssuer` has been replaced with an `issueToken` method, which is available directory on the context. The `catalogIdentityClient` has been replaced by the `signInWithCatalogUser` method, as well as the lower level `findCatalogUser` method and `getDefaultOwnershipEntityRefs` helper.
+
+ It should be possible to migrate most sign-in resolvers to more or less only use `signInWithCatalogUser`, for example an email lookup resolver like this one:
+
+ ```ts
+ async ({ profile }, ctx) => {
+ if (!profile.email) {
+ throw new Error('Profile contained no email');
+ }
+
+ const entity = await ctx.catalogIdentityClient.findUser({
+ annotations: {
+ 'acme.org/email': profile.email,
+ },
+ });
+
+ const claims = getEntityClaims(entity);
+ const token = await ctx.tokenIssuer.issueToken({ claims });
+
+ return { id: entity.metadata.name, entity, token };
+ };
+ ```
+
+ can be migrated to the following:
+
+ ```ts
+ async ({ profile }, ctx) => {
+ if (!profile.email) {
+ throw new Error('Profile contained no email');
+ }
+
+ return ctx.signInWithCatalogUser({
+ annotations: {
+ 'acme.org/email': profile.email,
+ },
+ });
+ };
+ ```
+
+ While a direct entity name lookup using a user ID might look like this:
+
+ ```ts
+ async ({ result: { fullProfile } }, ctx) => {
+ return ctx.signInWithCatalogUser({
+ entityRef: {
+ name: fullProfile.userId,
+ },
+ });
+ };
+ ```
+
+ If you want more control over the way that users are looked up, ownership is assigned, or tokens are issued, you can use a combination of the `findCatalogUser`, `getDefaultOwnershipEntityRefs`, and `issueToken` instead.
+
+- f4cdf4cac1: Defensively encode URL parameters when fetching ELB keys
+
+- 6ee04078e1: **DEPRECATION**: The `tokenIssuer` option for `OAuthAdapter` is no longer needed and has been deprecated.
+
+- a45bce06e3: Handle trailing slashes on GitHub `enterpriseInstanceUrl` settings
+
+- 45f7a261c7: Bumped passport-microsoft to resolve CVE-2021-41580
+
+- c5aeaf339d: Added exports of the following types: `AuthProviderConfig`, `StateEncoder`, `TokenParams`, `AwsAlbResult`.
+
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-auth-node@0.2.0
+ - @backstage/backend-common@0.13.2
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-auth-node@0.2.0
+
+### Minor Changes
+
+- 15d3a3c39a: **BREAKING**: Removed the deprecated `id` and `entity` fields from `BackstageSignInResult`.
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-catalog@1.1.0
+
+### Minor Changes
+
+- bdc61b4002: Expose 'initalFilter' through initialKind prop on Catalog Page.
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 2a3cac4c60: Corrected replacements for depreciated FilteredEntityLayout items
+- f6d2694092: Added tableOptions property to CatalogTable and DefaultCatalogPage to support customization of the Catalog Table. Related issue #10453
+- 5d5fdbe541: Columns in CatalogTable now change depending on the entity kind, ensuring only relevant columns are displayed.
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/integration-react@1.0.1
+ - @backstage/plugin-search-common@0.3.3
+ - @backstage/plugin-catalog-common@1.0.1
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-catalog-backend@1.1.0
+
+### Minor Changes
+
+- 8012ac46a0: **BREAKING (alpha api):** Replace `createCatalogPolicyDecision` export with `createCatalogConditionalDecision`, which accepts a permission parameter of type `ResourcePermission<'catalog-entity'>` along with conditions. The permission passed is expected to be the handled permission in `PermissionPolicy#handle`, whose type must first be narrowed using methods like `isPermission` and `isResourcePermission`:
+
+ ```typescript
+ class TestPermissionPolicy implements PermissionPolicy {
+ async handle(
+ request: PolicyQuery,
+ _user?: BackstageIdentityResponse,
+ ): Promise {
+ if (
+ // Narrow type of `request.permission` to `ResourcePermission<'catalog-entity'>
+ isResourcePermission(request.permission, RESOURCE_TYPE_CATALOG_ENTITY)
+ ) {
+ return createCatalogConditionalDecision(
+ request.permission,
+ catalogConditions.isEntityOwner(
+ _user?.identity.ownershipEntityRefs ?? [],
+ ),
+ );
+ }
+
+ return {
+ result: AuthorizeResult.ALLOW,
+ };
+ ```
+
+- 8012ac46a0: **BREAKING:** Mark CatalogBuilder#addPermissionRules as @alpha.
+
+- fb02d2d94d: export `locationSpecToLocationEntity`
+
+- bf82edf4c9: Added `/validate-entity` endpoint
+
+### Patch Changes
+
+- ada4446733: Specify type of `visibilityPermission` property on collators and collator factories.
+
+- 1691c6c5c2: Clarify that config locations that emit User and Group kinds now need to declare so in the `catalog.locations.[].rules`
+
+- 8592cacfd3: Fixed an issue where sometimes entities would have stale relations "stuck" and
+ not getting removed as expected, after the other end of the relation had stopped
+ referring to them.
+
+- 23646e51a5: Use new `PermissionEvaluator#authorizeConditional` method when retrieving permission conditions.
+
+- 9fe24b0fc8: Adjust the error messages when entities fail validation, to clearly state what entity that failed it
+
+- 48405ed232: Added `spec.profile.displayName` to search index for Group kinds
+
+- 95408dbe99: Enable internal batching of very large deletions, to not run into SQL binding limits
+
+- 8012ac46a0: Handle changes to @alpha permission-related types.
+
+ - All exported permission rules and conditions now have a `resourceType`.
+ - `createCatalogConditionalDecision` now expects supplied conditions to have the appropriate `resourceType`.
+ - `createCatalogPermissionRule` now expects `resourceType` as part of the supplied rule object.
+ - Introduce new `CatalogPermissionRule` convenience type.
+
+- ffec894ed0: add gitlab to AnnotateScmSlugEntityProcessor
+
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/plugin-permission-node@0.6.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-search-common@0.3.3
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-catalog-common@1.0.1
+ - @backstage/catalog-client@1.0.1
+ - @backstage/plugin-scaffolder-common@1.0.1
+
+## @backstage/plugin-cicd-statistics-module-gitlab@0.1.0
+
+### Minor Changes
+
+- d3af30b47d: Created a module to extract the CI/CD statistics from a Gitlab repository.
+ Read the `README.md` in the `cicd-statistics-module-gitlab` plugin folder on how to set it up.
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-cicd-statistics@0.1.6
+
+## @backstage/plugin-gcalendar@0.3.0
+
+### Minor Changes
+
+- c6616e6fc9: Fixed issue when not all calendars were fetched for some accounts
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-kubernetes-backend@0.5.0
+
+### Minor Changes
+
+- 3d45427666: **BREAKING** Custom cluster suppliers need to cache their getClusters result
+
+ To allow custom `KubernetesClustersSupplier` instances to refresh the list of clusters
+ the `getClusters` method is now called whenever the list of clusters is needed.
+
+ Existing `KubernetesClustersSupplier` implementations will need to ensure that `getClusters`
+ can be called frequently and should return a cached result from `getClusters` instead.
+
+ For example, here's a simple example of a custom supplier in `packages/backend/src/plugins/kubernetes.ts`:
+
+ ```diff
+ -import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';
+ +import {
+ + ClusterDetails,
+ + KubernetesBuilder,
+ + KubernetesClustersSupplier,
+ +} from '@backstage/plugin-kubernetes-backend';
+ import { Router } from 'express';
+ import { PluginEnvironment } from '../types';
+ +import { Duration } from 'luxon';
+ +
+ +export class CustomClustersSupplier implements KubernetesClustersSupplier {
+ + constructor(private clusterDetails: ClusterDetails[] = []) {}
+ +
+ + static create(refreshInterval: Duration) {
+ + const clusterSupplier = new CustomClustersSupplier();
+ + // setup refresh, e.g. using a copy of https://github.com/backstage/backstage/blob/master/plugins/search-backend-node/src/runPeriodically.ts
+ + runPeriodically(
+ + () => clusterSupplier.refreshClusters(),
+ + refreshInterval.toMillis(),
+ + );
+ + return clusterSupplier;
+ + }
+ +
+ + async refreshClusters(): Promise {
+ + this.clusterDetails = []; // fetch from somewhere
+ + }
+ +
+ + async getClusters(): Promise {
+ + return this.clusterDetails;
+ + }
+ +}
+
+ export default async function createPlugin(
+ env: PluginEnvironment,
+ ): Promise {
+ - const { router } = await KubernetesBuilder.createBuilder({
+ + const builder = await KubernetesBuilder.createBuilder({
+ logger: env.logger,
+ config: env.config,
+ - }).build();
+ + });
+ + builder.setClusterSupplier(
+ + CustomClustersSupplier.create(Duration.fromObject({ minutes: 60 })),
+ + );
+ + const { router } = await builder.build();
+ ```
+
+### Patch Changes
+
+- 753a20c89e: Add kubernetes namespace annotation `backstage.io/kubernetes-namespace` to allow namespaced Kubernetes resources fetches
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-kubernetes-common@0.2.9
+
+## @backstage/plugin-permission-common@0.6.0
+
+### Minor Changes
+
+- 8012ac46a0: Add `resourceType` property to `PermissionCondition` type to allow matching them with `ResourcePermission` instances.
+- c98d271466: Refactor api types into more specific, decoupled names.
+
+ - **BREAKING:**
+ - Renamed `AuthorizeDecision` to `EvaluatePermissionResponse`
+ - Renamed `AuthorizeQuery` to `EvaluatePermissionRequest`
+ - Renamed `AuthorizeRequest` to `EvaluatePermissionRequestBatch`
+ - Renamed `AuthorizeResponse` to `EvaluatePermissionResponseBatch`
+ - Renamed `Identified` to `IdentifiedPermissionMessage`
+ - Add `PermissionMessageBatch` helper type
+ - Add `ConditionalPolicyDecision`, `DefinitivePolicyDecision`, and `PolicyDecision` types from `@backstage/plugin-permission-node`
+
+### Patch Changes
+
+- 90754d4fa9: Removed [strict](https://github.com/colinhacks/zod#strict) validation from `PermissionCriteria` schemas to support backward-compatible changes.
+
+- 2b07063d77: Added `PermissionEvaluator`, which will replace the existing `PermissionAuthorizer` interface. This new interface provides stronger type safety and validation by splitting `PermissionAuthorizer.authorize()` into two methods:
+
+ - `authorize()`: Used when the caller requires a definitive decision.
+ - `authorizeConditional()`: Used when the caller can optimize the evaluation of any conditional decisions. For example, a plugin backend may want to use conditions in a database query instead of evaluating each resource in memory.
+
+- 8012ac46a0: Add `isPermission` helper method.
+
+- 95284162d6: - Add more specific `Permission` types.
+ - Add `createPermission` helper to infer the appropriate type for some permission input.
+ - Add `isResourcePermission` helper to refine Permissions to ResourcePermissions.
+
+## @backstage/plugin-permission-node@0.6.0
+
+### Minor Changes
+
+- 8012ac46a0: **BREAKING**: Stronger typing in `PermissionPolicy` 🎉.
+
+ Previously, it was entirely the responsibility of the `PermissionPolicy` author to only return `CONDITIONAL` decisions for permissions that are associated with a resource, and to return the correct kind of `PermissionCondition` instances inside the decision. Now, the policy authoring helpers provided in this package now ensure that the decision and permission match.
+
+ **For policy authors**: rename and adjust api of `createConditionExports`. Previously, the function returned a factory for creating conditional decisions named `createPolicyDecision`, which had a couple of drawbacks:
+
+ 1. The function always creates a _conditional_ policy decision, but this was not reflected in the name.
+ 2. Conditional decisions should only ever be returned from `PermissionPolicy#handle` for resource permissions, but there was nothing in the API that encoded this constraint.
+
+ This change addresses the drawbacks above by making the following changes for policy authors:
+
+ - The `createPolicyDecision` method has been renamed to `createConditionalDecision`.
+ - Along with conditions, the method now accepts a permission, which must be a `ResourcePermission`. This is expected to be the handled permission in `PermissionPolicy#handle`, whose type must first be narrowed using methods like `isPermission` and `isResourcePermission`:
+
+ ```typescript
+ class TestPermissionPolicy implements PermissionPolicy {
+ async handle(
+ request: PolicyQuery,
+ _user?: BackstageIdentityResponse,
+ ): Promise {
+ if (
+ // Narrow type of `request.permission` to `ResourcePermission<'catalog-entity'>
+ isResourcePermission(request.permission, RESOURCE_TYPE_CATALOG_ENTITY)
+ ) {
+ return createCatalogConditionalDecision(
+ request.permission,
+ catalogConditions.isEntityOwner(
+ _user?.identity.ownershipEntityRefs ?? [],
+ ),
+ );
+ }
+
+ return {
+ result: AuthorizeResult.ALLOW,
+ };
+ ```
+
+ **BREAKING**: when creating `PermissionRule`s, provide a `resourceType`.
+
+ ```diff
+ export const isEntityOwner = createCatalogPermissionRule({
+ name: 'IS_ENTITY_OWNER',
+ description: 'Allow entities owned by the current user',
+ + resourceType: RESOURCE_TYPE_CATALOG_ENTITY,
+ apply: (resource: Entity, claims: string[]) => {
+ if (!resource.relations) {
+ return false;
+ }
+
+ return resource.relations
+ .filter(relation => relation.type === RELATION_OWNED_BY)
+ .some(relation => claims.includes(relation.targetRef));
+ },
+ toQuery: (claims: string[]) => ({
+ key: 'relations.ownedBy',
+ values: claims,
+ }),
+ });
+ ```
+
+- c98d271466: **BREAKING:**
+
+ - Rename `PolicyAuthorizeQuery` to `PolicyQuery`
+ - Remove `PolicyDecision`, `DefinitivePolicyDecision`, and `ConditionalPolicyDecision`. These types are now exported from `@backstage/plugin-permission-common`
+
+- 322b69e46a: **BREAKING:** `ServerPermissionClient` now implements `PermissionEvaluator`, which moves out the capabilities for evaluating conditional decisions from `authorize()` to `authorizeConditional()` method.
+
+### Patch Changes
+
+- 90754d4fa9: Removed [strict](https://github.com/colinhacks/zod#strict) validation from `PermissionCriteria` schemas to support backward-compatible changes.
+- 8012ac46a0: Fix signature of permission rule in test suites
+- Updated dependencies
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/plugin-auth-node@0.2.0
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-permission-react@0.4.0
+
+### Minor Changes
+
+- 5bdcb8c45d: **BREAKING**: More restrictive typing for `usePermission` hook and `PermissionedRoute` component. It's no longer possible to pass a `resourceRef` unless the permission is of type `ResourcePermission`.
+
+### Patch Changes
+
+- c98d271466: Use updated types from `@backstage/plugin-permission-common`
+- 322b69e46a: **BREAKING:** Make `IdentityPermissionApi#authorize` typing more strict, using `AuthorizePermissionRequest` and `AuthorizePermissionResponse`.
+- Updated dependencies
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-scaffolder@1.1.0
+
+### Minor Changes
+
+- 6331ec1ebc: Added a context menu to the scaffolder page that provides links to the template editor and actions reference. These links and the presence of the context menu can be toggled through the `contextMenu` prop of the scaffolder page.
+- 8fad3b6ef5: The Template Preview page has been renamed to Template Editor, and is not available at the `/edit` path instead. There is a redirect in place from `/preview`.
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 946af407db: Changed input label for owner field in GitlabRepoPicker
+- 230ad0826f: Bump to using `@types/node` v16
+- d34900af81: Added a new `NextScaffolderRouter` which will eventually replace the exiting router
+- 9975ff9852: Applied the fix from version 1.0.1 of this package, which is part of the v1.0.2 release of Backstage.
+- 4431873583: Update `usePermission` usage.
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-permission-react@0.4.0
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/integration-react@1.0.1
+ - @backstage/plugin-catalog-common@1.0.1
+ - @backstage/catalog-client@1.0.1
+ - @backstage/plugin-scaffolder-common@1.0.1
+
+## @backstage/plugin-scaffolder-backend@1.1.0
+
+### Minor Changes
+
+- 2a7d52ca2c: Override default commit message and author details in GitLab action
+- f5f921dafb: Add new `draft` option to the `publish:github:pull-request` action.
+
+### Patch Changes
+
+- 64d9a031a8: build(deps): bump `isbinaryfile` from 4.0.8 to 5.0.0
+- 2f3d3a1eae: build(deps): bump `@gitbeaker/core` from 34.6.0 to 35.6.0
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+ - @backstage/catalog-client@1.0.1
+ - @backstage/plugin-scaffolder-common@1.0.1
+
+## @backstage/plugin-search@0.8.0
+
+### Minor Changes
+
+- 520e21aaea: The following exports has now been fully deleted from this package and can be import from `@backstage/plugin-search-react` instead.
+
+ `SearchApi` interface.
+ `searchApiRef`
+ `SearchContextProvider`
+ `useSearch`
+
+ `SearchContext` has now been fully deleted from this package and is no longer exported publicly. Use `SearchContextProvider` when access to the context is needed.
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+
+- 5c062f275e: Support customizing the content of the `SidebarSearchModal`
+
+- 38e01f2f70: Switch to `SearchDocument` type in `DefaultResultListItem` props
+
+- 230ad0826f: Bump to using `@types/node` v16
+
+- ab230a433f: The following exports has been moved to `@backstage/plugin-search-react` and will be removed in the next release. import from `@backstage/plugin-search-react` instead.
+
+ - `SearchApi` interface.
+ - `searchApiRef`
+ - `SearchContext`
+ - `SearchContextProvider`
+ - `useSearch`
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-search-react@0.1.0
+ - @backstage/plugin-search-common@0.3.3
+
+## @backstage/plugin-search-backend@0.5.0
+
+### Minor Changes
+
+- 94ccd772d4: **BREAKING**: The `authorization` property is no longer returned on search results when queried. Note: this will only result in a breaking change if you have custom code in your frontend that relies on the `authorization.resourceRef` property on documents.
+
+### Patch Changes
+
+- 30f9884359: Check for non-resource permissions when authorizing result-by-result in AuthorizedSearchEngine.
+- 3c8cfaaa80: Use `PermissionEvaluator` instead of `PermissionAuthorizer`, which is now deprecated.
+- 62ee65422c: Use new `IndexableResultSet` type as return type of query method in `SearchEngine` implementation.
+- c98d271466: Use updated types from `@backstage/plugin-permission-common`
+- Updated dependencies
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/plugin-permission-node@0.6.0
+ - @backstage/plugin-auth-node@0.2.0
+ - @backstage/plugin-search-common@0.3.3
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-search-backend-node@0.6.0
+
+## @backstage/plugin-search-backend-node@0.6.0
+
+### Minor Changes
+
+- 0a63e99a26: **BREAKING**: `IndexBuilder.addCollator()` now requires a `schedule` parameter (replacing `defaultRefreshIntervalSeconds`) which is expected to be a `TaskRunner` that is configured with the desired search indexing schedule for the given collator.
+
+ `Scheduler.addToSchedule()` now takes a new parameter object (`ScheduleTaskParameters`) with two new options `id` and `scheduledRunner` in addition to the migrated `task` argument.
+
+ NOTE: The search backend plugin now creates a dedicated database for coordinating indexing tasks.
+
+ To make this change to an existing app, make the following changes to `packages/backend/src/plugins/search.ts`:
+
+ ```diff
+ +import { Duration } from 'luxon';
+
+ /* ... */
+
+ + const schedule = env.scheduler.createScheduledTaskRunner({
+ + frequency: Duration.fromObject({ minutes: 10 }),
+ + timeout: Duration.fromObject({ minutes: 15 }),
+ + initialDelay: Duration.fromObject({ seconds: 3 }),
+ + });
+
+ indexBuilder.addCollator({
+ - defaultRefreshIntervalSeconds: 600,
+ + schedule,
+ factory: DefaultCatalogCollatorFactory.fromConfig(env.config, {
+ discovery: env.discovery,
+ tokenManager: env.tokenManager,
+ }),
+ });
+
+ indexBuilder.addCollator({
+ - defaultRefreshIntervalSeconds: 600,
+ + schedule,
+ factory: DefaultTechDocsCollatorFactory.fromConfig(env.config, {
+ discovery: env.discovery,
+ tokenManager: env.tokenManager,
+ }),
+ });
+
+ const { scheduler } = await indexBuilder.build();
+ - setTimeout(() => scheduler.start(), 3000);
+ + scheduler.start();
+ /* ... */
+ ```
+
+ NOTE: For scenarios where the `lunr` search engine is used in a multi-node configuration, a non-distributed `TaskRunner` like the following should be implemented to ensure consistency across nodes (alternatively, you can configure
+ the search plugin to use a non-distributed DB such as [SQLite](https://backstage.io/docs/tutorials/configuring-plugin-databases#postgresql-and-sqlite-3)):
+
+ ```diff
+ +import { TaskInvocationDefinition, TaskRunner } from '@backstage/backend-tasks';
+
+ /* ... */
+
+ + const schedule: TaskRunner = {
+ + run: async (task: TaskInvocationDefinition) => {
+ + const startRefresh = async () => {
+ + while (!task.signal?.aborted) {
+ + try {
+ + await task.fn(task.signal);
+ + } catch {
+ + // ignore intentionally
+ + }
+ +
+ + await new Promise(resolve => setTimeout(resolve, 600 * 1000));
+ + }
+ + };
+ + startRefresh();
+ + },
+ + };
+
+ indexBuilder.addCollator({
+ - defaultRefreshIntervalSeconds: 600,
+ + schedule,
+ factory: DefaultCatalogCollatorFactory.fromConfig(env.config, {
+ discovery: env.discovery,
+ tokenManager: env.tokenManager,
+ }),
+ });
+
+ /* ... */
+ ```
+
+### Patch Changes
+
+- 62ee65422c: Use new `IndexableResultSet` type as return type of query method in `SearchEngine` implementation.
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/backend-tasks@0.3.0
+ - @backstage/plugin-search-common@0.3.3
+
+## @backstage/plugin-search-react@0.1.0
+
+### Minor Changes
+
+- ab230a433f: New search package to hold things the search plugin itself and other frontend plugins (e.g. techdocs, home) depend on.
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+
+- 076b091113: api-report clean up - the package now exports following additional types:
+
+ `SearchContextProviderProps`
+ `SearchContextValue`
+ `SearchContextProviderForStorybookProps`
+ `SearchApiProviderForStorybookProps`
+
+- e1de8526aa: Versioned search context managed through version-bridge
+
+- Updated dependencies
+ - @backstage/core-app-api@1.0.1
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/version-bridge@1.0.1
+ - @backstage/plugin-search-common@0.3.3
+
+## @backstage/plugin-stack-overflow@0.1.0
+
+### Minor Changes
+
+- ac323de4ad: Add stack overflow plugin
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-home@0.4.20
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-search-common@0.3.3
+
+## @backstage/plugin-stack-overflow-backend@0.1.0
+
+### Minor Changes
+
+- ac323de4ad: Add stack overflow backend plugin
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-search-common@0.3.3
+
+## @backstage/plugin-tech-insights@0.2.0
+
+### Minor Changes
+
+- 567b13a84a: Add checksId option to EntityTechInsightsScorecardContent component
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+
+- 230ad0826f: Bump to using `@types/node` v16
+
+- 2fe58c7285: Improved the Tech-Insights documentation:
+
+ - `lifecycle` examples used `ttl` when it should be `timeToLive`
+ - Added list of included FactRetrievers
+ - Added full backend example using all included FactRetrievers
+ - Added boolean scorecard example image showing results of backend example
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-tech-insights-backend@0.3.0
+
+### Minor Changes
+
+- 231fee736b: This backend now uses the `@backstage/backend-tasks` package facilities for scheduling fact retrievers.
+
+ **BREAKING**: The `buildTechInsightsContext` function now takes an additional field in its options argument: `scheduler`. This is an instance of `PluginTaskScheduler`, which can be found in your backend initialization code's `env`.
+
+ ```diff
+ const builder = buildTechInsightsContext({
+ logger: env.logger,
+ config: env.config,
+ database: env.database,
+ discovery: env.discovery,
+ + scheduler: env.scheduler,
+ factRetrievers: [ /* ... */ ],
+ });
+ ```
+
+### Patch Changes
+
+- 21de525ce9: Updated README.md with better install instructions
+
+- c47509e1a0: Implemented changes suggested by Deepsource.io including multiple double non-null assertion operators and unexpected awaits for non-promise values.
+
+- 2fe58c7285: Improved the Tech-Insights documentation:
+
+ - `lifecycle` examples used `ttl` when it should be `timeToLive`
+ - Added list of included FactRetrievers
+ - Added full backend example using all included FactRetrievers
+ - Added boolean scorecard example image showing results of backend example
+
+- Updated dependencies
+ - @backstage/backend-tasks@0.3.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-tech-insights-node@0.2.9
+ - @backstage/backend-common@0.13.2
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-techdocs@1.1.0
+
+### Minor Changes
+
+- ace749b785: TechDocs supports a new, experimental method of customization: addons!
+
+ To customize the standalone TechDocs reader page experience, update your `/packages/app/src/App.tsx` in the following way:
+
+ ```diff
+ import { TechDocsIndexPage, TechDocsReaderPage } from '@backstage/plugin-techdocs';
+ + import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
+ + import { SomeAddon } from '@backstage/plugin-some-plugin';
+
+ // ...
+
+ } />
+ }
+ >
+ +
+ +
+ +
+
+
+ // ...
+ ```
+
+ To customize the TechDocs reader experience on the Catalog entity page, update your `packages/app/src/components/catalog/EntityPage.tsx` in the following way:
+
+ ```diff
+ import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
+ + import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
+ + import { SomeAddon } from '@backstage/plugin-some-plugin';
+
+ // ...
+
+
+
+ {overviewContent}
+
+
+
+ -
+ +
+ +
+ +
+ +
+ +
+
+
+
+ // ...
+ ```
+
+ If you do not wish to customize your TechDocs reader experience in this way at this time, no changes are necessary!
+
+### Patch Changes
+
+- ab230a433f: imports from `@backstage/plugin-search-react` instead of `@backstage/plugin-search`
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+
+- 230ad0826f: Bump to using `@types/node` v16
+
+- f0fb9153b7: Fix broken query selectors on techdocs
+
+- 9975ff9852: Applied the fix from version 1.0.1 of this package, which is part of the v1.0.2 release of Backstage.
+
+- 3ba256c389: Fixed a bug preventing custom TechDocs reader page implementations from rendering without being double-wrapped in the `` component.
+
+- fe53fe97d7: Fix permalink scrolling for anchors where the id starts with a number.
+
+- 0152c0de22: Some documentation layout tweaks:
+
+ - drawer toggle margins
+ - code block margins
+ - sidebar drawer width
+ - inner content width
+ - footer link width
+ - sidebar table of contents scroll
+
+- 3ba256c389: Fixed a bug that caused addons in the `Subheader` location to break the default TechDocs reader page layout.
+
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-app-api@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-search-react@0.1.0
+ - @backstage/plugin-techdocs-react@0.1.0
+ - @backstage/integration-react@1.0.1
+
+## @backstage/plugin-techdocs-backend@1.1.0
+
+### Minor Changes
+
+- 733187987b: Removed an undocumented, broken behavior where `README.md` files would be copied to `index.md` if it did not exist, leading to broken links in the TechDocs UI.
+
+ **WARNING**: If you notice 404s in TechDocs after updating, check to make sure that all markdown files referenced in your `mkdocs.yml`s' `nav` sections exist. The following configuration may be used to temporarily revert to the broken behavior.
+
+ ```yaml
+ techdocs:
+ generator:
+ mkdocs:
+ legacyCopyReadmeMdToIndexMd: true
+ ```
+
+### Patch Changes
+
+- ada4446733: Specify type of `visibilityPermission` property on collators and collator factories.
+- 7762d54200: Fixed a bug affecting those with cache enabled that would result in empty content being cached if the first attempt to load a static asset from storage were made via a `HEAD` request, rather than a `GET` request.
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-search-common@0.3.3
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-catalog-common@1.0.1
+ - @backstage/plugin-techdocs-node@1.1.0
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-techdocs-node@1.1.0
+
+### Minor Changes
+
+- bcf1a2496c: Removed an undocumented, broken behavior where `README.md` files would be copied to `index.md` if it did not exist, leading to broken links in the TechDocs UI.
+
+### Patch Changes
+
+- 9fa68705bf: The default container version used to generate TechDocs content is now `v1.0.2`.
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-search-common@0.3.3
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-techdocs-react@0.1.0
+
+### Minor Changes
+
+- ff1cc8bced: This package will house frontend utilities related to TechDocs to be shared across other frontend Backstage packages.
+
+ In this release, it introduces a framework that can be used create TechDocs addons.
+
+ Note: this package is not necessarily stable yet. After iteration on this package, its stability will be signaled by a major-version bump.
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/version-bridge@1.0.1
+
+## @backstage/app-defaults@1.0.1
+
+### Patch Changes
+
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-permission-react@0.4.0
+ - @backstage/core-app-api@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/backend-common@0.13.2
+
+### Patch Changes
+
+- 19f6c6c32a: The backend will no longer fail to start up when configured secrets do not match the configuration schema.
+
+- b7436743cb: Added the GerritUrlReader that implements "readUrl".
+
+- 3ef123bbf0: Support external ID when assuming roles in S3 integration
+
+ In order to assume a role created by a 3rd party as external
+ ID is needed. This change adds an optional field to the s3
+ integration configuration and consumes that in the AwsS3UrlReader.
+
+- bae9359032: The logger returned from `getVoidLogger` is now uses a silenced console transport instead.
+
+- 3ff0e79654: Tweaked the `UrlReader` multiplexer so that it uses the more helpful `NotAllowedError` messaging for all methods.
+
+- 12608f8ba8: Add `@types/webpack-env` to dependencies.
+
+- f9f512559b: Updated the visibility of database connection fields in config to be secret
+
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/config-loader@1.1.0
+
+## @backstage/backend-test-utils@0.1.23
+
+### Patch Changes
+
+- 0654c87cf2: `TestDatabases.create` will no longer set up an `afterAll` test handler if no databases are supported.
+- Updated dependencies
+ - @backstage/cli@0.17.0
+ - @backstage/backend-common@0.13.2
+
+## @backstage/catalog-client@1.0.1
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+
+## @backstage/catalog-model@1.0.1
+
+### Patch Changes
+
+- e0a51384ac: build(deps): bump `ajv` from 7.0.3 to 8.10.0
+- c12f8374d1: Added a connection between www-artist and artist-lookup components
+
+
+ Screenshots
+
+ 
+
+ 
+
+
+
+## @backstage/codemods@0.1.37
+
+### Patch Changes
+
+- 230ad0826f: Bump to using `@types/node` v16
+
+## @backstage/core-app-api@1.0.1
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 3ff2bfb66e: Refactored the route collection logic to prepare for future changes and avoid duplicate element tree traversal for the analytics context.
+- a7bb762dab: fixed empty body issue for POST requests using FetchAPI with 'plugin://' prefix
+- 230ad0826f: Bump to using `@types/node` v16
+- c47509e1a0: Implemented changes suggested by Deepsource.io including multiple double non-null assertion operators and unexpected awaits for non-promise values.
+- Updated dependencies
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/version-bridge@1.0.1
+
+## @backstage/core-components@0.9.3
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 25b8e8d5b5: Add BackstageTab to overridableComponents so can override styles in a theme
+- 230ad0826f: Bump to using `@types/node` v16
+- 41fd107189: Exported `IdentityProviders` type.
+- a13604b8f7: Adding a name to the core-components Tab styles so can customise in the theme settings
+- 19648d5cf5: fix support config ref to use backstage/backstage
+- d505e43ffc: Fix highlighting of active sidebar items.
+- 72f3dfd05a: Updated ProxiedSignInPageProps docs
+- 7741e47eae: `` now accepts additional props `sidebarOptions` and `submenuOptions` to allow further customization
+- Updated dependencies
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/core-plugin-api@1.0.1
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/version-bridge@1.0.1
+
+## @backstage/create-app@0.4.26
+
+### Patch Changes
+
+- 1691c6c5c2: Made `User` and `Group` entity kinds not permitted by the default
+ `catalog.rules` config.
+
+ The effect of this is that after creating a new Backstage repository, its
+ catalog no longer permits regular users to register `User` or `Group` entities
+ using the Backstage interface. Additionally, if you have config locations that
+ result in `User` or `Group` entities, you need to add those kinds to its own
+ specific rules:
+
+ ```yaml
+ catalog:
+ locations:
+ # This applies for example to url type locations
+ - type: url
+ target: https://example.com/org.yaml
+ rules:
+ - allow: [User, Group]
+ # But also note that this applies to ALL org location types!
+ - type: github-org
+ target: https://github.com/my-org-name
+ rules:
+ - allow: [User, Group]
+ ```
+
+ This rule change does NOT affect entity providers, only things that are emitted
+ by entity processors.
+
+ We recommend that this change is applied to your own Backstage repository, since
+ it makes it impossible for regular end users to affect your org data through
+ e.g. YAML files. To do so, remove the two kinds from the default rules in your config:
+
+ ```diff
+ catalog:
+ rules:
+ - - allow: [Component, System, API, Group, User, Resource, Location]
+ + - allow: [Component, System, API, Resource, Location]
+ ```
+
+ And for any location that in any way results in org data being ingested, add the corresponding rule to it:
+
+ ```diff
+ catalog:
+ locations:
+ - type: github-org
+ target: https://github.com/my-org-name
+ + rules:
+ + - allow: [User, Group]
+ ```
+
+- 0e911394d2: Remove the `knex` package that is installed in the `packages/backend` as it's provided by the `@backstage/*` packages for you automatically. You can make the following change in your `packages/backend/package.json` if you wish to apply this change.
+
+ ```diff
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "clean": "backstage-cli package clean",
+ - "migrate:create": "knex migrate:make -x ts"
+ ```
+
+ ```diff
+ "express": "^4.17.1",
+ "express-promise-router": "^4.1.0",
+ - "knex": "^0.21.6",
+ "pg": "^8.3.0",
+ ```
+
+- 520e21aaea: imports `useSearch` hook from new `@backstage/plugin-search-react` package.
+
+ To upgrade existing Apps:
+
+ 1. Change the import to the following:
+
+ `packages/app/src/components/search/SearchPage.tsx`
+
+ ```diff
+ import {
+ ...
+ SearchType,
+ - useSearch,
+ } from '@backstage/plugin-search';
+ +import { useSearch } from '@backstage/plugin-search-react';
+ ```
+
+ 2. Add `@backstage/plugin-search-react` as a dependency to the app.
+
+- 43759dd789: Removed `@octokit/rest` and `@gitbeaker/node` from backend dependencies as these are unused in the default app.
+
+ To apply these changes to your existing app, remove the following lines from the `dependencies` section of `packages/backend/package.json`
+
+ ```diff
+ "@backstage/plugin-techdocs-backend": "^1.0.0",
+ - "@gitbeaker/node": "^34.6.0",
+ - "@octokit/rest": "^18.5.3",
+ ```
+
+- e838a7060a: Add type resolutions for `@types/react` and `types/react-dom`.
+
+ The reason for this is the usage of `"@types/react": "*"` as a dependency which is very common practice in react packages. This recently resolves to react 18 which introduces several breaking changes in both internal and external packages.
+
+ To apply these changes to your existing installation, add a resolutions block to your `package.json`
+
+ ```json
+ "resolutions": {
+ "@types/react": "^17",
+ "@types/react-dom": "^17"
+ },
+ ```
+
+ If your existing app depends on react 16, use this resolution block instead.
+
+ ```json
+ "resolutions": {
+ "@types/react": "^16",
+ "@types/react-dom": "^16"
+ },
+ ```
+
+- 0a63e99a26: **BREAKING**: `IndexBuilder.addCollator()` now requires a `schedule` parameter (replacing `defaultRefreshIntervalSeconds`) which is expected to be a `TaskRunner` that is configured with the desired search indexing schedule for the given collator.
+
+ `Scheduler.addToSchedule()` now takes a new parameter object (`ScheduleTaskParameters`) with two new options `id` and `scheduledRunner` in addition to the migrated `task` argument.
+
+ NOTE: The search backend plugin now creates a dedicated database for coordinating indexing tasks.
+
+ To make this change to an existing app, make the following changes to `packages/backend/src/plugins/search.ts`:
+
+ ```diff
+ +import { Duration } from 'luxon';
+
+ /* ... */
+
+ + const schedule = env.scheduler.createScheduledTaskRunner({
+ + frequency: Duration.fromObject({ minutes: 10 }),
+ + timeout: Duration.fromObject({ minutes: 15 }),
+ + initialDelay: Duration.fromObject({ seconds: 3 }),
+ + });
+
+ indexBuilder.addCollator({
+ - defaultRefreshIntervalSeconds: 600,
+ + schedule,
+ factory: DefaultCatalogCollatorFactory.fromConfig(env.config, {
+ discovery: env.discovery,
+ tokenManager: env.tokenManager,
+ }),
+ });
+
+ indexBuilder.addCollator({
+ - defaultRefreshIntervalSeconds: 600,
+ + schedule,
+ factory: DefaultTechDocsCollatorFactory.fromConfig(env.config, {
+ discovery: env.discovery,
+ tokenManager: env.tokenManager,
+ }),
+ });
+
+ const { scheduler } = await indexBuilder.build();
+ - setTimeout(() => scheduler.start(), 3000);
+ + scheduler.start();
+ /* ... */
+ ```
+
+ NOTE: For scenarios where the `lunr` search engine is used in a multi-node configuration, a non-distributed `TaskRunner` like the following should be implemented to ensure consistency across nodes (alternatively, you can configure
+ the search plugin to use a non-distributed DB such as [SQLite](https://backstage.io/docs/tutorials/configuring-plugin-databases#postgresql-and-sqlite-3)):
+
+ ```diff
+ +import { TaskInvocationDefinition, TaskRunner } from '@backstage/backend-tasks';
+
+ /* ... */
+
+ + const schedule: TaskRunner = {
+ + run: async (task: TaskInvocationDefinition) => {
+ + const startRefresh = async () => {
+ + while (!task.signal?.aborted) {
+ + try {
+ + await task.fn(task.signal);
+ + } catch {
+ + // ignore intentionally
+ + }
+ +
+ + await new Promise(resolve => setTimeout(resolve, 600 * 1000));
+ + }
+ + };
+ + startRefresh();
+ + },
+ + };
+
+ indexBuilder.addCollator({
+ - defaultRefreshIntervalSeconds: 600,
+ + schedule,
+ factory: DefaultCatalogCollatorFactory.fromConfig(env.config, {
+ discovery: env.discovery,
+ tokenManager: env.tokenManager,
+ }),
+ });
+
+ /* ... */
+ ```
+
+- c07d9f9e1c: Add helpful README.md files in the original `packages` and `plugins` folders
+
+- 230ad0826f: Bump to using `@types/node` v16
+
+- 1882dbda2b: Accept `PermissionEvaluator` instead of the deprecated `PermissionAuthorizer`.
+
+ Apply the following to `packages/backend/src/types.ts`:
+
+ ```diff
+ - import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
+ + import { PermissionEvaluator } from '@backstage/plugin-permission-common';
+
+ export type PluginEnvironment = {
+ ...
+ discovery: PluginEndpointDiscovery;
+ tokenManager: TokenManager;
+ scheduler: PluginTaskScheduler;
+ - permissions: PermissionAuthorizer;
+ + permissions: PermissionEvaluator;
+ };
+ ```
+
+- e80cca164d: Tweaked `.eslintrc.js` files in the template to avoid having them apply during development. This change does not affect create apps.
+
+## @backstage/dev-utils@1.0.1
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-app-api@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/integration-react@1.0.1
+ - @backstage/test-utils@1.0.1
+ - @backstage/app-defaults@1.0.1
+
+## @backstage/integration-react@1.0.1
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/search-common@0.3.3
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-search-common@0.3.3
+
+## @backstage/techdocs-common@0.11.14
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-techdocs-node@1.1.0
+
+## @backstage/test-utils@1.0.1
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- c98d271466: Use updated types from `@backstage/plugin-permission-common`
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-permission-react@0.4.0
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/core-app-api@1.0.1
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/version-bridge@1.0.1
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+
+## @backstage/plugin-airbrake@0.3.4
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/dev-utils@1.0.1
+ - @backstage/test-utils@1.0.1
+
+## @backstage/plugin-airbrake-backend@0.2.4
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-allure@0.1.20
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-analytics-module-ga@0.1.15
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-apache-airflow@0.1.12
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-api-docs@0.8.4
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- ae321bd414: build(deps): bump `@asyncapi/react-component`
+- 230ad0826f: Bump to using `@types/node` v16
+- 1c8ebf7af2: Add dedicated gRPC api definition widget
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-catalog@1.1.0
+
+## @backstage/plugin-app-backend@0.3.31
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/config-loader@1.1.0
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-azure-devops@0.1.20
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-azure-devops-backend@0.3.10
+
+### Patch Changes
+
+- 236245d9f8: Stop loading all teams when plugin is initialized
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-badges@0.2.28
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-badges-backend@0.1.25
+
+### Patch Changes
+
+- 4c93fd36ee: allow overriding `DefaultBadgeBuilder.getMarkdownCode`
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-bazaar@0.1.19
+
+### Patch Changes
+
+- 69738379c7: Pass authorization header with Backstage token to backend requests.
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/cli@0.17.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-catalog@1.1.0
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-bazaar-backend@0.1.15
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+ - @backstage/backend-test-utils@0.1.23
+
+## @backstage/plugin-bitrise@0.1.31
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-catalog-backend-module-aws@0.1.4
+
+### Patch Changes
+
+- 5969c4b65c: Add a new provider `AwsS3EntityProvider` as replacement for `AwsS3DiscoveryProcessor`.
+
+ In order to migrate from the `AwsS3DiscoveryProcessor` you need to apply
+ the following changes:
+
+ **Before:**
+
+ ```yaml
+ # app-config.yaml
+
+ catalog:
+ locations:
+ - type: s3-discovery
+ target: https://sample-bucket.s3.us-east-2.amazonaws.com/prefix/
+ ```
+
+ ```ts
+ /* packages/backend/src/plugins/catalog.ts */
+
+ import { AwsS3DiscoveryProcessor } from '@backstage/plugin-catalog-backend-module-aws';
+
+ const builder = await CatalogBuilder.create(env);
+ /** ... other processors ... */
+ builder.addProcessor(new AwsS3DiscoveryProcessor(env.reader));
+ ```
+
+ **After:**
+
+ ```yaml
+ # app-config.yaml
+
+ catalog:
+ providers:
+ awsS3:
+ yourProviderId: # identifies your dataset / provider independent of config changes
+ bucketName: sample-bucket
+ prefix: prefix/ # optional
+ region: us-east-2 # optional, uses the default region otherwise
+ ```
+
+ ```ts
+ /* packages/backend/src/plugins/catalog.ts */
+
+ import { AwsS3EntityProvider } from '@backstage/plugin-catalog-backend-module-aws';
+
+ const builder = await CatalogBuilder.create(env);
+ /** ... other processors and/or providers ... */
+ builder.addEntityProvider(
+ ...AwsS3EntityProvider.fromConfig(env.config, {
+ logger: env.logger,
+ schedule: env.scheduler.createScheduledTaskRunner({
+ frequency: Duration.fromObject({ minutes: 30 }),
+ timeout: Duration.fromObject({ minutes: 3 }),
+ }),
+ }),
+ );
+ ```
+
+ For simple setups, you can omit the provider ID at the config
+ which has the same effect as using `default` for it.
+
+ ```yaml
+ # app-config.yaml
+
+ catalog:
+ providers:
+ awsS3:
+ # uses "default" as provider ID
+ bucketName: sample-bucket
+ prefix: prefix/ # optional
+ region: us-east-2 # optional, uses the default region otherwise
+ ```
+
+- 776a91ea3a: Corrected title and URL to setup documentation in README
+
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/backend-tasks@0.3.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-catalog-backend-module-azure@0.1.2
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-catalog-backend-module-bitbucket@0.1.2
+
+### Patch Changes
+
+- c47509e1a0: Implemented changes suggested by Deepsource.io including multiple double non-null assertion operators and unexpected awaits for non-promise values.
+- 9fed130139: split BitbucketClient into BitbucketCloudClient, BitbucketServerClient
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-catalog-backend-module-github@0.1.2
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-catalog-backend-module-gitlab@0.1.2
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-catalog-backend-module-ldap@0.4.2
+
+### Patch Changes
+
+- ebc0aef2c6: Changed relationship creation in LDAP data processor to leverage entityRefs instead of metadata.name
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/backend-tasks@0.3.0
+ - @backstage/catalog-model@1.0.1
+
+## @backstage/plugin-catalog-backend-module-msgraph@0.3.1
+
+### Patch Changes
+
+- 1691c6c5c2: Clarify that config locations that emit User and Group kinds now need to declare so in the `catalog.locations.[].rules`
+- 85fc53df95: Now plugin configuration accept a new optional parameter `groupSelect` which allow the client to fetch defined fields from the ms-graph api.
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/backend-tasks@0.3.0
+ - @backstage/catalog-model@1.0.1
+
+## @backstage/plugin-catalog-common@1.0.1
+
+### Patch Changes
+
+- ada4446733: Use `createPermission` helper when creating permissions.
+- 8c8bee47f4: Add `@alpha` `CatalogEntityPermission` convenience type, available for import from `@backstage/plugin-catalog-common/alpha`.
+- Updated dependencies
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/search-common@0.3.3
+
+## @backstage/plugin-catalog-graph@0.2.16
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 77800a32dd: Added renderNode and renderLabel property to EntityRelationsGraph to support customization using CustomNode and CustomLabel components
+- 99063c39ae: Minor API report cleanup
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-catalog-graphql@0.3.8
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+
+## @backstage/plugin-catalog-import@0.8.7
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/integration-react@1.0.1
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-catalog-react@1.0.1
+
+### Patch Changes
+
+- 0ffd88a90e: Prevent permissions with types other than `ResourcePermission<'catalog-entity'>` from being used with the `useEntityPermission` hook.
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+
+- 4af82967f4: Decouple tags picker from backend entities
+
+ `EntityTagPicker` fetches all the tags independently and it doesn't require all the entities to be available client side.
+
+- 4be0d1e777: Changed catalog filter components to only pay attention to query parameters relevant to the component.
+
+- 5d5fdbe541: Columns in CatalogTable now change depending on the entity kind, ensuring only relevant columns are displayed.
+
+- 863e7bcb7b: Updated the "unregister location" behavior in `UnregisterEntityDialog`. Removed unnecessary entity deletion requests that were sent after successfully deleting a location.
+
+- 37b04b5a5e: Removed broken link from Labels section of entity inspector.
+
+- a496cee4d1: Add support for string refs to the `EntityRefLinks` component
+
+- d34900af81: Added a new `NextScaffolderRouter` which will eventually replace the exiting router
+
+- 99063c39ae: Minor API report cleanup
+
+- 4431873583: Update `usePermission` usage.
+
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-permission-react@0.4.0
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/version-bridge@1.0.1
+ - @backstage/plugin-catalog-common@1.0.1
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-cicd-statistics@0.1.6
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-circleci@0.3.4
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-cloudbuild@0.3.4
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-code-climate@0.1.4
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-code-coverage@0.1.31
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-code-coverage-backend@0.1.29
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-config-schema@0.1.27
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-cost-insights@0.11.26
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-explore@0.3.35
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-explore-react@0.0.16
+
+## @backstage/plugin-explore-react@0.0.16
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-firehydrant@0.1.21
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-fossa@0.2.36
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-gcp-projects@0.3.23
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-git-release-manager@0.3.17
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-github-actions@0.5.4
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-github-deployments@0.1.35
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/integration-react@1.0.1
+
+## @backstage/plugin-gitops-profiles@0.3.22
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-gocd@0.1.10
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- 2677db7c15: Add pagination controls to GoCD build table
+- 4c6c2b2918: Add DORA metrics insights to GoCD builds page
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-graphiql@0.2.36
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- 99063c39ae: Minor API report cleanup
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-graphql-backend@0.1.21
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-catalog-graphql@0.3.8
+
+## @backstage/plugin-home@0.4.20
+
+### Patch Changes
+
+- ab230a433f: Export template logos `TemplateBackstageLogo` and `TemplateBackstageLogoIcon` from package.
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+
+- ac323de4ad: - Adds new `HomePageStackOverflowQuestions` component which renders a list of stack overflow questions on your homepage.
+
+ - Exports `ComponentRenderer` type.
+
+- 230ad0826f: Bump to using `@types/node` v16
+
+- 9b58775849: Updated the dependency on `@backstage/config` to `^1.0.0`.
+
+- 99063c39ae: Minor API report cleanup
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-stack-overflow@0.1.0
+
+## @backstage/plugin-ilert@0.1.30
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-jenkins@0.7.3
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-jenkins-common@0.1.3
+
+## @backstage/plugin-jenkins-backend@0.1.20
+
+### Patch Changes
+
+- 1917923ab8: Use `PermissionEvaluator` instead of `PermissionAuthorizer`, which is now deprecated.
+- b013de3f50: feature: provide access token to JenkinsInstanceConfig. It can be passed to other backend calls if authentication enabled. DefaultJenkinsInfoProvider sends always this token to catalog api if access token exists.
+- ca91107110: Fixed possible type error if jenkins response contains null values
+- 71f8708f00: Make `resourceRef` required in `JenkinsApi` to match usage.
+- Updated dependencies
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-auth-node@0.2.0
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-jenkins-common@0.1.3
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-jenkins-common@0.1.3
+
+### Patch Changes
+
+- ada4446733: Use `createPermission` helper when creating permissions.
+- Updated dependencies
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/plugin-catalog-common@1.0.1
+
+## @backstage/plugin-kafka@0.3.4
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-kafka-backend@0.2.24
+
+### Patch Changes
+
+- f26cf63878: build(deps-dev): bump `@types/jest-when` from 2.7.2 to 3.5.0
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-kubernetes@0.6.4
+
+### Patch Changes
+
+- 82e2ae6ff6: build(deps): bump `cronstrue` from 1.125.0 to 2.2.0
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 1023ee6353: export kubernetes components
+- 230ad0826f: Bump to using `@types/node` v16
+- f616d99f6f: Fix division by zero in currentToDeclaredResourceToPerc when pod resources weren't set
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-kubernetes-common@0.2.9
+
+## @backstage/plugin-kubernetes-common@0.2.9
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+
+## @backstage/plugin-lighthouse@0.3.4
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-newrelic@0.3.22
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-newrelic-dashboard@0.1.12
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-org@0.5.4
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+
+- cb592bfce7: Provides the ability to hide the relations toggle on the `OwnershipCard` as well as setting a default relation type.
+
+ To hide the toggle simply include the `hideRelationsToggle` prop like this:
+
+ ```tsx
+
+ ```
+
+ To set the default relation type, add the `relationsType` prop with a value of direct or aggregated, the default if not provided is direct. Here is an example:
+
+ ```tsx
+
+ ```
+
+- d014fe2cb4: Introduced a new MyGroupsSidebarItem SidebarItem that links to one or more groups based on the logged in user's membership.
+
+ To use MyGroupsSidebarItem you'll need to add it to your `Root.tsx` like this:
+
+ ```diff
+ // app/src/components/Root/Root.tsx
+ + import { MyGroupsSidebarItem } from '@backstage/plugin-org';
+ + import GroupIcon from '@material-ui/icons/People';
+
+
+
+ //...
+ }>
+ {/* Global nav, not org-specific */}
+ //...
+
+ +
+ //...
+
+ Sidebar>
+
+ ```
+
+- 111995470d: add aggregated ownership type for kind group in OwnershipCard
+
+- 230ad0826f: Bump to using `@types/node` v16
+
+- 0bada4fc4d: Added the `metadata.description` to the bottom of each member on the MembersListCard
+
+- 99063c39ae: Minor API report cleanup
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-pagerduty@0.3.31
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-periskop@0.1.2
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-periskop-backend@0.1.2
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-permission-backend@0.5.6
+
+### Patch Changes
+
+- c98d271466: Use updated types from `@backstage/plugin-permission-common`
+- 95284162d6: - Add more specific check for policies which return conditional decisions for non-resource permissions.
+ - Refine permission validation in authorize endpoint to differentiate between `BasicPermission` and `ResourcePermission` instances.
+- Updated dependencies
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/plugin-permission-node@0.6.0
+ - @backstage/plugin-auth-node@0.2.0
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-proxy-backend@0.2.25
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-rollbar@0.4.4
+
+### Patch Changes
+
+- 7c7919777e: build(deps-dev): bump `@testing-library/react-hooks` from 7.0.2 to 8.0.0
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-rollbar-backend@0.1.28
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.6
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-scaffolder-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-scaffolder-backend-module-rails@0.3.6
+
+### Patch Changes
+
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-scaffolder-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.4
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-scaffolder-backend@1.1.0
+
+## @backstage/plugin-scaffolder-common@1.0.1
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+
+## @backstage/plugin-search-backend-module-elasticsearch@0.1.3
+
+### Patch Changes
+
+- 62ee65422c: Use new `IndexableResultSet` type as return type of query method in `SearchEngine` implementation.
+- Updated dependencies
+ - @backstage/plugin-search-common@0.3.3
+ - @backstage/plugin-search-backend-node@0.6.0
+
+## @backstage/plugin-search-backend-module-pg@0.3.2
+
+### Patch Changes
+
+- 62ee65422c: Use new `IndexableResultSet` type as return type of query method in `SearchEngine` implementation.
+- Updated dependencies
+ - @backstage/plugin-search-common@0.3.3
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-search-backend-node@0.6.0
+
+## @backstage/plugin-search-common@0.3.3
+
+### Patch Changes
+
+- c8b295f2fb: - Introduce `SearchDocument` type. This type contains the subset of `IndexableDocument` properties relevant to the frontend, and is intended to be used for documents returned to the frontend from the search API.
+ - `SearchResultSet` is now a wrapper for documents of type `SearchDocument`, and is intended to be used in the frontend. This isn't a breaking change, since `IndexableDocument`s are valid `SearchDocument`s, so the old and new types are compatible.
+ - Introduce `IndexableResultSet` type, which wraps `IndexableDocument` instances in the same way as `SearchResultSet`.
+- Updated dependencies
+ - @backstage/plugin-permission-common@0.6.0
+
+## @backstage/plugin-sentry@0.3.42
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 68bb66102d: Exposed options for the material table
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-shortcuts@0.2.5
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-sonarqube@0.3.4
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-splunk-on-call@0.3.28
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.15
+
+### Patch Changes
+
+- e0a51384ac: build(deps): bump `ajv` from 7.0.3 to 8.10.0
+- ab008a0988: Removes node-cron from tech-insights to utilize backend-tasks
+- Updated dependencies
+ - @backstage/plugin-tech-insights-node@0.2.9
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-tech-insights-node@0.2.9
+
+### Patch Changes
+
+- 231fee736b: Adds an optional timeout to fact retriever registrations to stop a task if it runs too long.
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+
+## @backstage/plugin-tech-radar@0.5.11
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- f69789330a: Fix an issue where the Radar is not updated when switching between different radars
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-todo@0.2.6
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-todo-backend@0.1.28
+
+### Patch Changes
+
+- 5da036264b: Fix method to get source-location.
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/backend-common@0.13.2
+ - @backstage/catalog-client@1.0.1
+
+## @backstage/plugin-user-settings@0.4.3
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+
+- cf647f6a72: Wired up the OneLogin provider to be visible in the Settings UI when configured correctly.
+
+ Previously it wasn't visible at all.
+
+- af508a895e: Dynamically layout User Settings theme toggle container
+
+- 230ad0826f: Bump to using `@types/node` v16
+
+- 016c574b51: Added the ability to render extra setting tabs
+
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## @backstage/plugin-xcmetrics@0.2.24
+
+### Patch Changes
+
+- 24254fd433: build(deps): bump `@testing-library/user-event` from 13.5.0 to 14.0.0
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## example-app@0.2.70
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-permission-react@0.4.0
+ - @backstage/plugin-home@0.4.20
+ - @backstage/plugin-techdocs@1.1.0
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/cli@0.17.0
+ - @backstage/plugin-scaffolder@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-kubernetes@0.6.4
+ - @backstage/core-app-api@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-catalog-graph@0.2.16
+ - @backstage/plugin-catalog-import@0.8.7
+ - @backstage/plugin-kafka@0.3.4
+ - @backstage/plugin-lighthouse@0.3.4
+ - @backstage/plugin-rollbar@0.4.4
+ - @backstage/plugin-search-react@0.1.0
+ - @backstage/plugin-search@0.8.0
+ - @backstage/integration-react@1.0.1
+ - @backstage/plugin-airbrake@0.3.4
+ - @backstage/plugin-apache-airflow@0.1.12
+ - @backstage/plugin-api-docs@0.8.4
+ - @backstage/plugin-azure-devops@0.1.20
+ - @backstage/plugin-badges@0.2.28
+ - @backstage/plugin-catalog@1.1.0
+ - @backstage/plugin-circleci@0.3.4
+ - @backstage/plugin-cloudbuild@0.3.4
+ - @backstage/plugin-code-coverage@0.1.31
+ - @backstage/plugin-cost-insights@0.11.26
+ - @backstage/plugin-explore@0.3.35
+ - @backstage/plugin-gcalendar@0.3.0
+ - @backstage/plugin-gcp-projects@0.3.23
+ - @backstage/plugin-github-actions@0.5.4
+ - @backstage/plugin-gocd@0.1.10
+ - @backstage/plugin-graphiql@0.2.36
+ - @backstage/plugin-jenkins@0.7.3
+ - @backstage/plugin-newrelic@0.3.22
+ - @backstage/plugin-org@0.5.4
+ - @backstage/plugin-pagerduty@0.3.31
+ - @backstage/plugin-sentry@0.3.42
+ - @backstage/plugin-shortcuts@0.2.5
+ - @backstage/plugin-stack-overflow@0.1.0
+ - @backstage/plugin-tech-insights@0.2.0
+ - @backstage/plugin-tech-radar@0.5.11
+ - @backstage/plugin-todo@0.2.6
+ - @backstage/plugin-user-settings@0.4.3
+ - @backstage/plugin-search-common@0.3.3
+ - @backstage/plugin-catalog-common@1.0.1
+ - @backstage/app-defaults@1.0.1
+ - @backstage/plugin-newrelic-dashboard@0.1.12
+
+## example-backend@0.2.70
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/plugin-techdocs-backend@1.1.0
+ - @backstage/plugin-scaffolder-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-search-backend@0.5.0
+ - @backstage/plugin-auth-backend@0.13.0
+ - @backstage/backend-tasks@0.3.0
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/plugin-permission-node@0.6.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.15
+ - @backstage/plugin-kafka-backend@0.2.24
+ - @backstage/plugin-auth-node@0.2.0
+ - @backstage/plugin-jenkins-backend@0.1.20
+ - @backstage/plugin-badges-backend@0.1.25
+ - @backstage/plugin-tech-insights-node@0.2.9
+ - @backstage/plugin-todo-backend@0.1.28
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-kubernetes-backend@0.5.0
+ - @backstage/plugin-search-backend-node@0.6.0
+ - @backstage/plugin-search-backend-module-elasticsearch@0.1.3
+ - @backstage/plugin-search-backend-module-pg@0.3.2
+ - @backstage/plugin-permission-backend@0.5.6
+ - @backstage/plugin-tech-insights-backend@0.3.0
+ - @backstage/plugin-azure-devops-backend@0.3.10
+ - @backstage/plugin-scaffolder-backend-module-rails@0.3.6
+ - example-app@0.2.70
+ - @backstage/catalog-client@1.0.1
+ - @backstage/plugin-app-backend@0.3.31
+ - @backstage/plugin-code-coverage-backend@0.1.29
+ - @backstage/plugin-graphql-backend@0.1.21
+ - @backstage/plugin-proxy-backend@0.2.25
+ - @backstage/plugin-rollbar-backend@0.1.28
+
+## techdocs-cli-embedded-app@0.2.69
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-techdocs@1.1.0
+ - @backstage/cli@0.17.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/core-app-api@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-techdocs-react@0.1.0
+ - @backstage/integration-react@1.0.1
+ - @backstage/test-utils@1.0.1
+ - @backstage/plugin-catalog@1.1.0
+ - @backstage/app-defaults@1.0.1
diff --git a/docs/releases/v1.1.0.md b/docs/releases/v1.1.0.md
new file mode 100644
index 0000000000..0417423247
--- /dev/null
+++ b/docs/releases/v1.1.0.md
@@ -0,0 +1,70 @@
+---
+id: v1.1.0
+title: v1.1.0
+description: Backstage Release v1.1.0
+---
+
+These are the release notes for the v1.1.0 release of [Backstage](https://backstage.io/).
+
+A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done.
+
+## Highlights
+
+### Auth
+
+The auth [backend](https://github.com/backstage/backstage/tree/master/plugins/auth-backend) and [node package](https://github.com/backstage/backstage/tree/master/plugins/auth-node) received a few **BREAKING** changes.
+
+You are now required to always return a `token` from the result of a sign-in resolver, and all default sign-in resolvers have been removed. This means that you will have to make a conscious choice to use one of a few predefined resolver functions to be able to use a given auth provider for signing in, or to write your own. Don’t worry, it’s actually rather straightforward to do, and ends up clarifying responsibilities for safe authentication and catalog ownership.
+
+There are also a number of deprecations among the exported auth backend types, which you may want to adapt to.
+
+For more information, see the relevant [documentation section](https://backstage.io/docs/auth/identity-resolver) about sign-in resolvers, and the [backend](https://github.com/backstage/backstage/blob/master/plugins/auth-backend/CHANGELOG.md#0130)/[node](https://github.com/backstage/backstage/blob/master/plugins/auth-node/CHANGELOG.md#020) changelogs.
+
+### CLI
+
+The [CLI](https://github.com/backstage/backstage/tree/master/packages/cli) has bumped the `jest` version from `^26.0.1` to `^27.5.1`. You can find the complete list of breaking changes [here](https://github.com/facebook/jest/releases/tag/v27.0.0).
+
+We strongly recommend having completed the [package role migration](https://backstage.io/docs/tutorials/package-role-migration) before upgrading to this version, as the package roles are used to automatically determine the testing environment for each package.
+
+Note that one of the breaking changes of Jest 27 is that the `jsdom` environment no longer includes `setImmediate` and `clearImmediate`, which means you might need to update some of your frontend packages. Another notable change is that `jest.useFakeTimers` now defaults to the `'modern'` implementation, which also mocks microtasks.
+
+### Kubernetes
+
+The [Kubernetes backend](https://github.com/backstage/backstage/tree/master/plugins/kubernetes-backend) has a **BREAKING** change, in that cluster suppliers now need to cache their results to allow frequent calls to their methods. This was done to pave the way for custom suppliers that dynamically fetch results from the real authority, instead of hard coding them in config. Thanks [@heyLu](https://github.com/heyLu)! ([#10428](https://github.com/backstage/backstage/pull/10428))
+
+### Permissions
+
+The permission related packages received a number of **BREAKING** changes. Among other things, the names of types were settled to be made more crisp and clear. This will mostly apply to those who write custom permissions. This all goes to the [common](https://github.com/backstage/backstage/blob/master/plugins/permission-common/CHANGELOG.md#060), [node](https://github.com/backstage/backstage/blob/master/plugins/permission-node/CHANGELOG.md#060), and [react](https://github.com/backstage/backstage/blob/master/plugins/permission-react/CHANGELOG.md#040) packages, whose changelogs are linked here.
+
+### Stack Overflow
+
+There’s a new Stack Overflow [frontend](https://github.com/backstage/backstage/tree/master/plugins/stack-overflow) plugin with a corresponding [backend](https://github.com/backstage/backstage/tree/master/plugins/stack-overflow-backend]!
+
+### Misc
+
+- The [CI/CD Statistics plugin](https://github.com/backstage/backstage/tree/master/plugins/cicd-statistics) now has GitLab support, through the new [GitLab module](https://github.com/backstage/backstage/tree/master/plugins/cicd-statistics-module-gitlab). Thanks [@djamaile](https://github.com/djamaile)! ([#10140](https://github.com/backstage/backstage/pull/10140))
+
+- The catalog [AWS module](https://github.com/backstage/backstage/tree/master/plugins/catalog-backend-module-aws) added a new `AwsS3EntityProvider` as a replacement for the `AwsS3DiscoveryProcessor`. Thanks [@pjungermann](https://github.com/pjungermann)! ([#10480](https://github.com/backstage/backstage/pull/10480))
+
+- The permissions-related exports from the catalog backend have some [breaking changes](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/CHANGELOG.md#110). These are all in alpha still, so this only applies to you if you are developing catalog permissions and import from `@backstage/plugin-catalog-backend/alpha`.
+
+## Security Fixes
+
+This release does not contain any security fixes.
+
+## Upgrade path
+
+We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated).
+
+## Links and References
+
+Below you can find a list of links and references to help you learn about and start using this new release.
+
+- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/)
+- [GitHub repository](https://github.com/backstage/backstage)
+- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy)
+- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support
+- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.1.0-changelog.md)
+- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins)
+
+Sign up for our [newsletter](https://mailchi.mp/spotify/backstage-community) if you want to be informed about what is happening in the world of Backstage.
diff --git a/docs/releases/v1.2.0-next.0-changelog.md b/docs/releases/v1.2.0-next.0-changelog.md
new file mode 100644
index 0000000000..3ea7d86a22
--- /dev/null
+++ b/docs/releases/v1.2.0-next.0-changelog.md
@@ -0,0 +1,1115 @@
+# Release v1.2.0-next.0
+
+## @backstage/integration@1.2.0-next.0
+
+### Minor Changes
+
+- 6673babab9: Gerrit UrlReader: Implemented `readTree`
+
+- 1b4e1e2306: Split `bitbucket` integration into `bitbucketCloud` and `bitbucketServer`
+ (backwards compatible).
+
+ In order to migrate to the new integration configs,
+ move your configs from `integrations.bitbucket`
+ to `integrations.bitbucketCloud` or `integrations.bitbucketServer`.
+
+ Migration example:
+
+ **Before:**
+
+ ```yaml
+ integrations:
+ bitbucket:
+ - host: bitbucket.org
+ username: bitbucket_user
+ appPassword: app-password
+ - host: bitbucket-server.company.com
+ token: my-token
+ ```
+
+ **After:**
+
+ ```yaml
+ integrations:
+ bitbucketCloud:
+ - username: bitbucket_user
+ appPassword: app-password
+ bitbucketServer:
+ - host: bitbucket-server.company.com
+ token: my-token
+ ```
+
+- 566407bf8a: Gerrit Integration: Added the `getGerritProjectsApiUrl` function
+
+## @backstage/integration-react@1.1.0-next.0
+
+### Minor Changes
+
+- 1b4e1e2306: Split `bitbucket` integration into `bitbucketCloud` and `bitbucketServer`
+ (backwards compatible).
+
+ In order to migrate to the new integration configs,
+ move your configs from `integrations.bitbucket`
+ to `integrations.bitbucketCloud` or `integrations.bitbucketServer`.
+
+ Migration example:
+
+ **Before:**
+
+ ```yaml
+ integrations:
+ bitbucket:
+ - host: bitbucket.org
+ username: bitbucket_user
+ appPassword: app-password
+ - host: bitbucket-server.company.com
+ token: my-token
+ ```
+
+ **After:**
+
+ ```yaml
+ integrations:
+ bitbucketCloud:
+ - username: bitbucket_user
+ appPassword: app-password
+ bitbucketServer:
+ - host: bitbucket-server.company.com
+ token: my-token
+ ```
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+
+## @backstage/plugin-catalog@1.2.0-next.0
+
+### Minor Changes
+
+- 4274844a8c: Use InfoCardVariants on custom cards variant attribute
+- ceca63d149: Added the prop `NotFoundComponent` to `EntityLayout` which can be used to include a custom component when an entity is not found in the catalog
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+
+## @backstage/plugin-catalog-backend-module-gerrit@0.1.0-next.0
+
+### Minor Changes
+
+- 566407bf8a: Initial version of the `plugin-catalog-backend-module-gerrit` plugin
+
+### Patch Changes
+
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+ - @backstage/backend-tasks@0.3.1-next.0
+
+## @backstage/plugin-catalog-react@1.1.0-next.0
+
+### Minor Changes
+
+- 4274844a8c: Use InfoCardVariants on custom cards variant attribute
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+
+## @backstage/plugin-scaffolder@1.2.0-next.0
+
+### Minor Changes
+
+- 06ab5218f9: Add new bitbucket(Cloud/Server) integrations to ScaffolderClient.
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+
+## @backstage/plugin-scaffolder-backend@1.2.0-next.0
+
+### Minor Changes
+
+- 9818112d12: Update the `github:publish` action to allow passing required status check
+ contexts before merging to the main branch.
+- 8d5a2238a9: Split `publish:bitbucket` into `publish:bitbucketCloud` and `publish:bitbucketServer`.
+
+ In order to migrate from the deprecated action, you need to replace the use of action
+ `publish:bitbucket` in your templates with the use of either `publish:bitbucketCloud`
+ or `publish:bitbucketServer` - depending on which destination SCM provider you use.
+
+ Additionally, these actions will not utilize `integrations.bitbucket` anymore,
+ but `integrations.bitbucketCloud` or `integrations.bitbucketServer` respectively.
+ You may or may not have migrated to these already.
+
+ As described in a previous changeset, using these two replacement integrations configs
+ will not compromise use cases which still rely on `integrations.bitbucket` as this was
+ set up in a backwards compatible way.
+
+ Additionally, please mind that the option `enableLFS` is only available (and always was)
+ for Bitbucket Server use cases and therefore, is not even part of the schema for
+ `publish:bitbucketCloud` anymore.
+
+### Patch Changes
+
+- 0fc65cbf89: Override default commit message and author details in GitHub, Azure, bitbucket
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+
+## @backstage/plugin-techdocs-module-addons-contrib@0.1.0-next.0
+
+### Minor Changes
+
+- 5f4dbd2b52: A package for contributed TechDocs addons.
+
+ In this release it will introduce the ReportIssue addon, which lets you select text and open a GitHub/Gitlab issue.
+
+### Patch Changes
+
+- 075a9a067b: Updated the return type of `createTechDocsAddonExtension` to better reflect the fact that passing children to Addon components is not a valid use-case.
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+ - @backstage/plugin-techdocs-react@0.1.1-next.0
+
+## @backstage/backend-common@0.13.3-next.0
+
+### Patch Changes
+
+- 6673babab9: Gerrit integration: Added optional `cloneUrl` string to config.
+- 75bf9e1da9: Split BitbucketUrlReader into BitbucketCloudUrlReader and BitbucketServerUrlReader. Backwards compatible.
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- 9ec4e0613e: Update to `jose` 4.6.0
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/config-loader@1.1.1-next.0
+
+## @backstage/backend-tasks@0.3.1-next.0
+
+### Patch Changes
+
+- cfd779a9bc: Scheduled tasks now have an optional `scope` field. If unset, or having the
+ value `'global'`, the old behavior with cross-worker locking is retained. If
+ having the value `'local'`, there is no coordination across workers and the
+ behavior is more like `setInterval`. This can be used to replace usages of
+ `runPeriodically` helpers.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/backend-test-utils@0.1.24-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/cli@0.17.1-next.0
+
+## @backstage/cli@0.17.1-next.0
+
+### Patch Changes
+
+- 97cce67ac7: Add instructions to `create-github-app` command.
+- 08e12a3a14: Add package global-agent to support behind a proxy for backstage-cli commands like versions:bump.
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- 344ea56acc: Bump `commander` to version 9.1.0
+- 8ab2a8226b: Updated the `create-github-app` command to throw an error if the organization argument is a user or a non existing organization.
+- Updated dependencies
+ - @backstage/config-loader@1.1.1-next.0
+
+## @backstage/codemods@0.1.38-next.0
+
+### Patch Changes
+
+- 344ea56acc: Bump `commander` to version 9.1.0
+
+## @backstage/config-loader@1.1.1-next.0
+
+### Patch Changes
+
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- 9e8ef53498: Handle empty config files gracefully
+
+## @backstage/create-app@0.4.27-next.0
+
+### Patch Changes
+
+- 3983940a21: Optimized the command order in `packages/backend/Dockerfile` as well as added the `--no-install-recommends` to the `apt-get install` and tweaked the installed packages.
+
+ To apply this change to an existing app, update your `packages/backend/Dockerfile` to match the documented `Dockerfile` at .
+
+- 28bbf5aff6: Added some instruction comments to the generated config files, to clarify the
+ usage of `backend.baseUrl` and `backend.listen.host`. Importantly, it also per
+ default now listens on all IPv4 interfaces, to make it easier to take the step
+ over to production. If you want to do the same, update your
+ `app-config.production.yaml` as follows:
+
+ ```diff
+ backend:
+ listen:
+ port: 7007
+ + host: 0.0.0.0
+ ```
+
+ Also, updated the builtin backend Dockerfile to honor the
+ `app-config.production.yaml` file. If you want to do the same, change
+ `packages/backend/Dockerfile` as follows:
+
+ ```diff
+ -COPY packages/backend/dist/bundle.tar.gz app-config.yaml ./
+ +COPY packages/backend/dist/bundle.tar.gz app-config*.yaml ./
+ RUN tar xzf bundle.tar.gz && rm bundle.tar.gz
+
+ -CMD ["node", "packages/backend", "--config", "app-config.yaml"]
+ +CMD ["node", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.production.yaml"]
+ ```
+
+ If you look carefully, this adds a glob match on app-config files. For those
+ that try out the build flows locally, you also want to make sure that the docker
+ daemon does NOT pick up any local/private config files that might contain
+ secrets. You should therefore also update your local `.dockerignore` file at the
+ same time:
+
+ ```diff
+ +*.local.yaml
+ ```
+
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+
+- 344ea56acc: Bump `commander` to version 9.1.0
+
+- 806427545f: Added a link to the `${GITHUB_TOKEN}` to document how to generate a token
+
+## @backstage/dev-utils@1.0.2-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+ - @backstage/test-utils@1.0.2-next.0
+
+## @techdocs/cli@1.1.1-next.0
+
+### Patch Changes
+
+- 344ea56acc: Bump `commander` to version 9.1.0
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-techdocs-node@1.1.1-next.0
+
+## @backstage/techdocs-common@0.11.15-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-techdocs-node@1.1.1-next.0
+
+## @backstage/test-utils@1.0.2-next.0
+
+### Patch Changes
+
+- 7a5ddfd595: Added missing `Routes` element to wrap the `Route` elements of the test app wrapping.
+- 7a5ddfd595: The internal elements created as part of the `mountedRoutes` implementation are now hidden during rendering.
+
+## @backstage/plugin-airbrake@0.3.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/test-utils@1.0.2-next.0
+ - @backstage/dev-utils@1.0.2-next.0
+
+## @backstage/plugin-airbrake-backend@0.2.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-allure@0.1.21-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-api-docs@0.8.5-next.0
+
+### Patch Changes
+
+- 4274844a8c: Use InfoCardVariants on custom cards variant attribute
+- 09fa05e5d7: Bumped @asyncapi/react-component > openapi-sampler > json-pointer to resolve security vulnerability CVE-2021-23820
+- 433a609a15: Updated the rendering of AsyncApi definitions to be able to resolve absolute HTTP \\$ref references.
+- Updated dependencies
+ - @backstage/plugin-catalog@1.2.0-next.0
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-app-backend@0.3.32-next.0
+
+### Patch Changes
+
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/config-loader@1.1.1-next.0
+
+## @backstage/plugin-auth-backend@0.13.1-next.0
+
+### Patch Changes
+
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+
+- 787ae0d541: Add more common predefined sign-in resolvers to auth providers.
+
+ Add the existing resolver to more providers (already available at `google`):
+
+ - `providers.microsoft.resolvers.emailLocalPartMatchingUserEntityName()`
+ - `providers.okta.resolvers.emailLocalPartMatchingUserEntityName()`
+
+ Add a new resolver for simple email-to-email matching:
+
+ - `providers.google.resolvers.emailMatchingUserEntityProfileEmail()`
+ - `providers.microsoft.resolvers.emailMatchingUserEntityProfileEmail()`
+ - `providers.okta.resolvers.emailMatchingUserEntityProfileEmail()`
+
+- 9ec4e0613e: Update to `jose` 4.6.0
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-auth-node@0.2.1-next.0
+
+## @backstage/plugin-auth-node@0.2.1-next.0
+
+### Patch Changes
+
+- 9ec4e0613e: Update to `jose` 4.6.0
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-azure-devops@0.1.21-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-azure-devops-backend@0.3.11-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-badges@0.2.29-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-badges-backend@0.1.26-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-bazaar@0.1.20-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/cli@0.17.1-next.0
+ - @backstage/plugin-catalog@1.2.0-next.0
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-bazaar-backend@0.1.16-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/backend-test-utils@0.1.24-next.0
+
+## @backstage/plugin-bitrise@0.1.32-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-catalog-backend@1.1.2-next.0
+
+### Patch Changes
+
+- 55e09b29dd: Fixing broken types for `knex` when checking returned rows
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- 8cc75993a6: Fixed issue in `PermissionEvaluator` instance check that would cause unexpected "invalid union" errors.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-permission-node@0.6.1-next.0
+
+## @backstage/plugin-catalog-backend-module-aws@0.1.5-next.0
+
+### Patch Changes
+
+- bffec1c96a: Fix S3 object URL creation at AwsS3EntityProvider by
+
+ - handle absence of region config,
+ - handle regions with region-less URIs (us-east-1),
+ - apply URI encoding,
+ - and simplify the logic overall.
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+ - @backstage/backend-tasks@0.3.1-next.0
+
+## @backstage/plugin-catalog-backend-module-azure@0.1.3-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+
+## @backstage/plugin-catalog-backend-module-bitbucket@0.1.3-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+
+## @backstage/plugin-catalog-backend-module-github@0.1.3-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+
+## @backstage/plugin-catalog-backend-module-gitlab@0.1.3-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+
+## @backstage/plugin-catalog-backend-module-ldap@0.4.3-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+ - @backstage/backend-tasks@0.3.1-next.0
+
+## @backstage/plugin-catalog-backend-module-msgraph@0.3.2-next.0
+
+### Patch Changes
+
+- 8d9f673106: Add annotation `microsoft.com/email` when using the `defaultUserTransformer`.
+
+ This will allow users of the Microsoft auth provider to utilize the predefined
+ SignIn resolver instead of maintaining their own.
+
+ ```typescript
+ // backend/plugins/auth.ts
+
+ // [...]
+
+ export default async function createPlugin(
+ env: PluginEnvironment,
+ ): Promise {
+ return await createRouter({
+ // [...]
+ providerFactories: {
+ microsoft: providers.microsoft.create({
+ signIn: {
+ resolver:
+ providers.microsoft.resolvers.emailMatchingUserEntityAnnotation(),
+ },
+ }),
+ },
+ });
+ }
+ ```
+
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+ - @backstage/backend-tasks@0.3.1-next.0
+
+## @backstage/plugin-catalog-graph@0.2.17-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-catalog-import@0.8.8-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+
+## @backstage/plugin-cicd-statistics@0.1.7-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-cicd-statistics-module-gitlab@0.1.1-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-cicd-statistics@0.1.7-next.0
+
+## @backstage/plugin-circleci@0.3.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-cloudbuild@0.3.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-code-climate@0.1.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-code-coverage@0.1.32-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-code-coverage-backend@0.1.30-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+
+## @backstage/plugin-explore@0.3.36-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-firehydrant@0.1.22-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-fossa@0.2.37-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-gcalendar@0.3.1-next.0
+
+### Patch Changes
+
+- 1429dbbea9: fixed google API types dependencies
+
+## @backstage/plugin-git-release-manager@0.3.18-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+
+## @backstage/plugin-github-actions@0.5.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-github-deployments@0.1.36-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+
+## @backstage/plugin-gocd@0.1.11-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-graphql-backend@0.1.22-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-home@0.4.21-next.0
+
+### Patch Changes
+
+- 2b733d9d39: star icons now have the same yellow color as the other star icons when a entity is favourite
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/plugin-stack-overflow@0.1.1-next.0
+
+## @backstage/plugin-ilert@0.1.31-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-jenkins@0.7.4-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-jenkins-backend@0.1.22-next.0
+
+### Patch Changes
+
+- 8cc75993a6: Fixed issue in `PermissionEvaluator` instance check that would cause unexpected "invalid union" errors.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-auth-node@0.2.1-next.0
+
+## @backstage/plugin-kafka@0.3.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-kafka-backend@0.2.25-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-kubernetes@0.6.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-kubernetes-backend@0.5.1-next.0
+
+### Patch Changes
+
+- b9f7ffb162: Add filtering to GKE cluster locator
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-lighthouse@0.3.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-newrelic-dashboard@0.1.13-next.0
+
+### Patch Changes
+
+- 5fa2fb2553: Add `FetchApi` and related `fetchApiRef` which implement fetch. in order to included the Authorization Token to New Relic Dashboard Plugin, so that frontend can send an authenticated proxy call to backend
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-org@0.5.5-next.0
+
+### Patch Changes
+
+- 8da4a207dd: Fix ref to filtered catalog table view when using aggregated relations.
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-pagerduty@0.3.32-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-periskop@0.1.3-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-periskop-backend@0.1.3-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-permission-backend@0.5.7-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-auth-node@0.2.1-next.0
+ - @backstage/plugin-permission-node@0.6.1-next.0
+
+## @backstage/plugin-permission-node@0.6.1-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-auth-node@0.2.1-next.0
+
+## @backstage/plugin-proxy-backend@0.2.26-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-rollbar@0.4.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-rollbar-backend@0.1.29-next.0
+
+### Patch Changes
+
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.7-next.0
+
+### Patch Changes
+
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-scaffolder-backend@1.2.0-next.0
+ - @backstage/integration@1.2.0-next.0
+
+## @backstage/plugin-scaffolder-backend-module-rails@0.3.7-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-scaffolder-backend@1.2.0-next.0
+ - @backstage/integration@1.2.0-next.0
+
+## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-scaffolder-backend@1.2.0-next.0
+
+## @backstage/plugin-search@0.8.1-next.0
+
+### Patch Changes
+
+- 11a46863de: Fix issue with `HomePageSearchBar` requiring `SearchContext`
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/plugin-search-react@0.1.1-next.0
+
+## @backstage/plugin-search-backend@0.5.2-next.0
+
+### Patch Changes
+
+- 8cc75993a6: Fixed issue in `PermissionEvaluator` instance check that would cause unexpected "invalid union" errors.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-auth-node@0.2.1-next.0
+ - @backstage/plugin-permission-node@0.6.1-next.0
+ - @backstage/plugin-search-backend-node@0.6.1-next.0
+
+## @backstage/plugin-search-backend-module-elasticsearch@0.1.4-next.0
+
+### Patch Changes
+
+- a7f7a63d14: Prevent orphaned stale indices by permanently marking them for deletion so removal can be re-attempted if it failed previously
+- Updated dependencies
+ - @backstage/plugin-search-backend-node@0.6.1-next.0
+
+## @backstage/plugin-search-backend-module-pg@0.3.3-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-search-backend-node@0.6.1-next.0
+
+## @backstage/plugin-search-backend-node@0.6.1-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-tasks@0.3.1-next.0
+
+## @backstage/plugin-search-react@0.1.1-next.0
+
+### Patch Changes
+
+- 11a46863de: Export `useSearchContextCheck` hook to check if the search context is available
+- a307a14be0: Removed dependency on `@backstage/core-app-api`.
+
+## @backstage/plugin-sentry@0.3.43-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-sonarqube@0.3.5-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-splunk-on-call@0.3.29-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-stack-overflow@0.1.1-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-home@0.4.21-next.0
+
+## @backstage/plugin-tech-insights@0.2.1-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-tech-insights-backend@0.3.1-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/backend-tasks@0.3.1-next.0
+ - @backstage/plugin-tech-insights-node@0.2.10-next.0
+
+## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.16-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-tech-insights-node@0.2.10-next.0
+
+## @backstage/plugin-tech-insights-node@0.2.10-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## @backstage/plugin-techdocs@1.1.1-next.0
+
+### Patch Changes
+
+- a307a14be0: Removed dependency on `@backstage/core-app-api`.
+- bed0d64ce9: Fixed bugs that prevented a 404 error from being shown when it should have been.
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+ - @backstage/plugin-search-react@0.1.1-next.0
+ - @backstage/plugin-techdocs-react@0.1.1-next.0
+
+## @backstage/plugin-techdocs-backend@1.1.1-next.0
+
+### Patch Changes
+
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-techdocs-node@1.1.1-next.0
+
+## @backstage/plugin-techdocs-node@1.1.1-next.0
+
+### Patch Changes
+
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- b26f4cb6a1: Allow usage of custom tags with sequence node type (such as the !ENV tag) in the techdocs mkdocs config.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+
+## @backstage/plugin-techdocs-react@0.1.1-next.0
+
+### Patch Changes
+
+- 075a9a067b: Updated the return type of `createTechDocsAddonExtension` to better reflect the fact that passing children to Addon components is not a valid use-case.
+
+## @backstage/plugin-todo@0.2.7-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+
+## @backstage/plugin-todo-backend@0.1.29-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/integration@1.2.0-next.0
+
+## example-app@0.2.71-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-scaffolder@1.2.0-next.0
+ - @backstage/cli@0.17.1-next.0
+ - @backstage/plugin-home@0.4.21-next.0
+ - @backstage/plugin-api-docs@0.8.5-next.0
+ - @backstage/plugin-catalog@1.2.0-next.0
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+ - @backstage/plugin-newrelic-dashboard@0.1.13-next.0
+ - @backstage/plugin-search@0.8.1-next.0
+ - @backstage/plugin-search-react@0.1.1-next.0
+ - @backstage/plugin-techdocs@1.1.1-next.0
+ - @backstage/plugin-techdocs-module-addons-contrib@0.1.0-next.0
+ - @backstage/plugin-techdocs-react@0.1.1-next.0
+ - @backstage/plugin-gcalendar@0.3.1-next.0
+ - @backstage/plugin-org@0.5.5-next.0
+ - @backstage/plugin-catalog-import@0.8.8-next.0
+ - @backstage/plugin-github-actions@0.5.5-next.0
+ - @backstage/plugin-airbrake@0.3.5-next.0
+ - @backstage/plugin-azure-devops@0.1.21-next.0
+ - @backstage/plugin-badges@0.2.29-next.0
+ - @backstage/plugin-catalog-graph@0.2.17-next.0
+ - @backstage/plugin-circleci@0.3.5-next.0
+ - @backstage/plugin-cloudbuild@0.3.5-next.0
+ - @backstage/plugin-code-coverage@0.1.32-next.0
+ - @backstage/plugin-explore@0.3.36-next.0
+ - @backstage/plugin-gocd@0.1.11-next.0
+ - @backstage/plugin-jenkins@0.7.4-next.0
+ - @backstage/plugin-kafka@0.3.5-next.0
+ - @backstage/plugin-kubernetes@0.6.5-next.0
+ - @backstage/plugin-lighthouse@0.3.5-next.0
+ - @backstage/plugin-pagerduty@0.3.32-next.0
+ - @backstage/plugin-rollbar@0.4.5-next.0
+ - @backstage/plugin-sentry@0.3.43-next.0
+ - @backstage/plugin-stack-overflow@0.1.1-next.0
+ - @backstage/plugin-tech-insights@0.2.1-next.0
+ - @backstage/plugin-todo@0.2.7-next.0
+
+## example-backend@0.2.71-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-scaffolder-backend@1.2.0-next.0
+ - @backstage/plugin-kubernetes-backend@0.5.1-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+ - @backstage/plugin-app-backend@0.3.32-next.0
+ - @backstage/plugin-auth-backend@0.13.1-next.0
+ - @backstage/plugin-rollbar-backend@0.1.29-next.0
+ - @backstage/plugin-techdocs-backend@1.1.1-next.0
+ - @backstage/plugin-search-backend-module-elasticsearch@0.1.4-next.0
+ - @backstage/plugin-jenkins-backend@0.1.22-next.0
+ - @backstage/plugin-search-backend@0.5.2-next.0
+ - @backstage/backend-tasks@0.3.1-next.0
+ - @backstage/plugin-auth-node@0.2.1-next.0
+ - example-app@0.2.71-next.0
+ - @backstage/plugin-azure-devops-backend@0.3.11-next.0
+ - @backstage/plugin-badges-backend@0.1.26-next.0
+ - @backstage/plugin-code-coverage-backend@0.1.30-next.0
+ - @backstage/plugin-graphql-backend@0.1.22-next.0
+ - @backstage/plugin-kafka-backend@0.2.25-next.0
+ - @backstage/plugin-permission-backend@0.5.7-next.0
+ - @backstage/plugin-permission-node@0.6.1-next.0
+ - @backstage/plugin-proxy-backend@0.2.26-next.0
+ - @backstage/plugin-scaffolder-backend-module-rails@0.3.7-next.0
+ - @backstage/plugin-search-backend-module-pg@0.3.3-next.0
+ - @backstage/plugin-search-backend-node@0.6.1-next.0
+ - @backstage/plugin-tech-insights-backend@0.3.1-next.0
+ - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.16-next.0
+ - @backstage/plugin-tech-insights-node@0.2.10-next.0
+ - @backstage/plugin-todo-backend@0.1.29-next.0
+
+## techdocs-cli-embedded-app@0.2.70-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/cli@0.17.1-next.0
+ - @backstage/plugin-catalog@1.2.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+ - @backstage/plugin-techdocs@1.1.1-next.0
+ - @backstage/plugin-techdocs-react@0.1.1-next.0
+ - @backstage/test-utils@1.0.2-next.0
diff --git a/docs/tutorials/switching-sqlite-postgres.md b/docs/tutorials/switching-sqlite-postgres.md
index 5d4268a4bc..c4e4bd83b6 100644
--- a/docs/tutorials/switching-sqlite-postgres.md
+++ b/docs/tutorials/switching-sqlite-postgres.md
@@ -55,3 +55,34 @@ launching Backstage, or remove the `${...}` values and simply set actual values
directly for development.
The Backstage App is now ready to start up with a PostgreSQL backing database.
+
+### Override default PostgreSQL Database Pool Configuration
+
+If you want to override the default connection pool settings then use the below configuration:
+
+```diff
+backend:
+ database:
+- client: better-sqlite3
+- connection: ':memory:'
++ # config options: https://node-postgres.com/api/client
++ client: pg
++ connection:
++ host: ${POSTGRES_HOST}
++ port: ${POSTGRES_PORT}
++ user: ${POSTGRES_USER}
++ password: ${POSTGRES_PASSWORD}
++ # Refer to Tarn docs for default values on PostgreSQL pool configuration - https://github.com/Vincit/tarn.js
++ knexConfig:
++ pool:
++ min: 3
++ max: 12
++ acquireTimeoutMillis: 60000
++ idleTimeoutMillis: 60000
++ # https://node-postgres.com/features/ssl
++ # you can set the sslmode configuration option via the `PGSSLMODE` environment variable
++ # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require)
++ # ssl:
++ # ca: # if you have a CA file and want to verify it you can uncomment this section
++ # $file: /ca/server.crt
+```
diff --git a/docs/tutorials/using-backstage-proxy-within-plugin.md b/docs/tutorials/using-backstage-proxy-within-plugin.md
index 771aa7a652..3002eb1aff 100644
--- a/docs/tutorials/using-backstage-proxy-within-plugin.md
+++ b/docs/tutorials/using-backstage-proxy-within-plugin.md
@@ -52,7 +52,7 @@ calling `${backend-url}/api/proxy/`. The reason why
`backend-url` is referenced is because the backstage backend creates and runs
the proxy. Backstage is structured in such a way that you could run the
backstage frontend independently of the backend. So when calling your API you
-need to prepend the backend url to your http call.
+need to prepend the backend URL to your http call.
The recommended pattern for calling out to services is to wrap your calls in a
[Utility API](../api/utility-apis.md). This section describes the steps to wrap
diff --git a/microsite/data/plugins/adr.yaml b/microsite/data/plugins/adr.yaml
new file mode 100644
index 0000000000..f180c80e36
--- /dev/null
+++ b/microsite/data/plugins/adr.yaml
@@ -0,0 +1,9 @@
+---
+title: Architecture Decision Records
+author: Phil Kuang
+authorUrl: https://github.com/kuangp
+category: Discovery
+description: Browse your project's ADRs.
+documentation: https://github.com/backstage/backstage/tree/master/plugins/adr
+iconUrl: img/adr-logo.png
+npmPackageName: '@backstage/plugin-adr'
diff --git a/microsite/data/plugins/cloud-carbon-footprint.yaml b/microsite/data/plugins/cloud-carbon-footprint.yaml
new file mode 100644
index 0000000000..7e73ad6adb
--- /dev/null
+++ b/microsite/data/plugins/cloud-carbon-footprint.yaml
@@ -0,0 +1,15 @@
+---
+title: Cloud Carbon Footprint
+author: Thoughtworks
+authorUrl: https://github.com/cloud-carbon-footprint
+category: Metrics
+description: View your cloud carbon footprint by estimating energy use (kilowatt-hours) and carbon emissions (metric tons CO2e) from public cloud usage.
+documentation: https://github.com/cloud-carbon-footprint/ccf-backstage-plugin/blob/trunk/README.md
+iconUrl: https://www.cloudcarbonfootprint.org/img/logo.png
+npmPackageName: '@cloud-carbon-footprint/backstage-plugin-frontend'
+tags:
+ - sustainability
+ - cloud
+ - climate
+ - carbon-emissions
+ - carbon-footprint
diff --git a/microsite/package.json b/microsite/package.json
index ebdc83dc23..c0c16d881b 100644
--- a/microsite/package.json
+++ b/microsite/package.json
@@ -16,7 +16,7 @@
"lock:check": "yarn-lock-check"
},
"devDependencies": {
- "@spotify/prettier-config": "^13.0.0",
+ "@spotify/prettier-config": "^13.0.1",
"docusaurus": "^2.0.0-alpha.70",
"js-yaml": "^4.1.0",
"prettier": "^2.6.2",
diff --git a/microsite/sidebars.json b/microsite/sidebars.json
index d284a3c8ab..43e9dd3978 100644
--- a/microsite/sidebars.json
+++ b/microsite/sidebars.json
@@ -1,6 +1,6 @@
{
"releases": {
- "Release Notes": ["releases/v1.0.0"]
+ "Release Notes": ["releases/v1.1.0", "releases/v1.0.0"]
},
"docs": {
"Overview": [
@@ -109,6 +109,7 @@
"features/techdocs/techdocs-overview",
"features/techdocs/getting-started",
"features/techdocs/concepts",
+ "features/techdocs/addons",
"features/techdocs/architecture",
"features/techdocs/creating-and-publishing",
"features/techdocs/configuration",
@@ -156,7 +157,10 @@
{
"type": "subcategory",
"label": "Gerrit",
- "ids": ["integrations/gerrit/locations"]
+ "ids": [
+ "integrations/gerrit/locations",
+ "integrations/gerrit/discovery"
+ ]
},
{
"type": "subcategory",
@@ -164,7 +168,8 @@
"ids": [
"integrations/github/locations",
"integrations/github/discovery",
- "integrations/github/org"
+ "integrations/github/org",
+ "integrations/github/github-apps"
]
},
{
@@ -202,7 +207,6 @@
"plugins/proxying",
"plugins/backend-plugin",
"plugins/call-existing-api",
- "plugins/github-apps",
"plugins/url-reader"
]
},
@@ -246,7 +250,6 @@
]
},
"auth/add-auth-provider",
- "auth/using-auth",
"auth/identity-resolver",
"auth/auth-backend",
"auth/oauth",
diff --git a/microsite/static/img/adr-logo.png b/microsite/static/img/adr-logo.png
new file mode 100644
index 0000000000..a71c54074d
Binary files /dev/null and b/microsite/static/img/adr-logo.png differ
diff --git a/microsite/yarn.lock b/microsite/yarn.lock
index 72d56b3521..448647da15 100644
--- a/microsite/yarn.lock
+++ b/microsite/yarn.lock
@@ -909,10 +909,10 @@
resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==
-"@spotify/prettier-config@^13.0.0":
- version "13.0.0"
- resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-13.0.0.tgz#ff6372cedf7e97e2e8a2d96c5ec12aa32cca3dbf"
- integrity sha512-Hl3zgj67zaYejjLQLq0h0DlDMaI62EppO30AcStpLZNihjfwnFeS2+/gamiRHAnLki3P8bXaZVYwOV5NYNGQfw==
+"@spotify/prettier-config@^13.0.1":
+ version "13.0.1"
+ resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-13.0.1.tgz#0fdceb3d4ab543259ce6adc0ec1d10e34898b812"
+ integrity sha512-oVd4hjx2+y0MeUdk1l+ItwVLwlrDlvTlGwXBWMMzPYc7DLyxuxFvDfoHGkAQkrikfAgtdnzxrW6u9a8ywUqdfw==
"@types/cheerio@^0.22.8":
version "0.22.23"
@@ -1117,9 +1117,9 @@ async-each@^1.0.1:
integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
async@^2.6.2:
- version "2.6.3"
- resolved "https://registry.npmjs.org/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
- integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
+ version "2.6.4"
+ resolved "https://registry.npmjs.org/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221"
+ integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==
dependencies:
lodash "^4.17.14"
diff --git a/mkdocs.yml b/mkdocs.yml
index 204a4768c3..0e56dcbd73 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,5 +1,7 @@
site_name: 'Backstage'
site_description: 'Main documentation for Backstage features and platform APIs'
+repo_url: https://github.com/backstage/backstage
+edit_uri: edit/master/docs
plugins:
- techdocs-core
@@ -99,10 +101,12 @@ nav:
- Installation: 'integrations/datadog-rum/installation.md'
- Gerrit:
- Locations: 'integrations/gerrit/locations.md'
+ - Discovery: 'integrations/gerrit/discovery.md'
- GitHub:
- Locations: 'integrations/github/locations.md'
- Discovery: 'integrations/github/discovery.md'
- Org Data: 'integrations/github/org.md'
+ - GitHub Apps: 'integrations/github/github-apps.md'
- GitLab:
- Locations: 'integrations/gitlab/locations.md'
- Discovery: 'integrations/gitlab/discovery.md'
@@ -124,7 +128,6 @@ nav:
- Proxying: 'plugins/proxying.md'
- Backend plugin: 'plugins/backend-plugin.md'
- Call existing API: 'plugins/call-existing-api.md'
- - GitHub Apps for Backend Authentication: 'plugins/github-apps.md'
- URL Reader: 'plugins/url-reader.md'
- Testing:
- Testing with Jest: 'plugins/testing.md'
@@ -150,7 +153,6 @@ nav:
- OAuth2Proxy: 'auth/oauth2-proxy/provider.md'
- Bitbucket: 'auth/bitbucket/provider.md'
- Adding authentication providers: 'auth/add-auth-provider.md'
- - Using authentication and identity: 'auth/using-auth.md'
- Sign in resolvers: 'auth/identity-resolver.md'
- Auth backend: 'auth/auth-backend.md'
- OAuth and OpenID Connect: 'auth/oauth.md'
diff --git a/package.json b/package.json
index 6fea4e081a..db8816a7ac 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,7 @@
"@types/react": "^17",
"@types/react-dom": "^17"
},
- "version": "1.1.0-next.2",
+ "version": "1.2.0-next.0",
"dependencies": {
"@manypkg/get-packages": "^1.1.3",
"@microsoft/api-documenter": "^7.17.5",
@@ -67,7 +67,7 @@
"cross-env": "^7.0.0",
"concurrently": "^7.0.0",
"eslint-plugin-notice": "^0.9.10",
- "fs-extra": "10.0.1",
+ "fs-extra": "10.1.0",
"husky": "^7.0.4",
"lerna": "^4.0.0",
"lint-staged": "^12.2.0",
diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md
index d0b482dac7..cf09d57fcd 100644
--- a/packages/app-defaults/CHANGELOG.md
+++ b/packages/app-defaults/CHANGELOG.md
@@ -1,5 +1,27 @@
# @backstage/app-defaults
+## 1.0.1
+
+### Patch Changes
+
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/plugin-permission-react@0.4.0
+ - @backstage/core-app-api@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+
+## 1.0.1-next.2
+
+### Patch Changes
+
+- 230ad0826f: Bump to using `@types/node` v16
+- Updated dependencies
+ - @backstage/core-app-api@1.0.1-next.1
+ - @backstage/core-components@0.9.3-next.2
+ - @backstage/core-plugin-api@1.0.1-next.0
+ - @backstage/plugin-permission-react@0.4.0-next.1
+
## 1.0.1-next.1
### Patch Changes
diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json
index 0d70d29c92..ae18b4217f 100644
--- a/packages/app-defaults/package.json
+++ b/packages/app-defaults/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/app-defaults",
"description": "Provides the default wiring of a Backstage App",
- "version": "1.0.1-next.1",
+ "version": "1.0.1",
"private": false,
"publishConfig": {
"access": "public",
@@ -33,10 +33,10 @@
"start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/core-components": "^0.9.3-next.0",
- "@backstage/core-app-api": "^1.0.1-next.0",
- "@backstage/core-plugin-api": "^1.0.0",
- "@backstage/plugin-permission-react": "^0.4.0-next.0",
+ "@backstage/core-components": "^0.9.3",
+ "@backstage/core-app-api": "^1.0.1",
+ "@backstage/core-plugin-api": "^1.0.1",
+ "@backstage/plugin-permission-react": "^0.4.0",
"@backstage/theme": "^0.2.15",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
@@ -46,8 +46,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.17.0-next.1",
- "@backstage/test-utils": "^1.0.1-next.1",
+ "@backstage/cli": "^0.17.1-next.0",
+ "@backstage/test-utils": "^1.0.2-next.0",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@types/jest": "^26.0.7",
diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md
index 9fe57d36fc..498cdf6ed5 100644
--- a/packages/app/CHANGELOG.md
+++ b/packages/app/CHANGELOG.md
@@ -1,5 +1,156 @@
# example-app
+## 0.2.71-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-scaffolder@1.2.0-next.0
+ - @backstage/cli@0.17.1-next.0
+ - @backstage/plugin-home@0.4.21-next.0
+ - @backstage/plugin-api-docs@0.8.5-next.0
+ - @backstage/plugin-catalog@1.2.0-next.0
+ - @backstage/plugin-catalog-react@1.1.0-next.0
+ - @backstage/integration-react@1.1.0-next.0
+ - @backstage/plugin-newrelic-dashboard@0.1.13-next.0
+ - @backstage/plugin-search@0.8.1-next.0
+ - @backstage/plugin-search-react@0.1.1-next.0
+ - @backstage/plugin-techdocs@1.1.1-next.0
+ - @backstage/plugin-techdocs-module-addons-contrib@0.1.0-next.0
+ - @backstage/plugin-techdocs-react@0.1.1-next.0
+ - @backstage/plugin-gcalendar@0.3.1-next.0
+ - @backstage/plugin-org@0.5.5-next.0
+ - @backstage/plugin-catalog-import@0.8.8-next.0
+ - @backstage/plugin-github-actions@0.5.5-next.0
+ - @backstage/plugin-airbrake@0.3.5-next.0
+ - @backstage/plugin-azure-devops@0.1.21-next.0
+ - @backstage/plugin-badges@0.2.29-next.0
+ - @backstage/plugin-catalog-graph@0.2.17-next.0
+ - @backstage/plugin-circleci@0.3.5-next.0
+ - @backstage/plugin-cloudbuild@0.3.5-next.0
+ - @backstage/plugin-code-coverage@0.1.32-next.0
+ - @backstage/plugin-explore@0.3.36-next.0
+ - @backstage/plugin-gocd@0.1.11-next.0
+ - @backstage/plugin-jenkins@0.7.4-next.0
+ - @backstage/plugin-kafka@0.3.5-next.0
+ - @backstage/plugin-kubernetes@0.6.5-next.0
+ - @backstage/plugin-lighthouse@0.3.5-next.0
+ - @backstage/plugin-pagerduty@0.3.32-next.0
+ - @backstage/plugin-rollbar@0.4.5-next.0
+ - @backstage/plugin-sentry@0.3.43-next.0
+ - @backstage/plugin-stack-overflow@0.1.1-next.0
+ - @backstage/plugin-tech-insights@0.2.1-next.0
+ - @backstage/plugin-todo@0.2.7-next.0
+
+## 0.2.70
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-permission-react@0.4.0
+ - @backstage/plugin-home@0.4.20
+ - @backstage/plugin-techdocs@1.1.0
+ - @backstage/plugin-catalog-react@1.0.1
+ - @backstage/cli@0.17.0
+ - @backstage/plugin-scaffolder@1.1.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-kubernetes@0.6.4
+ - @backstage/core-app-api@1.0.1
+ - @backstage/core-components@0.9.3
+ - @backstage/core-plugin-api@1.0.1
+ - @backstage/plugin-catalog-graph@0.2.16
+ - @backstage/plugin-catalog-import@0.8.7
+ - @backstage/plugin-kafka@0.3.4
+ - @backstage/plugin-lighthouse@0.3.4
+ - @backstage/plugin-rollbar@0.4.4
+ - @backstage/plugin-search-react@0.1.0
+ - @backstage/plugin-search@0.8.0
+ - @backstage/integration-react@1.0.1
+ - @backstage/plugin-airbrake@0.3.4
+ - @backstage/plugin-apache-airflow@0.1.12
+ - @backstage/plugin-api-docs@0.8.4
+ - @backstage/plugin-azure-devops@0.1.20
+ - @backstage/plugin-badges@0.2.28
+ - @backstage/plugin-catalog@1.1.0
+ - @backstage/plugin-circleci@0.3.4
+ - @backstage/plugin-cloudbuild@0.3.4
+ - @backstage/plugin-code-coverage@0.1.31
+ - @backstage/plugin-cost-insights@0.11.26
+ - @backstage/plugin-explore@0.3.35
+ - @backstage/plugin-gcalendar@0.3.0
+ - @backstage/plugin-gcp-projects@0.3.23
+ - @backstage/plugin-github-actions@0.5.4
+ - @backstage/plugin-gocd@0.1.10
+ - @backstage/plugin-graphiql@0.2.36
+ - @backstage/plugin-jenkins@0.7.3
+ - @backstage/plugin-newrelic@0.3.22
+ - @backstage/plugin-org@0.5.4
+ - @backstage/plugin-pagerduty@0.3.31
+ - @backstage/plugin-sentry@0.3.42
+ - @backstage/plugin-shortcuts@0.2.5
+ - @backstage/plugin-stack-overflow@0.1.0
+ - @backstage/plugin-tech-insights@0.2.0
+ - @backstage/plugin-tech-radar@0.5.11
+ - @backstage/plugin-todo@0.2.6
+ - @backstage/plugin-user-settings@0.4.3
+ - @backstage/plugin-search-common@0.3.3
+ - @backstage/plugin-catalog-common@1.0.1
+ - @backstage/app-defaults@1.0.1
+ - @backstage/plugin-newrelic-dashboard@0.1.12
+
+## 0.2.70-next.2
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-home@0.4.20-next.3
+ - @backstage/plugin-techdocs@1.1.0-next.3
+ - @backstage/cli@0.17.0-next.3
+ - @backstage/plugin-scaffolder@1.1.0-next.3
+ - @backstage/plugin-kubernetes@0.6.4-next.2
+ - @backstage/core-app-api@1.0.1-next.1
+ - @backstage/core-components@0.9.3-next.2
+ - @backstage/core-plugin-api@1.0.1-next.0
+ - @backstage/integration-react@1.0.1-next.2
+ - @backstage/plugin-airbrake@0.3.4-next.1
+ - @backstage/plugin-apache-airflow@0.1.12-next.1
+ - @backstage/plugin-api-docs@0.8.4-next.3
+ - @backstage/plugin-azure-devops@0.1.20-next.1
+ - @backstage/plugin-badges@0.2.28-next.1
+ - @backstage/plugin-catalog-graph@0.2.16-next.3
+ - @backstage/plugin-catalog-import@0.8.7-next.2
+ - @backstage/plugin-catalog-react@1.0.1-next.3
+ - @backstage/plugin-catalog@1.1.0-next.3
+ - @backstage/plugin-circleci@0.3.4-next.1
+ - @backstage/plugin-cloudbuild@0.3.4-next.1
+ - @backstage/plugin-code-coverage@0.1.31-next.1
+ - @backstage/plugin-cost-insights@0.11.26-next.1
+ - @backstage/plugin-explore@0.3.35-next.1
+ - @backstage/plugin-gcalendar@0.3.0-next.2
+ - @backstage/plugin-gcp-projects@0.3.23-next.1
+ - @backstage/plugin-github-actions@0.5.4-next.2
+ - @backstage/plugin-gocd@0.1.10-next.2
+ - @backstage/plugin-graphiql@0.2.36-next.2
+ - @backstage/plugin-jenkins@0.7.3-next.1
+ - @backstage/plugin-kafka@0.3.4-next.1
+ - @backstage/plugin-lighthouse@0.3.4-next.1
+ - @backstage/plugin-newrelic@0.3.22-next.1
+ - @backstage/plugin-org@0.5.4-next.3
+ - @backstage/plugin-pagerduty@0.3.31-next.1
+ - @backstage/plugin-rollbar@0.4.4-next.1
+ - @backstage/plugin-search@0.7.5-next.1
+ - @backstage/plugin-sentry@0.3.42-next.2
+ - @backstage/plugin-shortcuts@0.2.5-next.1
+ - @backstage/plugin-stack-overflow@0.1.0-next.1
+ - @backstage/plugin-tech-insights@0.2.0-next.1
+ - @backstage/plugin-tech-radar@0.5.11-next.2
+ - @backstage/plugin-todo@0.2.6-next.1
+ - @backstage/plugin-user-settings@0.4.3-next.1
+ - @backstage/app-defaults@1.0.1-next.2
+ - @backstage/plugin-search-react@0.1.0-next.0
+ - @backstage/plugin-permission-react@0.4.0-next.1
+ - @backstage/plugin-newrelic-dashboard@0.1.12-next.1
+
## 0.2.70-next.1
### Patch Changes
diff --git a/packages/app/package.json b/packages/app/package.json
index f8dc6127c8..6e98358a75 100644
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -1,63 +1,65 @@
{
"name": "example-app",
- "version": "0.2.70-next.1",
+ "version": "0.2.71-next.0",
"private": true,
"backstage": {
"role": "frontend"
},
"bundled": true,
"dependencies": {
- "@backstage/app-defaults": "^1.0.1-next.1",
- "@backstage/catalog-model": "^1.0.1-next.0",
- "@backstage/cli": "^0.17.0-next.1",
+ "@backstage/app-defaults": "^1.0.1",
+ "@backstage/catalog-model": "^1.0.1",
+ "@backstage/cli": "^0.17.1-next.0",
"@backstage/config": "^1.0.0",
- "@backstage/core-app-api": "^1.0.1-next.0",
- "@backstage/core-components": "^0.9.3-next.0",
- "@backstage/core-plugin-api": "^1.0.0",
- "@backstage/integration-react": "^1.0.1-next.1",
- "@backstage/plugin-airbrake": "^0.3.4-next.0",
- "@backstage/plugin-api-docs": "^0.8.4-next.1",
- "@backstage/plugin-azure-devops": "^0.1.20-next.0",
- "@backstage/plugin-apache-airflow": "^0.1.12-next.0",
- "@backstage/plugin-badges": "^0.2.28-next.0",
- "@backstage/plugin-catalog": "^1.1.0-next.1",
- "@backstage/plugin-catalog-common": "^1.0.1-next.1",
- "@backstage/plugin-catalog-graph": "^0.2.16-next.1",
- "@backstage/plugin-catalog-import": "^0.8.7-next.1",
- "@backstage/plugin-catalog-react": "^1.0.1-next.1",
- "@backstage/plugin-circleci": "^0.3.4-next.0",
- "@backstage/plugin-cloudbuild": "^0.3.4-next.0",
- "@backstage/plugin-code-coverage": "^0.1.31-next.0",
- "@backstage/plugin-cost-insights": "^0.11.26-next.0",
- "@backstage/plugin-explore": "^0.3.35-next.0",
- "@backstage/plugin-gcalendar": "^0.3.0-next.1",
- "@backstage/plugin-gcp-projects": "^0.3.23-next.0",
- "@backstage/plugin-github-actions": "^0.5.4-next.1",
- "@backstage/plugin-gocd": "^0.1.10-next.0",
- "@backstage/plugin-graphiql": "^0.2.36-next.0",
- "@backstage/plugin-home": "^0.4.20-next.1",
- "@backstage/plugin-jenkins": "^0.7.3-next.0",
- "@backstage/plugin-kafka": "^0.3.4-next.0",
- "@backstage/plugin-kubernetes": "^0.6.4-next.1",
- "@backstage/plugin-lighthouse": "^0.3.4-next.0",
- "@backstage/plugin-newrelic": "^0.3.22-next.0",
- "@backstage/plugin-newrelic-dashboard": "^0.1.12-next.0",
- "@backstage/plugin-org": "^0.5.4-next.1",
- "@backstage/plugin-pagerduty": "0.3.31-next.0",
- "@backstage/plugin-permission-react": "^0.4.0-next.0",
- "@backstage/plugin-rollbar": "^0.4.4-next.0",
- "@backstage/plugin-scaffolder": "^1.0.1-next.1",
- "@backstage/plugin-search": "^0.7.5-next.0",
- "@backstage/plugin-search-react": "^0.0.0",
- "@backstage/plugin-search-common": "^0.3.3-next.1",
- "@backstage/plugin-sentry": "^0.3.42-next.0",
- "@backstage/plugin-shortcuts": "^0.2.5-next.0",
- "@backstage/plugin-stack-overflow": "^0.1.0-next.0",
- "@backstage/plugin-tech-radar": "^0.5.11-next.1",
- "@backstage/plugin-techdocs": "^1.0.1-next.1",
- "@backstage/plugin-todo": "^0.2.6-next.0",
- "@backstage/plugin-user-settings": "^0.4.3-next.0",
- "@backstage/plugin-tech-insights": "^0.1.14-next.0",
+ "@backstage/core-app-api": "^1.0.1",
+ "@backstage/core-components": "^0.9.3",
+ "@backstage/core-plugin-api": "^1.0.1",
+ "@backstage/integration-react": "^1.1.0-next.0",
+ "@backstage/plugin-airbrake": "^0.3.5-next.0",
+ "@backstage/plugin-api-docs": "^0.8.5-next.0",
+ "@backstage/plugin-azure-devops": "^0.1.21-next.0",
+ "@backstage/plugin-apache-airflow": "^0.1.12",
+ "@backstage/plugin-badges": "^0.2.29-next.0",
+ "@backstage/plugin-catalog": "^1.2.0-next.0",
+ "@backstage/plugin-catalog-common": "^1.0.1",
+ "@backstage/plugin-catalog-graph": "^0.2.17-next.0",
+ "@backstage/plugin-catalog-import": "^0.8.8-next.0",
+ "@backstage/plugin-catalog-react": "^1.1.0-next.0",
+ "@backstage/plugin-circleci": "^0.3.5-next.0",
+ "@backstage/plugin-cloudbuild": "^0.3.5-next.0",
+ "@backstage/plugin-code-coverage": "^0.1.32-next.0",
+ "@backstage/plugin-cost-insights": "^0.11.26",
+ "@backstage/plugin-explore": "^0.3.36-next.0",
+ "@backstage/plugin-gcalendar": "^0.3.1-next.0",
+ "@backstage/plugin-gcp-projects": "^0.3.23",
+ "@backstage/plugin-github-actions": "^0.5.5-next.0",
+ "@backstage/plugin-gocd": "^0.1.11-next.0",
+ "@backstage/plugin-graphiql": "^0.2.36",
+ "@backstage/plugin-home": "^0.4.21-next.0",
+ "@backstage/plugin-jenkins": "^0.7.4-next.0",
+ "@backstage/plugin-kafka": "^0.3.5-next.0",
+ "@backstage/plugin-kubernetes": "^0.6.5-next.0",
+ "@backstage/plugin-lighthouse": "^0.3.5-next.0",
+ "@backstage/plugin-newrelic": "^0.3.22",
+ "@backstage/plugin-newrelic-dashboard": "^0.1.13-next.0",
+ "@backstage/plugin-org": "^0.5.5-next.0",
+ "@backstage/plugin-pagerduty": "0.3.32-next.0",
+ "@backstage/plugin-permission-react": "^0.4.0",
+ "@backstage/plugin-rollbar": "^0.4.5-next.0",
+ "@backstage/plugin-scaffolder": "^1.2.0-next.0",
+ "@backstage/plugin-search": "^0.8.1-next.0",
+ "@backstage/plugin-search-react": "^0.1.1-next.0",
+ "@backstage/plugin-search-common": "^0.3.3",
+ "@backstage/plugin-sentry": "^0.3.43-next.0",
+ "@backstage/plugin-shortcuts": "^0.2.5",
+ "@backstage/plugin-stack-overflow": "^0.1.1-next.0",
+ "@backstage/plugin-tech-radar": "^0.5.11",
+ "@backstage/plugin-techdocs": "^1.1.1-next.0",
+ "@backstage/plugin-techdocs-react": "^0.1.1-next.0",
+ "@backstage/plugin-techdocs-module-addons-contrib": "^0.1.0-next.0",
+ "@backstage/plugin-todo": "^0.2.7-next.0",
+ "@backstage/plugin-user-settings": "^0.4.3",
+ "@backstage/plugin-tech-insights": "^0.2.1-next.0",
"@backstage/theme": "^0.2.15",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
@@ -78,8 +80,7 @@
"zen-observable": "^0.8.15"
},
"devDependencies": {
- "@backstage/plugin-permission-react": "^0.4.0-next.0",
- "@backstage/test-utils": "^1.0.1-next.1",
+ "@backstage/test-utils": "^1.0.2-next.0",
"@rjsf/core": "^3.2.1",
"@testing-library/cypress": "^8.0.2",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx
index 9cbbcc86a9..4cf2c02e55 100644
--- a/packages/app/src/App.tsx
+++ b/packages/app/src/App.tsx
@@ -66,9 +66,11 @@ import { SearchPage } from '@backstage/plugin-search';
import { TechRadarPage } from '@backstage/plugin-tech-radar';
import {
TechDocsIndexPage,
- techdocsPlugin,
TechDocsReaderPage,
+ techdocsPlugin,
} from '@backstage/plugin-techdocs';
+import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
+import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
import {
UserSettingsPage,
UserSettingsTab,
@@ -87,6 +89,7 @@ import { defaultPreviewTemplate } from './components/scaffolder/defaultPreviewTe
import { searchPage } from './components/search/SearchPage';
import { providers } from './identityProviders';
import * as plugins from './plugins';
+
import { techDocsPage } from './components/techdocs/TechDocsPage';
import { ApacheAirflowPage } from '@backstage/plugin-apache-airflow';
import { PermissionedRoute } from '@backstage/plugin-permission-react';
@@ -178,6 +181,9 @@ const routes = (
element={}
>
{techDocsPage}
+
+
+ ) => (
} to="/search">
-
+
+ {({ toggleModal }) => }
+ }>
diff --git a/packages/app/src/components/home/HomePage.tsx b/packages/app/src/components/home/HomePage.tsx
index 6c8867ac28..2cd5481c91 100644
--- a/packages/app/src/components/home/HomePage.tsx
+++ b/packages/app/src/components/home/HomePage.tsx
@@ -22,6 +22,7 @@ import {
WelcomeTitle,
HeaderWorldClock,
ClockConfig,
+ HomePageStarredEntities,
} from '@backstage/plugin-home';
import { Content, Header, Page } from '@backstage/core-components';
import { HomePageSearchBar } from '@backstage/plugin-search';
@@ -104,6 +105,9 @@ export const homePage = (
+
+
+
diff --git a/packages/app/src/components/search/SearchModal.tsx b/packages/app/src/components/search/SearchModal.tsx
new file mode 100644
index 0000000000..f75017a4dd
--- /dev/null
+++ b/packages/app/src/components/search/SearchModal.tsx
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import {
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Grid,
+ List,
+ makeStyles,
+ Paper,
+ useTheme,
+} from '@material-ui/core';
+import LaunchIcon from '@material-ui/icons/Launch';
+import { Link, useContent } from '@backstage/core-components';
+import { useApi, useRouteRef } from '@backstage/core-plugin-api';
+import { CatalogSearchResultListItem } from '@backstage/plugin-catalog';
+import {
+ catalogApiRef,
+ CATALOG_FILTER_EXISTS,
+} from '@backstage/plugin-catalog-react';
+import {
+ DefaultResultListItem,
+ SearchBar,
+ SearchFilter,
+ searchPlugin,
+ SearchResult,
+ SearchResultPager,
+ SearchType,
+} from '@backstage/plugin-search';
+import { useSearch } from '@backstage/plugin-search-react';
+import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
+
+const useStyles = makeStyles(theme => ({
+ container: {
+ borderRadius: 30,
+ display: 'flex',
+ height: '2.4em',
+ },
+ filter: {
+ '& + &': {
+ marginTop: theme.spacing(2.5),
+ },
+ },
+ filters: {
+ padding: theme.spacing(2),
+ marginTop: theme.spacing(2),
+ },
+ input: {
+ flex: 1,
+ },
+ dialogActionsContainer: { padding: theme.spacing(1, 3) },
+ viewResultsLink: { verticalAlign: '0.5em' },
+}));
+
+export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => {
+ const getSearchLink = useRouteRef(searchPlugin.routes.root);
+ const classes = useStyles();
+
+ const catalogApi = useApi(catalogApiRef);
+ const { term, types } = useSearch();
+ const { focusContent } = useContent();
+ const { transitions } = useTheme();
+
+ const handleResultClick = () => {
+ toggleModal();
+ setTimeout(focusContent, transitions.duration.leavingScreen);
+ };
+
+ const handleKeyPress = () => {
+ handleResultClick();
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ {types.includes('techdocs') && (
+
+ {
+ // Return a list of entities which are documented.
+ const { items } = await catalogApi.getEntities({
+ fields: ['metadata.name'],
+ filter: {
+ 'metadata.annotations.backstage.io/techdocs-ref':
+ CATALOG_FILTER_EXISTS,
+ },
+ });
+
+ const names = items.map(entity => entity.metadata.name);
+ names.sort();
+ return names;
+ }}
+ />
+
+ )}
+
+
+
+
+
+
+
+
+ {
+ toggleModal();
+ setTimeout(
+ focusContent,
+ transitions.duration.leavingScreen,
+ );
+ }}
+ to={`${getSearchLink()}?query=${term}`}
+ >
+
+ View Full Results
+
+
+
+
+
+
+
+
+ {({ results }) => (
+
+ {results.map(({ type, document }) => {
+ let resultItem;
+ switch (type) {
+ case 'software-catalog':
+ resultItem = (
+
+ );
+ break;
+ case 'techdocs':
+ resultItem = (
+
+ );
+ break;
+ default:
+ resultItem = (
+
+ );
+ }
+ return (
+
+ {resultItem}
+
+ );
+ })}
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx
index 65da72d91c..fd9c80686c 100644
--- a/packages/app/src/components/search/SearchPage.tsx
+++ b/packages/app/src/components/search/SearchPage.tsx
@@ -36,8 +36,8 @@ import {
SearchResult,
SearchResultPager,
SearchType,
- useSearch,
} from '@backstage/plugin-search';
+import { useSearch } from '@backstage/plugin-search-react';
import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
import { Grid, List, makeStyles, Paper, Theme } from '@material-ui/core';
import React, { useContext } from 'react';
diff --git a/packages/app/src/components/techdocs/TechDocsPage.tsx b/packages/app/src/components/techdocs/TechDocsPage.tsx
index 4f49cf38e8..d79acbe0a7 100644
--- a/packages/app/src/components/techdocs/TechDocsPage.tsx
+++ b/packages/app/src/components/techdocs/TechDocsPage.tsx
@@ -14,30 +14,21 @@
* limitations under the License.
*/
-import { Content } from '@backstage/core-components';
+import React from 'react';
+import { Page } from '@backstage/core-components';
import {
TechDocsReaderPageHeader,
- TechDocsReaderPage,
- Reader,
+ TechDocsReaderPageSubheader,
+ TechDocsReaderPageContent,
} from '@backstage/plugin-techdocs';
-import React from 'react';
const DefaultTechDocsPage = () => {
return (
-
- {({ techdocsMetadataValue, entityMetadataValue, entityRef, onReady }) => (
- <>
-
-
-
-
- >
- )}
-
+
+
+
+
+
);
};
diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md
index e8adcd9181..d64b199d6c 100644
--- a/packages/backend-common/CHANGELOG.md
+++ b/packages/backend-common/CHANGELOG.md
@@ -1,5 +1,46 @@
# @backstage/backend-common
+## 0.13.3-next.0
+
+### Patch Changes
+
+- 6673babab9: Gerrit integration: Added optional `cloneUrl` string to config.
+- 75bf9e1da9: Split BitbucketUrlReader into BitbucketCloudUrlReader and BitbucketServerUrlReader. Backwards compatible.
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- 9ec4e0613e: Update to `jose` 4.6.0
+- Updated dependencies
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/config-loader@1.1.1-next.0
+
+## 0.13.2
+
+### Patch Changes
+
+- 19f6c6c32a: The backend will no longer fail to start up when configured secrets do not match the configuration schema.
+- b7436743cb: Added the GerritUrlReader that implements "readUrl".
+- 3ef123bbf0: Support external ID when assuming roles in S3 integration
+
+ In order to assume a role created by a 3rd party as external
+ ID is needed. This change adds an optional field to the s3
+ integration configuration and consumes that in the AwsS3UrlReader.
+
+- bae9359032: The logger returned from `getVoidLogger` is now uses a silenced console transport instead.
+- 3ff0e79654: Tweaked the `UrlReader` multiplexer so that it uses the more helpful `NotAllowedError` messaging for all methods.
+- 12608f8ba8: Add `@types/webpack-env` to dependencies.
+- f9f512559b: Updated the visibility of database connection fields in config to be secret
+- Updated dependencies
+ - @backstage/integration@1.1.0
+ - @backstage/config-loader@1.1.0
+
+## 0.13.2-next.2
+
+### Patch Changes
+
+- 19f6c6c32a: The backend will no longer fail to start up when configured secrets do not match the configuration schema.
+- Updated dependencies
+ - @backstage/config-loader@1.1.0-next.1
+ - @backstage/integration@1.1.0-next.2
+
## 0.13.2-next.1
### Patch Changes
diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md
index cd4d08df87..961973b144 100644
--- a/packages/backend-common/api-report.md
+++ b/packages/backend-common/api-report.md
@@ -10,7 +10,9 @@ import { AbortController as AbortController_2 } from 'node-abort-controller';
import { AbortSignal as AbortSignal_2 } from 'node-abort-controller';
import { AwsS3Integration } from '@backstage/integration';
import { AzureIntegration } from '@backstage/integration';
+import { BitbucketCloudIntegration } from '@backstage/integration';
import { BitbucketIntegration } from '@backstage/integration';
+import { BitbucketServerIntegration } from '@backstage/integration';
import { Config } from '@backstage/config';
import cors from 'cors';
import Docker from 'dockerode';
@@ -83,9 +85,54 @@ export class AzureUrlReader implements UrlReader {
}
// @public
+export class BitbucketCloudUrlReader implements UrlReader {
+ constructor(
+ integration: BitbucketCloudIntegration,
+ deps: {
+ treeResponseFactory: ReadTreeResponseFactory;
+ },
+ );
+ // (undocumented)
+ static factory: ReaderFactory;
+ // (undocumented)
+ read(url: string): Promise;
+ // (undocumented)
+ readTree(url: string, options?: ReadTreeOptions): Promise;
+ // (undocumented)
+ readUrl(url: string, options?: ReadUrlOptions): Promise;
+ // (undocumented)
+ search(url: string, options?: SearchOptions): Promise;
+ // (undocumented)
+ toString(): string;
+}
+
+// @public
+export class BitbucketServerUrlReader implements UrlReader {
+ constructor(
+ integration: BitbucketServerIntegration,
+ deps: {
+ treeResponseFactory: ReadTreeResponseFactory;
+ },
+ );
+ // (undocumented)
+ static factory: ReaderFactory;
+ // (undocumented)
+ read(url: string): Promise;
+ // (undocumented)
+ readTree(url: string, options?: ReadTreeOptions): Promise;
+ // (undocumented)
+ readUrl(url: string, options?: ReadUrlOptions): Promise;
+ // (undocumented)
+ search(url: string, options?: SearchOptions): Promise;
+ // (undocumented)
+ toString(): string;
+}
+
+// @public @deprecated
export class BitbucketUrlReader implements UrlReader {
constructor(
integration: BitbucketIntegration,
+ logger: Logger,
deps: {
treeResponseFactory: ReadTreeResponseFactory;
},
@@ -175,7 +222,7 @@ export class Contexts {
export function createDatabaseClient(
dbConfig: Config,
overrides?: Partial,
-): Knex[]>;
+): Knex;
// @public
export function createRootLogger(
@@ -255,13 +302,19 @@ export type FromReadableArrayOptions = Array<{
// @public
export class GerritUrlReader implements UrlReader {
- constructor(integration: GerritIntegration);
+ constructor(
+ integration: GerritIntegration,
+ deps: {
+ treeResponseFactory: ReadTreeResponseFactory;
+ },
+ workDir: string,
+ );
// (undocumented)
static factory: ReaderFactory;
// (undocumented)
read(url: string): Promise;
// (undocumented)
- readTree(): Promise;
+ readTree(url: string, options?: ReadTreeOptions): Promise;
// (undocumented)
readUrl(url: string, options?: ReadUrlOptions): Promise;
// (undocumented)
diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json
index bc2b25e4f4..d66465a471 100644
--- a/packages/backend-common/package.json
+++ b/packages/backend-common/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-common",
"description": "Common functionality library for Backstage backends",
- "version": "0.13.2-next.1",
+ "version": "0.13.3-next.0",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -36,9 +36,9 @@
"dependencies": {
"@backstage/cli-common": "^0.1.8",
"@backstage/config": "^1.0.0",
- "@backstage/config-loader": "^1.0.1-next.0",
+ "@backstage/config-loader": "^1.1.1-next.0",
"@backstage/errors": "^1.0.0",
- "@backstage/integration": "^1.1.0-next.1",
+ "@backstage/integration": "^1.2.0-next.0",
"@backstage/types": "^1.0.0",
"@google-cloud/storage": "^5.8.0",
"@manypkg/get-packages": "^1.1.3",
@@ -47,6 +47,7 @@
"@types/dockerode": "^3.3.0",
"@types/express": "^4.17.6",
"@types/luxon": "^2.0.4",
+ "@types/webpack-env": "^1.15.2",
"archiver": "^5.0.2",
"aws-sdk": "^2.840.0",
"compression": "^1.7.4",
@@ -55,11 +56,11 @@
"dockerode": "^3.3.1",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
- "fs-extra": "10.0.1",
+ "fs-extra": "10.1.0",
"git-url-parse": "^11.6.0",
"helmet": "^5.0.2",
"isomorphic-git": "^1.8.0",
- "jose": "^1.27.1",
+ "jose": "^4.6.0",
"keyv": "^4.0.3",
"keyv-memcache": "^1.2.5",
"@keyv/redis": "^2.2.3",
@@ -89,8 +90,8 @@
}
},
"devDependencies": {
- "@backstage/backend-test-utils": "^0.1.23-next.1",
- "@backstage/cli": "^0.17.0-next.1",
+ "@backstage/backend-test-utils": "^0.1.24-next.0",
+ "@backstage/cli": "^0.17.1-next.0",
"@types/archiver": "^5.1.0",
"@types/compression": "^1.7.0",
"@types/concat-stream": "^2.0.0",
diff --git a/packages/backend-common/src/cache/CacheManager.test.ts b/packages/backend-common/src/cache/CacheManager.test.ts
index c6cad2e49b..82c04f2cdd 100644
--- a/packages/backend-common/src/cache/CacheManager.test.ts
+++ b/packages/backend-common/src/cache/CacheManager.test.ts
@@ -18,7 +18,6 @@ import { ConfigReader } from '@backstage/config';
import Keyv from 'keyv';
/* @ts-expect-error */
import KeyvMemcache from 'keyv-memcache';
-/* @ts-expect-error */
import KeyvRedis from '@keyv/redis';
import { DefaultCacheClient } from './CacheClient';
import { CacheManager } from './CacheManager';
@@ -215,7 +214,7 @@ describe('CacheManager', () => {
ttl: expectedTtl,
});
expect(mockCacheCalls[0][0].store).toBeInstanceOf(KeyvRedis);
- const redis = KeyvRedis as jest.Mock;
+ const redis = KeyvRedis as unknown as jest.Mock;
const mockRedisCalls = redis.mock.calls.splice(-1);
expect(mockRedisCalls[0][0]).toEqual(redisConnection);
});
diff --git a/packages/backend-common/src/cache/CacheManager.ts b/packages/backend-common/src/cache/CacheManager.ts
index d8652e42d8..99e3770ada 100644
--- a/packages/backend-common/src/cache/CacheManager.ts
+++ b/packages/backend-common/src/cache/CacheManager.ts
@@ -18,7 +18,6 @@ import { Config } from '@backstage/config';
import Keyv from 'keyv';
// @ts-expect-error
import KeyvMemcache from 'keyv-memcache';
-// @ts-expect-error
import KeyvRedis from '@keyv/redis';
import { Logger } from 'winston';
import { getRootLogger } from '../logging';
diff --git a/packages/backend-common/src/reading/BitbucketCloudUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketCloudUrlReader.test.ts
new file mode 100644
index 0000000000..38841d75ad
--- /dev/null
+++ b/packages/backend-common/src/reading/BitbucketCloudUrlReader.test.ts
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ConfigReader } from '@backstage/config';
+import {
+ BitbucketCloudIntegration,
+ readBitbucketCloudIntegrationConfig,
+} from '@backstage/integration';
+import { setupRequestMockHandlers } from '@backstage/backend-test-utils';
+import fs from 'fs-extra';
+import mockFs from 'mock-fs';
+import { rest } from 'msw';
+import { setupServer } from 'msw/node';
+import os from 'os';
+import path from 'path';
+import { NotModifiedError } from '@backstage/errors';
+import { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader';
+import { DefaultReadTreeResponseFactory } from './tree';
+
+const treeResponseFactory = DefaultReadTreeResponseFactory.create({
+ config: new ConfigReader({}),
+});
+
+const reader = new BitbucketCloudUrlReader(
+ new BitbucketCloudIntegration(
+ readBitbucketCloudIntegrationConfig(
+ new ConfigReader({
+ host: 'bitbucket.org',
+ apiBaseUrl: 'https://api.bitbucket.org/2.0',
+ username: 'username',
+ appPassword: 'password',
+ }),
+ ),
+ ),
+ { treeResponseFactory },
+);
+
+const tmpDir = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp';
+
+describe('BitbucketCloudUrlReader', () => {
+ beforeEach(() => {
+ mockFs({
+ [tmpDir]: mockFs.directory(),
+ });
+ });
+
+ afterEach(() => {
+ mockFs.restore();
+ });
+
+ const worker = setupServer();
+ setupRequestMockHandlers(worker);
+
+ describe('readUrl', () => {
+ it('should be able to readUrl without ETag', async () => {
+ worker.use(
+ rest.get(
+ 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml',
+ (req, res, ctx) => {
+ expect(req.headers.get('If-None-Match')).toBeNull();
+ return res(
+ ctx.status(200),
+ ctx.body('foo'),
+ ctx.set('ETag', 'etag-value'),
+ );
+ },
+ ),
+ );
+
+ const result = await reader.readUrl(
+ 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml',
+ );
+ const buffer = await result.buffer();
+ expect(buffer.toString()).toBe('foo');
+ });
+
+ it('should be able to readUrl with matching ETag', async () => {
+ worker.use(
+ rest.get(
+ 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml',
+ (req, res, ctx) => {
+ expect(req.headers.get('If-None-Match')).toBe(
+ 'matching-etag-value',
+ );
+ return res(ctx.status(304));
+ },
+ ),
+ );
+
+ await expect(
+ reader.readUrl(
+ 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml',
+ { etag: 'matching-etag-value' },
+ ),
+ ).rejects.toThrow(NotModifiedError);
+ });
+
+ it('should be able to readUrl without matching ETag', async () => {
+ worker.use(
+ rest.get(
+ 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml',
+ (req, res, ctx) => {
+ expect(req.headers.get('If-None-Match')).toBe(
+ 'previous-etag-value',
+ );
+ return res(
+ ctx.status(200),
+ ctx.body('foo'),
+ ctx.set('ETag', 'new-etag-value'),
+ );
+ },
+ ),
+ );
+
+ const result = await reader.readUrl(
+ 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml',
+ { etag: 'previous-etag-value' },
+ );
+ const buffer = await result.buffer();
+ expect(buffer.toString()).toBe('foo');
+ expect(result.etag).toBe('new-etag-value');
+ });
+ });
+
+ describe('read', () => {
+ it('rejects unknown targets', async () => {
+ await expect(
+ reader.read('https://not.bitbucket.com/apa'),
+ ).rejects.toThrow(
+ 'Incorrect URL: https://not.bitbucket.com/apa, Error: Invalid Bitbucket Cloud URL or file path',
+ );
+ });
+ });
+
+ describe('readTree', () => {
+ const repoBuffer = fs.readFileSync(
+ path.resolve(
+ __dirname,
+ '__fixtures__/bitbucket-repo-with-commit-hash.tar.gz',
+ ),
+ );
+
+ beforeEach(() => {
+ worker.use(
+ rest.get(
+ 'https://api.bitbucket.org/2.0/repositories/backstage/mock',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.json({
+ mainbranch: {
+ type: 'branch',
+ name: 'master',
+ },
+ }),
+ ),
+ ),
+ rest.get(
+ 'https://bitbucket.org/backstage/mock/get/master.tar.gz',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.set('Content-Type', 'application/zip'),
+ ctx.set(
+ 'content-disposition',
+ 'attachment; filename=backstage-mock-12ab34cd56ef.tar.gz',
+ ),
+ ctx.body(repoBuffer),
+ ),
+ ),
+ rest.get(
+ 'https://api.bitbucket.org/2.0/repositories/backstage/mock/commits/master',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.json({
+ values: [{ hash: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }],
+ }),
+ ),
+ ),
+ );
+ });
+
+ it('returns the wanted files from an archive', async () => {
+ const response = await reader.readTree(
+ 'https://bitbucket.org/backstage/mock/src/master',
+ );
+
+ expect(response.etag).toBe('12ab34cd56ef');
+
+ const files = await response.files();
+
+ expect(files.length).toBe(2);
+ const mkDocsFile = await files[0].content();
+ const indexMarkdownFile = await files[1].content();
+
+ expect(indexMarkdownFile.toString()).toBe('# Test\n');
+ expect(mkDocsFile.toString()).toBe('site_name: Test\n');
+ });
+
+ it('creates a directory with the wanted files', async () => {
+ const response = await reader.readTree(
+ 'https://bitbucket.org/backstage/mock',
+ );
+
+ const dir = await response.dir({ targetDir: tmpDir });
+
+ await expect(
+ fs.readFile(path.join(dir, 'mkdocs.yml'), 'utf8'),
+ ).resolves.toBe('site_name: Test\n');
+ await expect(
+ fs.readFile(path.join(dir, 'docs', 'index.md'), 'utf8'),
+ ).resolves.toBe('# Test\n');
+ });
+
+ it('returns the wanted files from an archive with a subpath', async () => {
+ const response = await reader.readTree(
+ 'https://bitbucket.org/backstage/mock/src/master/docs',
+ );
+
+ expect(response.etag).toBe('12ab34cd56ef');
+
+ const files = await response.files();
+
+ expect(files.length).toBe(1);
+ const indexMarkdownFile = await files[0].content();
+
+ expect(indexMarkdownFile.toString()).toBe('# Test\n');
+ });
+
+ it('creates a directory with the wanted files with a subpath', async () => {
+ const response = await reader.readTree(
+ 'https://bitbucket.org/backstage/mock/src/master/docs',
+ );
+
+ const dir = await response.dir({ targetDir: tmpDir });
+
+ await expect(
+ fs.readFile(path.join(dir, 'index.md'), 'utf8'),
+ ).resolves.toBe('# Test\n');
+ });
+
+ it('throws a NotModifiedError when given a etag in options', async () => {
+ const fnBitbucket = async () => {
+ await reader.readTree('https://bitbucket.org/backstage/mock', {
+ etag: '12ab34cd56ef',
+ });
+ };
+
+ await expect(fnBitbucket).rejects.toThrow(NotModifiedError);
+ });
+
+ it('should not throw a NotModifiedError when given an outdated etag in options', async () => {
+ const response = await reader.readTree(
+ 'https://bitbucket.org/backstage/mock',
+ { etag: 'outdatedetag123abc' },
+ );
+
+ expect(response.etag).toBe('12ab34cd56ef');
+ });
+ });
+
+ describe('search hosted', () => {
+ const repoBuffer = fs.readFileSync(
+ path.resolve(
+ __dirname,
+ '__fixtures__/bitbucket-repo-with-commit-hash.tar.gz',
+ ),
+ );
+
+ beforeEach(() => {
+ worker.use(
+ rest.get(
+ 'https://api.bitbucket.org/2.0/repositories/backstage/mock',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.json({
+ mainbranch: {
+ type: 'branch',
+ name: 'master',
+ },
+ }),
+ ),
+ ),
+ rest.get(
+ 'https://bitbucket.org/backstage/mock/get/master.tar.gz',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.set('Content-Type', 'application/zip'),
+ ctx.set(
+ 'content-disposition',
+ 'attachment; filename=backstage-mock-12ab34cd56ef.tar.gz',
+ ),
+ ctx.body(repoBuffer),
+ ),
+ ),
+ rest.get(
+ 'https://api.bitbucket.org/2.0/repositories/backstage/mock/commits/master',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.json({
+ values: [{ hash: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }],
+ }),
+ ),
+ ),
+ );
+ });
+
+ it('works for the naive case', async () => {
+ const result = await reader.search(
+ 'https://bitbucket.org/backstage/mock/src/master/**/index.*',
+ );
+ expect(result.etag).toBe('12ab34cd56ef');
+ expect(result.files.length).toBe(1);
+ expect(result.files[0].url).toBe(
+ 'https://bitbucket.org/backstage/mock/src/master/docs/index.md',
+ );
+ await expect(result.files[0].content()).resolves.toEqual(
+ Buffer.from('# Test\n'),
+ );
+ });
+
+ it('works in nested folders', async () => {
+ const result = await reader.search(
+ 'https://bitbucket.org/backstage/mock/src/master/docs/index.*',
+ );
+ expect(result.etag).toBe('12ab34cd56ef');
+ expect(result.files.length).toBe(1);
+ expect(result.files[0].url).toBe(
+ 'https://bitbucket.org/backstage/mock/src/master/docs/index.md',
+ );
+ await expect(result.files[0].content()).resolves.toEqual(
+ Buffer.from('# Test\n'),
+ );
+ });
+
+ it('throws NotModifiedError when same etag', async () => {
+ await expect(
+ reader.search(
+ 'https://bitbucket.org/backstage/mock/src/master/**/index.*',
+ { etag: '12ab34cd56ef' },
+ ),
+ ).rejects.toThrow(NotModifiedError);
+ });
+ });
+});
diff --git a/packages/backend-common/src/reading/BitbucketCloudUrlReader.ts b/packages/backend-common/src/reading/BitbucketCloudUrlReader.ts
new file mode 100644
index 0000000000..6a9406e920
--- /dev/null
+++ b/packages/backend-common/src/reading/BitbucketCloudUrlReader.ts
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { NotFoundError, NotModifiedError } from '@backstage/errors';
+import {
+ BitbucketCloudIntegration,
+ getBitbucketCloudDefaultBranch,
+ getBitbucketCloudDownloadUrl,
+ getBitbucketCloudFileFetchUrl,
+ getBitbucketCloudRequestOptions,
+ ScmIntegrations,
+} from '@backstage/integration';
+import fetch, { Response } from 'node-fetch';
+import parseGitUrl from 'git-url-parse';
+import { trimEnd } from 'lodash';
+import { Minimatch } from 'minimatch';
+import { Readable } from 'stream';
+import {
+ ReaderFactory,
+ ReadTreeOptions,
+ ReadTreeResponse,
+ ReadTreeResponseFactory,
+ ReadUrlOptions,
+ ReadUrlResponse,
+ SearchOptions,
+ SearchResponse,
+ UrlReader,
+} from './types';
+
+/**
+ * Implements a {@link UrlReader} for files from Bitbucket Cloud.
+ *
+ * @public
+ */
+export class BitbucketCloudUrlReader implements UrlReader {
+ static factory: ReaderFactory = ({ config, treeResponseFactory }) => {
+ const integrations = ScmIntegrations.fromConfig(config);
+ return integrations.bitbucketCloud.list().map(integration => {
+ const reader = new BitbucketCloudUrlReader(integration, {
+ treeResponseFactory,
+ });
+ const predicate = (url: URL) => url.host === integration.config.host;
+ return { reader, predicate };
+ });
+ };
+
+ constructor(
+ private readonly integration: BitbucketCloudIntegration,
+ private readonly deps: { treeResponseFactory: ReadTreeResponseFactory },
+ ) {
+ const { host, username, appPassword } = integration.config;
+
+ if (username && !appPassword) {
+ throw new Error(
+ `Bitbucket Cloud integration for '${host}' has configured a username but is missing a required appPassword.`,
+ );
+ }
+ }
+
+ async read(url: string): Promise {
+ const response = await this.readUrl(url);
+ return response.buffer();
+ }
+
+ async readUrl(
+ url: string,
+ options?: ReadUrlOptions,
+ ): Promise {
+ const { etag, signal } = options ?? {};
+ const bitbucketUrl = getBitbucketCloudFileFetchUrl(
+ url,
+ this.integration.config,
+ );
+ const requestOptions = getBitbucketCloudRequestOptions(
+ this.integration.config,
+ );
+
+ let response: Response;
+ try {
+ response = await fetch(bitbucketUrl.toString(), {
+ headers: {
+ ...requestOptions.headers,
+ ...(etag && { 'If-None-Match': etag }),
+ },
+ // TODO(freben): The signal cast is there because pre-3.x versions of
+ // node-fetch have a very slightly deviating AbortSignal type signature.
+ // The difference does not affect us in practice however. The cast can be
+ // removed after we support ESM for CLI dependencies and migrate to
+ // version 3 of node-fetch.
+ // https://github.com/backstage/backstage/issues/8242
+ ...(signal && { signal: signal as any }),
+ });
+ } catch (e) {
+ throw new Error(`Unable to read ${url}, ${e}`);
+ }
+
+ if (response.status === 304) {
+ throw new NotModifiedError();
+ }
+
+ if (response.ok) {
+ return {
+ buffer: async () => Buffer.from(await response.arrayBuffer()),
+ etag: response.headers.get('ETag') ?? undefined,
+ };
+ }
+
+ const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`;
+ if (response.status === 404) {
+ throw new NotFoundError(message);
+ }
+ throw new Error(message);
+ }
+
+ async readTree(
+ url: string,
+ options?: ReadTreeOptions,
+ ): Promise {
+ const { filepath } = parseGitUrl(url);
+
+ const lastCommitShortHash = await this.getLastCommitShortHash(url);
+ if (options?.etag && options.etag === lastCommitShortHash) {
+ throw new NotModifiedError();
+ }
+
+ const downloadUrl = await getBitbucketCloudDownloadUrl(
+ url,
+ this.integration.config,
+ );
+ const archiveResponse = await fetch(
+ downloadUrl,
+ getBitbucketCloudRequestOptions(this.integration.config),
+ );
+ if (!archiveResponse.ok) {
+ const message = `Failed to read tree from ${url}, ${archiveResponse.status} ${archiveResponse.statusText}`;
+ if (archiveResponse.status === 404) {
+ throw new NotFoundError(message);
+ }
+ throw new Error(message);
+ }
+
+ return await this.deps.treeResponseFactory.fromTarArchive({
+ stream: archiveResponse.body as unknown as Readable,
+ subpath: filepath,
+ etag: lastCommitShortHash,
+ filter: options?.filter,
+ });
+ }
+
+ async search(url: string, options?: SearchOptions): Promise {
+ const { filepath } = parseGitUrl(url);
+ const matcher = new Minimatch(filepath);
+
+ // TODO(freben): For now, read the entire repo and filter through that. In
+ // a future improvement, we could be smart and try to deduce that non-glob
+ // prefixes (like for filepaths such as some-prefix/**/a.yaml) can be used
+ // to get just that part of the repo.
+ const treeUrl = trimEnd(url.replace(filepath, ''), '/');
+
+ const tree = await this.readTree(treeUrl, {
+ etag: options?.etag,
+ filter: path => matcher.match(path),
+ });
+ const files = await tree.files();
+
+ return {
+ etag: tree.etag,
+ files: files.map(file => ({
+ url: this.integration.resolveUrl({
+ url: `/${file.path}`,
+ base: url,
+ }),
+ content: file.content,
+ })),
+ };
+ }
+
+ toString() {
+ const { host, username, appPassword } = this.integration.config;
+ const authed = Boolean(username && appPassword);
+ return `bitbucketCloud{host=${host},authed=${authed}}`;
+ }
+
+ private async getLastCommitShortHash(url: string): Promise {
+ const { name: repoName, owner: project, ref } = parseGitUrl(url);
+
+ let branch = ref;
+ if (!branch) {
+ branch = await getBitbucketCloudDefaultBranch(
+ url,
+ this.integration.config,
+ );
+ }
+
+ const commitsApiUrl = `${this.integration.config.apiBaseUrl}/repositories/${project}/${repoName}/commits/${branch}`;
+
+ const commitsResponse = await fetch(
+ commitsApiUrl,
+ getBitbucketCloudRequestOptions(this.integration.config),
+ );
+ if (!commitsResponse.ok) {
+ const message = `Failed to retrieve commits from ${commitsApiUrl}, ${commitsResponse.status} ${commitsResponse.statusText}`;
+ if (commitsResponse.status === 404) {
+ throw new NotFoundError(message);
+ }
+ throw new Error(message);
+ }
+
+ const commits = await commitsResponse.json();
+ if (
+ commits &&
+ commits.values &&
+ commits.values.length > 0 &&
+ commits.values[0].hash
+ ) {
+ return commits.values[0].hash.substring(0, 12);
+ }
+
+ throw new Error(`Failed to read response from ${commitsApiUrl}`);
+ }
+}
diff --git a/packages/backend-common/src/reading/BitbucketServerUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketServerUrlReader.test.ts
new file mode 100644
index 0000000000..1417752494
--- /dev/null
+++ b/packages/backend-common/src/reading/BitbucketServerUrlReader.test.ts
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ConfigReader } from '@backstage/config';
+import {
+ BitbucketServerIntegration,
+ readBitbucketServerIntegrationConfig,
+} from '@backstage/integration';
+import { setupRequestMockHandlers } from '@backstage/backend-test-utils';
+import fs from 'fs-extra';
+import mockFs from 'mock-fs';
+import { rest } from 'msw';
+import { setupServer } from 'msw/node';
+import os from 'os';
+import path from 'path';
+import { NotModifiedError } from '@backstage/errors';
+import { BitbucketServerUrlReader } from './BitbucketServerUrlReader';
+import { DefaultReadTreeResponseFactory } from './tree';
+
+const treeResponseFactory = DefaultReadTreeResponseFactory.create({
+ config: new ConfigReader({}),
+});
+
+const reader = new BitbucketServerUrlReader(
+ new BitbucketServerIntegration(
+ readBitbucketServerIntegrationConfig(
+ new ConfigReader({
+ host: 'bitbucket.mycompany.net',
+ apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0',
+ }),
+ ),
+ ),
+ { treeResponseFactory },
+);
+
+const tmpDir = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp';
+
+describe('BitbucketServerUrlReader', () => {
+ beforeEach(() => {
+ mockFs({
+ [tmpDir]: mockFs.directory(),
+ });
+ });
+
+ afterEach(() => {
+ mockFs.restore();
+ });
+
+ const worker = setupServer();
+ setupRequestMockHandlers(worker);
+
+ describe('readTree', () => {
+ const repoBuffer = fs.readFileSync(
+ path.resolve(__dirname, '__fixtures__/bitbucket-server-repo.tar.gz'),
+ );
+
+ beforeEach(() => {
+ worker.use(
+ rest.get(
+ 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.set('Content-Type', 'application/zip'),
+ ctx.set(
+ 'content-disposition',
+ 'attachment; filename=backstage-mock.tgz',
+ ),
+ ctx.body(repoBuffer),
+ ),
+ ),
+ rest.get(
+ 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.json({
+ values: [{ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }],
+ }),
+ ),
+ ),
+ );
+ });
+
+ it('uses private bitbucket host', async () => {
+ const response = await reader.readTree(
+ 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs?at=some-branch',
+ );
+
+ expect(response.etag).toBe('12ab34cd56ef');
+
+ const files = await response.files();
+
+ expect(files.length).toBe(1);
+ const indexMarkdownFile = await files[0].content();
+
+ expect(indexMarkdownFile.toString()).toBe('# Test\n');
+ });
+ });
+
+ describe('search private', () => {
+ const repoBuffer = fs.readFileSync(
+ path.resolve(__dirname, '__fixtures__/bitbucket-server-repo.tar.gz'),
+ );
+
+ beforeEach(() => {
+ worker.use(
+ rest.get(
+ 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.set('Content-Type', 'application/zip'),
+ ctx.set(
+ 'content-disposition',
+ 'attachment; filename=backstage-mock.tgz',
+ ),
+ ctx.body(repoBuffer),
+ ),
+ ),
+ rest.get(
+ 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits',
+ (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.json({
+ values: [{ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }],
+ }),
+ ),
+ ),
+ );
+ });
+
+ it('works for the naive case', async () => {
+ const result = await reader.search(
+ 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/**/index.*?at=master',
+ );
+ expect(result.etag).toBe('12ab34cd56ef');
+ expect(result.files.length).toBe(1);
+ expect(result.files[0].url).toBe(
+ 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs/index.md?at=master',
+ );
+ await expect(result.files[0].content()).resolves.toEqual(
+ Buffer.from('# Test\n'),
+ );
+ });
+
+ it('works in nested folders', async () => {
+ const result = await reader.search(
+ 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs/index.*?at=master',
+ );
+ expect(result.etag).toBe('12ab34cd56ef');
+ expect(result.files.length).toBe(1);
+ expect(result.files[0].url).toBe(
+ 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs/index.md?at=master',
+ );
+ await expect(result.files[0].content()).resolves.toEqual(
+ Buffer.from('# Test\n'),
+ );
+ });
+
+ it('throws NotModifiedError when same etag', async () => {
+ await expect(
+ reader.search(
+ 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/**/index.*?at=master',
+ { etag: '12ab34cd56ef' },
+ ),
+ ).rejects.toThrow(NotModifiedError);
+ });
+ });
+});
diff --git a/packages/backend-common/src/reading/BitbucketServerUrlReader.ts b/packages/backend-common/src/reading/BitbucketServerUrlReader.ts
new file mode 100644
index 0000000000..320b8f2719
--- /dev/null
+++ b/packages/backend-common/src/reading/BitbucketServerUrlReader.ts
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { NotFoundError, NotModifiedError } from '@backstage/errors';
+import {
+ BitbucketServerIntegration,
+ getBitbucketServerDownloadUrl,
+ getBitbucketServerFileFetchUrl,
+ getBitbucketServerRequestOptions,
+ ScmIntegrations,
+} from '@backstage/integration';
+import fetch, { Response } from 'node-fetch';
+import parseGitUrl from 'git-url-parse';
+import { trimEnd } from 'lodash';
+import { Minimatch } from 'minimatch';
+import { Readable } from 'stream';
+import {
+ ReaderFactory,
+ ReadTreeOptions,
+ ReadTreeResponse,
+ ReadTreeResponseFactory,
+ ReadUrlOptions,
+ ReadUrlResponse,
+ SearchOptions,
+ SearchResponse,
+ UrlReader,
+} from './types';
+
+/**
+ * Implements a {@link UrlReader} for files from Bitbucket Server APIs.
+ *
+ * @public
+ */
+export class BitbucketServerUrlReader implements UrlReader {
+ static factory: ReaderFactory = ({ config, treeResponseFactory }) => {
+ const integrations = ScmIntegrations.fromConfig(config);
+ return integrations.bitbucketServer.list().map(integration => {
+ const reader = new BitbucketServerUrlReader(integration, {
+ treeResponseFactory,
+ });
+ const predicate = (url: URL) => url.host === integration.config.host;
+ return { reader, predicate };
+ });
+ };
+
+ constructor(
+ private readonly integration: BitbucketServerIntegration,
+ private readonly deps: { treeResponseFactory: ReadTreeResponseFactory },
+ ) {}
+
+ async read(url: string): Promise {
+ const response = await this.readUrl(url);
+ return response.buffer();
+ }
+
+ async readUrl(
+ url: string,
+ options?: ReadUrlOptions,
+ ): Promise {
+ const { etag, signal } = options ?? {};
+ const bitbucketUrl = getBitbucketServerFileFetchUrl(
+ url,
+ this.integration.config,
+ );
+ const requestOptions = getBitbucketServerRequestOptions(
+ this.integration.config,
+ );
+
+ let response: Response;
+ try {
+ response = await fetch(bitbucketUrl.toString(), {
+ headers: {
+ ...requestOptions.headers,
+ ...(etag && { 'If-None-Match': etag }),
+ },
+ // TODO(freben): The signal cast is there because pre-3.x versions of
+ // node-fetch have a very slightly deviating AbortSignal type signature.
+ // The difference does not affect us in practice however. The cast can be
+ // removed after we support ESM for CLI dependencies and migrate to
+ // version 3 of node-fetch.
+ // https://github.com/backstage/backstage/issues/8242
+ ...(signal && { signal: signal as any }),
+ });
+ } catch (e) {
+ throw new Error(`Unable to read ${url}, ${e}`);
+ }
+
+ if (response.status === 304) {
+ throw new NotModifiedError();
+ }
+
+ if (response.ok) {
+ return {
+ buffer: async () => Buffer.from(await response.arrayBuffer()),
+ etag: response.headers.get('ETag') ?? undefined,
+ };
+ }
+
+ const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`;
+ if (response.status === 404) {
+ throw new NotFoundError(message);
+ }
+ throw new Error(message);
+ }
+
+ async readTree(
+ url: string,
+ options?: ReadTreeOptions,
+ ): Promise {
+ const { filepath } = parseGitUrl(url);
+
+ const lastCommitShortHash = await this.getLastCommitShortHash(url);
+ if (options?.etag && options.etag === lastCommitShortHash) {
+ throw new NotModifiedError();
+ }
+
+ const downloadUrl = await getBitbucketServerDownloadUrl(
+ url,
+ this.integration.config,
+ );
+ const archiveResponse = await fetch(
+ downloadUrl,
+ getBitbucketServerRequestOptions(this.integration.config),
+ );
+ if (!archiveResponse.ok) {
+ const message = `Failed to read tree from ${url}, ${archiveResponse.status} ${archiveResponse.statusText}`;
+ if (archiveResponse.status === 404) {
+ throw new NotFoundError(message);
+ }
+ throw new Error(message);
+ }
+
+ return await this.deps.treeResponseFactory.fromTarArchive({
+ stream: archiveResponse.body as unknown as Readable,
+ subpath: filepath,
+ etag: lastCommitShortHash,
+ filter: options?.filter,
+ });
+ }
+
+ async search(url: string, options?: SearchOptions): Promise {
+ const { filepath } = parseGitUrl(url);
+ const matcher = new Minimatch(filepath);
+
+ // TODO(freben): For now, read the entire repo and filter through that. In
+ // a future improvement, we could be smart and try to deduce that non-glob
+ // prefixes (like for filepaths such as some-prefix/**/a.yaml) can be used
+ // to get just that part of the repo.
+ const treeUrl = trimEnd(url.replace(filepath, ''), '/');
+
+ const tree = await this.readTree(treeUrl, {
+ etag: options?.etag,
+ filter: path => matcher.match(path),
+ });
+ const files = await tree.files();
+
+ return {
+ etag: tree.etag,
+ files: files.map(file => ({
+ url: this.integration.resolveUrl({
+ url: `/${file.path}`,
+ base: url,
+ }),
+ content: file.content,
+ })),
+ };
+ }
+
+ toString() {
+ const { host, token } = this.integration.config;
+ const authed = Boolean(token);
+ return `bitbucketServer{host=${host},authed=${authed}}`;
+ }
+
+ private async getLastCommitShortHash(url: string): Promise {
+ const { name: repoName, owner: project } = parseGitUrl(url);
+
+ // Bitbucket Server https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp222
+ const commitsApiUrl = `${this.integration.config.apiBaseUrl}/projects/${project}/repos/${repoName}/commits`;
+
+ const commitsResponse = await fetch(
+ commitsApiUrl,
+ getBitbucketServerRequestOptions(this.integration.config),
+ );
+ if (!commitsResponse.ok) {
+ const message = `Failed to retrieve commits from ${commitsApiUrl}, ${commitsResponse.status} ${commitsResponse.statusText}`;
+ if (commitsResponse.status === 404) {
+ throw new NotFoundError(message);
+ }
+ throw new Error(message);
+ }
+
+ const commits = await commitsResponse.json();
+ if (
+ commits &&
+ commits.values &&
+ commits.values.length > 0 &&
+ commits.values[0].id
+ ) {
+ return commits.values[0].id.substring(0, 12);
+ }
+
+ throw new Error(`Failed to read response from ${commitsApiUrl}`);
+ }
+}
diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts
index eff982581b..3a2360debb 100644
--- a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts
+++ b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts
@@ -29,38 +29,76 @@ import path from 'path';
import { NotModifiedError } from '@backstage/errors';
import { BitbucketUrlReader } from './BitbucketUrlReader';
import { DefaultReadTreeResponseFactory } from './tree';
+import { getVoidLogger } from '../logging';
-const treeResponseFactory = DefaultReadTreeResponseFactory.create({
- config: new ConfigReader({}),
+const logger = getVoidLogger();
+
+describe('BitbucketUrlReader.factory', () => {
+ it('only apply integration configs not inherited from bitbucketCloud or bitbucketServer', () => {
+ const config = new ConfigReader({
+ integrations: {
+ bitbucket: [],
+ bitbucketCloud: [
+ {
+ username: 'username',
+ appPassword: 'password',
+ },
+ ],
+ bitbucketServer: [
+ {
+ host: 'bitbucket-server.local',
+ token: 'test-token',
+ },
+ ],
+ },
+ });
+ const treeResponseFactory = DefaultReadTreeResponseFactory.create({
+ config: config,
+ });
+
+ const tuples = BitbucketUrlReader.factory({
+ config,
+ logger,
+ treeResponseFactory,
+ });
+
+ expect(tuples).toHaveLength(0);
+ });
});
-const bitbucketProcessor = new BitbucketUrlReader(
- new BitbucketIntegration(
- readBitbucketIntegrationConfig(
- new ConfigReader({
- host: 'bitbucket.org',
- apiBaseUrl: 'https://api.bitbucket.org/2.0',
- }),
- ),
- ),
- { treeResponseFactory },
-);
-
-const hostedBitbucketProcessor = new BitbucketUrlReader(
- new BitbucketIntegration(
- readBitbucketIntegrationConfig(
- new ConfigReader({
- host: 'bitbucket.mycompany.net',
- apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0',
- }),
- ),
- ),
- { treeResponseFactory },
-);
-
-const tmpDir = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp';
-
describe('BitbucketUrlReader', () => {
+ const treeResponseFactory = DefaultReadTreeResponseFactory.create({
+ config: new ConfigReader({}),
+ });
+
+ const bitbucketProcessor = new BitbucketUrlReader(
+ new BitbucketIntegration(
+ readBitbucketIntegrationConfig(
+ new ConfigReader({
+ host: 'bitbucket.org',
+ apiBaseUrl: 'https://api.bitbucket.org/2.0',
+ }),
+ ),
+ ),
+ logger,
+ { treeResponseFactory },
+ );
+
+ const hostedBitbucketProcessor = new BitbucketUrlReader(
+ new BitbucketIntegration(
+ readBitbucketIntegrationConfig(
+ new ConfigReader({
+ host: 'bitbucket.mycompany.net',
+ apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0',
+ }),
+ ),
+ ),
+ logger,
+ { treeResponseFactory },
+ );
+
+ const tmpDir = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp';
+
beforeEach(() => {
mockFs({
[tmpDir]: mockFs.directory(),
diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.ts b/packages/backend-common/src/reading/BitbucketUrlReader.ts
index df22f1633f..1687a66262 100644
--- a/packages/backend-common/src/reading/BitbucketUrlReader.ts
+++ b/packages/backend-common/src/reading/BitbucketUrlReader.ts
@@ -28,6 +28,7 @@ import parseGitUrl from 'git-url-parse';
import { trimEnd } from 'lodash';
import { Minimatch } from 'minimatch';
import { Readable } from 'stream';
+import { Logger } from 'winston';
import {
ReaderFactory,
ReadTreeOptions,
@@ -45,24 +46,38 @@ import {
* as the one exposed by Bitbucket Cloud itself.
*
* @public
+ * @deprecated in favor of BitbucketCloudUrlReader and BitbucketServerUrlReader
*/
export class BitbucketUrlReader implements UrlReader {
- static factory: ReaderFactory = ({ config, treeResponseFactory }) => {
+ static factory: ReaderFactory = ({ config, logger, treeResponseFactory }) => {
const integrations = ScmIntegrations.fromConfig(config);
- return integrations.bitbucket.list().map(integration => {
- const reader = new BitbucketUrlReader(integration, {
- treeResponseFactory,
+ return integrations.bitbucket
+ .list()
+ .filter(
+ item =>
+ !integrations.bitbucketCloud.byHost(item.config.host) &&
+ !integrations.bitbucketServer.byHost(item.config.host),
+ )
+ .map(integration => {
+ const reader = new BitbucketUrlReader(integration, logger, {
+ treeResponseFactory,
+ });
+ const predicate = (url: URL) => url.host === integration.config.host;
+ return { reader, predicate };
});
- const predicate = (url: URL) => url.host === integration.config.host;
- return { reader, predicate };
- });
};
constructor(
private readonly integration: BitbucketIntegration,
+ logger: Logger,
private readonly deps: { treeResponseFactory: ReadTreeResponseFactory },
) {
const { host, token, username, appPassword } = integration.config;
+ const replacement =
+ host === 'bitbucket.org' ? 'bitbucketCloud' : 'bitbucketServer';
+ logger.warn(
+ `[Deprecated] Please migrate from "integrations.bitbucket" to "integrations.${replacement}".`,
+ );
if (!token && username && !appPassword) {
throw new Error(
diff --git a/packages/backend-common/src/reading/GerritUrlReader.test.ts b/packages/backend-common/src/reading/GerritUrlReader.test.ts
index bc88fdcb20..fc27b3dd6a 100644
--- a/packages/backend-common/src/reading/GerritUrlReader.test.ts
+++ b/packages/backend-common/src/reading/GerritUrlReader.test.ts
@@ -14,24 +14,36 @@
* limitations under the License.
*/
-import { rest } from 'msw';
-import { setupServer } from 'msw/node';
import { setupRequestMockHandlers } from '@backstage/backend-test-utils';
import { ConfigReader } from '@backstage/config';
-import { JsonObject } from '@backstage/types';
-import { getVoidLogger } from '../logging';
-import { DefaultReadTreeResponseFactory } from './tree';
-import { UrlReaderPredicateTuple } from './types';
+import { NotModifiedError, NotFoundError } from '@backstage/errors';
import {
GerritIntegration,
readGerritIntegrationConfig,
} from '@backstage/integration';
+import { JsonObject } from '@backstage/types';
+import { rest } from 'msw';
+import { setupServer } from 'msw/node';
+import mockFs from 'mock-fs';
+import fs from 'fs-extra';
+import path from 'path';
+import { getVoidLogger } from '../logging';
+import { UrlReaderPredicateTuple } from './types';
+import { DefaultReadTreeResponseFactory } from './tree';
import { GerritUrlReader } from './GerritUrlReader';
const treeResponseFactory = DefaultReadTreeResponseFactory.create({
config: new ConfigReader({}),
});
+jest.mock('../scm', () => ({
+ Git: {
+ fromAuth: () => ({
+ clone: jest.fn(() => Promise.resolve({})),
+ }),
+ },
+}));
+
const gerritProcessor = new GerritUrlReader(
new GerritIntegration(
readGerritIntegrationConfig(
@@ -40,6 +52,8 @@ const gerritProcessor = new GerritUrlReader(
}),
),
),
+ { treeResponseFactory },
+ '/tmp',
);
const createReader = (config: JsonObject): UrlReaderPredicateTuple[] => {
@@ -54,6 +68,10 @@ describe('GerritUrlReader', () => {
const worker = setupServer();
setupRequestMockHandlers(worker);
+ afterAll(() => {
+ jest.clearAllMocks();
+ });
+
describe('reader factory', () => {
it('creates a reader.', () => {
const readers = createReader({
@@ -103,7 +121,7 @@ describe('GerritUrlReader', () => {
expect(predicate(new URL('https://gerrit-review.com/path'))).toBe(false);
});
- it('returns false for host.', () => {
+ it('returns false for host.', () => {
expect(predicate(new URL('https://gerrit.com/path'))).toBe(true);
});
});
@@ -170,4 +188,104 @@ describe('GerritUrlReader', () => {
);
});
});
+
+ describe('readTree', () => {
+ const branchAPIUrl =
+ 'https://gerrit.com/projects/app%2Fweb/branches/master';
+ const branchAPIresponse = fs.readFileSync(
+ path.resolve(__dirname, '__fixtures__/gerrit/branch-info-response.txt'),
+ );
+ const treeUrl = 'https://gerrit.com/app/web/+/refs/heads/master/';
+ const etag = '52432507a70b677b5674b019c9a46b2e9f29d0a1';
+ const mkdocsContent = 'great content';
+ const mdContent = 'doc';
+
+ beforeEach(() => {
+ mockFs({
+ '/tmp/': mockFs.directory(),
+ '/tmp/gerrit-clone-123abc/repo/mkdocs.yml': mkdocsContent,
+ '/tmp/gerrit-clone-123abc/repo/docs/first.md': mdContent,
+ });
+ const spy = jest.spyOn(fs, 'mkdtemp');
+ spy.mockImplementation(() => '/tmp/gerrit-clone-123abc');
+ });
+
+ afterEach(() => {
+ mockFs.restore();
+ jest.clearAllMocks();
+ });
+
+ it('reads the wanted files correctly.', async () => {
+ worker.use(
+ rest.get(branchAPIUrl, (_, res, ctx) => {
+ return res(ctx.status(200), ctx.body(branchAPIresponse));
+ }),
+ );
+
+ const response = await gerritProcessor.readTree(treeUrl);
+
+ expect(response.etag).toBe(etag);
+
+ const files = await response.files();
+ expect(files.length).toBe(2);
+
+ const docsYaml = await files[0].content();
+ expect(docsYaml.toString()).toBe(mkdocsContent);
+
+ const mdFile = await files[1].content();
+ expect(mdFile.toString()).toBe(mdContent);
+ });
+
+ it('throws NotModifiedError for matching etags.', async () => {
+ worker.use(
+ rest.get(branchAPIUrl, (_, res, ctx) => {
+ return res(ctx.status(200), ctx.body(branchAPIresponse));
+ }),
+ );
+
+ await expect(gerritProcessor.readTree(treeUrl, { etag })).rejects.toThrow(
+ NotModifiedError,
+ );
+ });
+
+ it('throws NotFoundError if branch info not found.', async () => {
+ worker.use(
+ rest.get(branchAPIUrl, (_, res, ctx) => {
+ return res(ctx.status(404, 'Not found.'));
+ }),
+ );
+
+ await expect(gerritProcessor.readTree(treeUrl)).rejects.toThrow(
+ NotFoundError,
+ );
+ });
+
+ it('should throw on failures while getting branch info.', async () => {
+ worker.use(
+ rest.get(branchAPIUrl, (_, res, ctx) => {
+ return res(ctx.status(500, 'Error'));
+ }),
+ );
+
+ await expect(gerritProcessor.readTree(treeUrl)).rejects.toThrow(Error);
+ });
+
+ it('should returns wanted files with a subpath', async () => {
+ worker.use(
+ rest.get(branchAPIUrl, (_, res, ctx) => {
+ return res(ctx.status(200), ctx.body(branchAPIresponse));
+ }),
+ );
+
+ const response = await gerritProcessor.readTree(`${treeUrl}/docs`);
+
+ expect(response.etag).toBe(etag);
+
+ const files = await response.files();
+ expect(files.length).toBe(1);
+
+ const mdFile = await files[0].content();
+ expect(mdFile.toString()).toBe(mdContent);
+ });
+ });
});
diff --git a/packages/backend-common/src/reading/GerritUrlReader.ts b/packages/backend-common/src/reading/GerritUrlReader.ts
index 7cc0b4731b..f3e8924192 100644
--- a/packages/backend-common/src/reading/GerritUrlReader.ts
+++ b/packages/backend-common/src/reading/GerritUrlReader.ts
@@ -14,16 +14,30 @@
* limitations under the License.
*/
-import { NotFoundError } from '@backstage/errors';
+import { Git } from '../scm';
+import { NotFoundError, NotModifiedError } from '@backstage/errors';
import {
GerritIntegration,
+ getGerritCloneRepoUrl,
+ getGerritBranchApiUrl,
getGerritFileContentsApiUrl,
getGerritRequestOptions,
+ parseGerritJsonResponse,
+ parseGerritGitilesUrl,
} from '@backstage/integration';
+import concatStream from 'concat-stream';
+import fs from 'fs-extra';
import fetch, { Response } from 'node-fetch';
+import os from 'os';
+import { join as joinPath } from 'path';
+import tar from 'tar';
+import { pipeline as pipelineCb, Readable } from 'stream';
+import { promisify } from 'util';
import {
ReaderFactory,
+ ReadTreeOptions,
ReadTreeResponse,
+ ReadTreeResponseFactory,
ReadUrlOptions,
ReadUrlResponse,
SearchResponse,
@@ -31,6 +45,11 @@ import {
} from './types';
import { ScmIntegrations } from '@backstage/integration';
+const pipeline = promisify(pipelineCb);
+
+const createTemporaryDirectory = async (workDir: string): Promise =>
+ await fs.mkdtemp(joinPath(workDir, '/gerrit-clone-'));
+
/**
* Implements a {@link UrlReader} for files in Gerrit.
*
@@ -50,16 +69,22 @@ import { ScmIntegrations } from '@backstage/integration';
* @public
*/
export class GerritUrlReader implements UrlReader {
- static factory: ReaderFactory = ({ config }) => {
+ static factory: ReaderFactory = ({ config, treeResponseFactory }) => {
const integrations = ScmIntegrations.fromConfig(config);
if (!integrations.gerrit) {
return [];
}
+ const workDir =
+ config.getOptionalString('backend.workingDirectory') ?? os.tmpdir();
return integrations.gerrit.list().map(integration => {
- const reader = new GerritUrlReader(integration);
+ const reader = new GerritUrlReader(
+ integration,
+ { treeResponseFactory },
+ workDir,
+ );
const predicate = (url: URL) => {
const gitilesUrl = new URL(integration.config.gitilesBaseUrl!);
- // If gitilesUrl is not specfified it will default to
+ // If gitilesUrl is not specified it will default to
// "integration.config.host".
return url.host === gitilesUrl.host;
};
@@ -67,7 +92,11 @@ export class GerritUrlReader implements UrlReader {
});
};
- constructor(private readonly integration: GerritIntegration) {}
+ constructor(
+ private readonly integration: GerritIntegration,
+ private readonly deps: { treeResponseFactory: ReadTreeResponseFactory },
+ private readonly workDir: string,
+ ) {}
async read(url: string): Promise {
const response = await this.readUrl(url);
@@ -109,8 +138,72 @@ export class GerritUrlReader implements UrlReader {
);
}
- async readTree(): Promise {
- throw new Error('GerritReader does not implement readTree');
+ async readTree(
+ url: string,
+ options?: ReadTreeOptions,
+ ): Promise {
+ const { filePath } = parseGerritGitilesUrl(this.integration.config, url);
+ const apiUrl = getGerritBranchApiUrl(this.integration.config, url);
+ let response: Response;
+ try {
+ response = await fetch(apiUrl, {
+ method: 'GET',
+ ...getGerritRequestOptions(this.integration.config),
+ });
+ } catch (e) {
+ throw new Error(`Unable to read branch state ${url}, ${e}`);
+ }
+
+ if (response.status === 404) {
+ throw new NotFoundError(`Not found: ${url}`);
+ }
+
+ if (!response.ok) {
+ throw new Error(
+ `${url} could not be read as ${apiUrl}, ${response.status} ${response.statusText}`,
+ );
+ }
+ const branchInfo = (await parseGerritJsonResponse(response as any)) as {
+ revision: string;
+ };
+ if (options?.etag === branchInfo.revision) {
+ throw new NotModifiedError();
+ }
+
+ const git = Git.fromAuth({
+ username: this.integration.config.username,
+ password: this.integration.config.password,
+ });
+ const tempDir = await createTemporaryDirectory(this.workDir);
+ const cloneUrl = getGerritCloneRepoUrl(this.integration.config, url);
+ try {
+ // The "fromTarArchive" function will strip the top level directory so
+ // an additional directory level is created when we clone.
+ await git.clone({
+ url: cloneUrl,
+ dir: joinPath(tempDir, 'repo'),
+ ref: branchInfo.revision,
+ depth: 1,
+ });
+
+ const data = await new Promise(async resolve => {
+ await pipeline(
+ tar.create({ cwd: tempDir }, ['']),
+ concatStream(resolve),
+ );
+ });
+ const tarArchive = Readable.from(data);
+ return await this.deps.treeResponseFactory.fromTarArchive({
+ stream: tarArchive as unknown as Readable,
+ subpath: filePath === '/' ? undefined : filePath,
+ etag: branchInfo.revision,
+ filter: options?.filter,
+ });
+ } catch (error) {
+ throw new Error(`Could not clone ${cloneUrl}: ${error}`);
+ } finally {
+ await fs.rm(tempDir, { recursive: true, force: true });
+ }
}
async search(): Promise {
diff --git a/packages/backend-common/src/reading/UrlReaderPredicateMux.test.ts b/packages/backend-common/src/reading/UrlReaderPredicateMux.test.ts
new file mode 100644
index 0000000000..527f26a9ec
--- /dev/null
+++ b/packages/backend-common/src/reading/UrlReaderPredicateMux.test.ts
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { getVoidLogger } from '../logging';
+import { UrlReaderPredicateMux } from './UrlReaderPredicateMux';
+
+describe('UrlReaderPredicateMux', () => {
+ it('forwards methods based on predicate', async () => {
+ const fooReader = {
+ read: jest.fn(),
+ readUrl: jest.fn(),
+ readTree: jest.fn(),
+ search: jest.fn(),
+ };
+ const barReader = {
+ read: jest.fn(),
+ readUrl: jest.fn(),
+ readTree: jest.fn(),
+ search: jest.fn(),
+ };
+
+ const mux = new UrlReaderPredicateMux(getVoidLogger());
+ mux.register({
+ predicate: url => url.hostname === 'foo',
+ reader: fooReader,
+ });
+ mux.register({
+ predicate: url => url.hostname === 'bar',
+ reader: barReader,
+ });
+
+ await mux.read('http://foo/1');
+ expect(fooReader.read).toHaveBeenCalledWith('http://foo/1');
+ await mux.readUrl('http://foo/2');
+ expect(fooReader.readUrl).toHaveBeenCalledWith('http://foo/2', undefined);
+ await mux.readTree('http://foo/3');
+ expect(fooReader.readTree).toHaveBeenCalledWith('http://foo/3', undefined);
+ await mux.search('http://foo/4');
+ expect(fooReader.search).toHaveBeenCalledWith('http://foo/4', undefined);
+
+ await mux.read('http://bar/1');
+ expect(barReader.read).toHaveBeenCalledWith('http://bar/1');
+ await mux.readUrl('http://bar/2');
+ expect(barReader.readUrl).toHaveBeenCalledWith('http://bar/2', undefined);
+ await mux.readTree('http://bar/3');
+ expect(barReader.readTree).toHaveBeenCalledWith('http://bar/3', undefined);
+ await mux.search('http://bar/4');
+ expect(barReader.search).toHaveBeenCalledWith('http://bar/4', undefined);
+ });
+
+ it('throws an error if no predicate matches', async () => {
+ const mux = new UrlReaderPredicateMux(getVoidLogger());
+
+ await expect(mux.readUrl('http://foo/1')).rejects.toThrowError(
+ /^Reading from 'http:\/\/foo\/1' is not allowed. You may/,
+ );
+
+ mux.register({
+ predicate: url => url.hostname === 'foo',
+ reader: {
+ read: jest.fn(),
+ readUrl: jest.fn(),
+ readTree: jest.fn(),
+ search: jest.fn(),
+ },
+ });
+
+ await expect(mux.readUrl('http://foo/1')).resolves.toBeUndefined();
+
+ await expect(mux.readUrl('http://bar/1')).rejects.toThrowError(
+ /^Reading from 'http:\/\/bar\/1' is not allowed. You may/,
+ );
+ });
+});
diff --git a/packages/backend-common/src/reading/UrlReaderPredicateMux.ts b/packages/backend-common/src/reading/UrlReaderPredicateMux.ts
index bbe94a0fb4..13d85be4d4 100644
--- a/packages/backend-common/src/reading/UrlReaderPredicateMux.ts
+++ b/packages/backend-common/src/reading/UrlReaderPredicateMux.ts
@@ -29,6 +29,14 @@ import {
const MIN_WARNING_INTERVAL_MS = 1000 * 60 * 15;
+function notAllowedMessage(url: string) {
+ return (
+ `Reading from '${url}' is not allowed. ` +
+ `You may need to configure an integration for the target host, or add it ` +
+ `to the configured list of allowed hosts at 'backend.reading.allow'`
+ );
+}
+
/**
* A UrlReader implementation that selects from a set of UrlReaders
* based on a predicate tied to each reader.
@@ -52,11 +60,7 @@ export class UrlReaderPredicateMux implements UrlReader {
}
}
- throw new NotAllowedError(
- `Reading from '${url}' is not allowed. ` +
- `You may need to configure an integration for the target host, or add it ` +
- `to the configured list of allowed hosts at 'backend.reading.allow'`,
- );
+ throw new NotAllowedError(notAllowedMessage(url));
}
async readUrl(
@@ -87,7 +91,7 @@ export class UrlReaderPredicateMux implements UrlReader {
}
}
- throw new NotAllowedError(`Reading from '${url}' is not allowed`);
+ throw new NotAllowedError(notAllowedMessage(url));
}
async readTree(
@@ -102,7 +106,7 @@ export class UrlReaderPredicateMux implements UrlReader {
}
}
- throw new NotAllowedError(`Reading from '${url}' is not allowed`);
+ throw new NotAllowedError(notAllowedMessage(url));
}
async search(url: string, options?: SearchOptions): Promise {
@@ -114,7 +118,7 @@ export class UrlReaderPredicateMux implements UrlReader {
}
}
- throw new NotAllowedError(`Reading from '${url}' is not allowed`);
+ throw new NotAllowedError(notAllowedMessage(url));
}
toString() {
diff --git a/packages/backend-common/src/reading/UrlReaders.ts b/packages/backend-common/src/reading/UrlReaders.ts
index e676d0e14c..72833454c3 100644
--- a/packages/backend-common/src/reading/UrlReaders.ts
+++ b/packages/backend-common/src/reading/UrlReaders.ts
@@ -19,6 +19,8 @@ import { Config } from '@backstage/config';
import { ReaderFactory, UrlReader } from './types';
import { UrlReaderPredicateMux } from './UrlReaderPredicateMux';
import { AzureUrlReader } from './AzureUrlReader';
+import { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader';
+import { BitbucketServerUrlReader } from './BitbucketServerUrlReader';
import { BitbucketUrlReader } from './BitbucketUrlReader';
import { GerritUrlReader } from './GerritUrlReader';
import { GithubUrlReader } from './GithubUrlReader';
@@ -82,6 +84,8 @@ export class UrlReaders {
config,
factories: factories.concat([
AzureUrlReader.factory,
+ BitbucketCloudUrlReader.factory,
+ BitbucketServerUrlReader.factory,
BitbucketUrlReader.factory,
GerritUrlReader.factory,
GithubUrlReader.factory,
diff --git a/packages/backend-common/src/reading/__fixtures__/gerrit/branch-info-response.txt b/packages/backend-common/src/reading/__fixtures__/gerrit/branch-info-response.txt
new file mode 100644
index 0000000000..20018c1bdf
--- /dev/null
+++ b/packages/backend-common/src/reading/__fixtures__/gerrit/branch-info-response.txt
@@ -0,0 +1,2 @@
+)]}'
+{"web_links":[{"name":"browse","url":"https://gerrit.googlesource.com/app/web/+/refs/heads/master","target":"_blank"}],"ref":"refs/heads/master","revision":"52432507a70b677b5674b019c9a46b2e9f29d0a1"}
diff --git a/packages/backend-common/src/reading/index.ts b/packages/backend-common/src/reading/index.ts
index c2c82e2bd5..f1609179b5 100644
--- a/packages/backend-common/src/reading/index.ts
+++ b/packages/backend-common/src/reading/index.ts
@@ -15,7 +15,9 @@
*/
export { AzureUrlReader } from './AzureUrlReader';
+export { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader';
export { BitbucketUrlReader } from './BitbucketUrlReader';
+export { BitbucketServerUrlReader } from './BitbucketServerUrlReader';
export { GerritUrlReader } from './GerritUrlReader';
export { GithubUrlReader } from './GithubUrlReader';
export { GitlabUrlReader } from './GitlabUrlReader';
diff --git a/packages/backend-common/src/tokens/ServerTokenManager.test.ts b/packages/backend-common/src/tokens/ServerTokenManager.test.ts
index 1799291544..0ff7bfb316 100644
--- a/packages/backend-common/src/tokens/ServerTokenManager.test.ts
+++ b/packages/backend-common/src/tokens/ServerTokenManager.test.ts
@@ -17,7 +17,7 @@ import { getVoidLogger } from '../logging/voidLogger';
import { ConfigReader } from '@backstage/config';
import { ServerTokenManager } from './ServerTokenManager';
import { Logger } from 'winston';
-import { JWK } from 'jose';
+import * as jose from 'jose';
import { TokenManager } from './types';
const emptyConfig = new ConfigReader({});
@@ -204,7 +204,7 @@ describe('ServerTokenManager', () => {
});
describe('NODE_ENV === development', () => {
- const generateSyncSpy = jest.spyOn(JWK, 'generateSync');
+ const generateSecretSpy = jest.spyOn(jose, 'generateSecret');
beforeEach(() => {
(process.env as any).NODE_ENV = 'development';
@@ -214,26 +214,30 @@ describe('ServerTokenManager', () => {
jest.clearAllMocks();
});
- it('should generate a key if no config is provided', () => {
- ServerTokenManager.fromConfig(emptyConfig, { logger });
-
- expect(generateSyncSpy).toHaveBeenCalledWith('oct', 192);
+ it('should generate a key if no config is provided', async () => {
+ const tokenManager = ServerTokenManager.fromConfig(emptyConfig, {
+ logger,
+ });
+ const token = await tokenManager.getToken();
+ expect(token).toBeDefined();
+ expect(generateSecretSpy).toHaveBeenCalledWith('HS256');
});
- it('should generate a key if no keys are provided in the configuration', () => {
- ServerTokenManager.fromConfig(
+ it('should generate a key if no keys are provided in the configuration', async () => {
+ const tokenManager = ServerTokenManager.fromConfig(
new ConfigReader({
backend: { auth: { keys: [] } },
}),
{ logger },
);
-
- expect(generateSyncSpy).toHaveBeenCalledWith('oct', 192);
+ const token = await tokenManager.getToken();
+ expect(token).toBeDefined();
+ expect(generateSecretSpy).toHaveBeenCalledWith('HS256');
});
it('should use provided secrets if config is provided', () => {
ServerTokenManager.fromConfig(configWithSecret, { logger });
- expect(generateSyncSpy).not.toHaveBeenCalled();
+ expect(generateSecretSpy).not.toHaveBeenCalled();
});
});
});
diff --git a/packages/backend-common/src/tokens/ServerTokenManager.ts b/packages/backend-common/src/tokens/ServerTokenManager.ts
index d6693edba1..484b99ca4d 100644
--- a/packages/backend-common/src/tokens/ServerTokenManager.ts
+++ b/packages/backend-common/src/tokens/ServerTokenManager.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { JWKS, JWK, JWT } from 'jose';
+import { base64url, generateSecret, SignJWT, jwtVerify, exportJWK } from 'jose';
import { Config } from '@backstage/config';
import { AuthenticationError } from '@backstage/errors';
import { TokenManager } from './types';
@@ -37,8 +37,10 @@ class NoopTokenManager implements TokenManager {
* @public
*/
export class ServerTokenManager implements TokenManager {
- private readonly verificationKeys: JWKS.KeyStore;
- private readonly signingKey: JWK.Key;
+ private verificationKeys: Uint8Array[];
+ private signingKey: Uint8Array;
+ private privateKeyPromise?: Promise;
+ private logger: Logger;
static noop(): TokenManager {
return new NoopTokenManager();
@@ -49,51 +51,87 @@ export class ServerTokenManager implements TokenManager {
const keys = config.getOptionalConfigArray('backend.auth.keys');
if (keys?.length) {
- return new ServerTokenManager(keys.map(key => key.getString('secret')));
+ return new ServerTokenManager(
+ keys.map(key => key.getString('secret')),
+ logger,
+ );
}
if (process.env.NODE_ENV !== 'development') {
throw new Error(
'You must configure at least one key in backend.auth.keys for production.',
);
}
-
// For development, if a secret has not been configured, we auto generate a secret instead of throwing.
- const generatedDevOnlyKey = JWK.generateSync('oct', 24 * 8);
- if (generatedDevOnlyKey.k === undefined) {
- throw new Error('Internal error, JWK key generation returned no data');
- }
logger.warn(
'Generated a secret for backend-to-backend authentication: DEVELOPMENT USE ONLY.',
);
- return new ServerTokenManager([generatedDevOnlyKey.k]);
+ return new ServerTokenManager([], logger);
}
- private constructor(secrets: string[]) {
- if (!secrets.length) {
+ private constructor(secrets: string[], logger: Logger) {
+ if (!secrets.length && process.env.NODE_ENV !== 'development') {
throw new Error(
'No secrets provided when constructing ServerTokenManager',
);
}
+ this.logger = logger;
+ this.verificationKeys = secrets.map(s => base64url.decode(s));
+ this.signingKey = this.verificationKeys[0];
+ }
- this.verificationKeys = new JWKS.KeyStore(
- secrets.map(k => JWK.asKey({ kty: 'oct', k })),
- );
- this.signingKey = this.verificationKeys.all()[0];
+ // Called when no keys have been generated yet in the dev environment
+ private async generateKeys(): Promise {
+ if (process.env.NODE_ENV !== 'development') {
+ throw new Error(
+ 'Key generation is not supported outside of the dev environment',
+ );
+ }
+ if (this.privateKeyPromise) {
+ return this.privateKeyPromise;
+ }
+ const promise = (async () => {
+ const secret = await generateSecret('HS256');
+ const jwk = await exportJWK(secret);
+ this.verificationKeys.push(base64url.decode(jwk.k ?? ''));
+ this.signingKey = this.verificationKeys[0];
+ return;
+ })();
+
+ try {
+ // If we fail to generate a new key, we need to clear the state so that
+ // the next caller will try to generate another key.
+ await promise;
+ } catch (error) {
+ this.logger.error(`Failed to generate new key, ${error}`);
+ delete this.privateKeyPromise;
+ }
+ return promise;
}
async getToken(): Promise<{ token: string }> {
- const jwt = JWT.sign({ sub: 'backstage-server' }, this.signingKey, {
- algorithm: 'HS256',
- });
-
+ if (!this.verificationKeys.length) {
+ await this.generateKeys();
+ }
+ const sub = 'backstage-server';
+ const jwt = await new SignJWT({ alg: 'HS256' })
+ .setProtectedHeader({ alg: 'HS256', sub: sub })
+ .setSubject('backstage-server')
+ .sign(this.signingKey);
return { token: jwt };
}
async authenticate(token: string): Promise {
- try {
- JWT.verify(token, this.verificationKeys);
- } catch (e) {
- throw new AuthenticationError('Invalid server token');
+ let verifyError = undefined;
+ for (const key of this.verificationKeys) {
+ try {
+ await jwtVerify(token, key);
+ // If the verify succeeded, return
+ return;
+ } catch (e) {
+ // Catch the verify exception and continue
+ verifyError = e;
+ }
}
+ throw new AuthenticationError(`Invalid server token: ${verifyError}`);
}
}
diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md
index ee63a45598..a8c66d866d 100644
--- a/packages/backend-tasks/CHANGELOG.md
+++ b/packages/backend-tasks/CHANGELOG.md
@@ -1,5 +1,40 @@
# @backstage/backend-tasks
+## 0.3.1-next.0
+
+### Patch Changes
+
+- cfd779a9bc: Scheduled tasks now have an optional `scope` field. If unset, or having the
+ value `'global'`, the old behavior with cross-worker locking is retained. If
+ having the value `'local'`, there is no coordination across workers and the
+ behavior is more like `setInterval`. This can be used to replace usages of
+ `runPeriodically` helpers.
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+
+## 0.3.0
+
+### Minor Changes
+
+- ab008a0988: Adds the ability to manually trigger tasks which are registered
+
+### Patch Changes
+
+- bdd2773202: Refactored the internal `TaskWorker` class to make it easier to test.
+- a83babdd63: Fixed the `initialDelay` parameter of tasks to properly make task workers
+ _always_ wait before the first invocations on startup, not just the very first
+ time that the task is ever created. This behavior is more in line with
+ expectations. Callers to not need to update their code.
+
+ Also clarified in the doc comment for the field that this wait applies only on
+ an individual worker level. That is, if you have a cluster of workers then each
+ individual machine may postpone its first task invocation by the given amount of
+ time to leave room for the service to settle, but _other_ workers may still
+ continue to invoke the task on the regular cadence in the meantime.
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.2
+
## 0.3.0-next.2
### Patch Changes
diff --git a/packages/backend-tasks/api-report.md b/packages/backend-tasks/api-report.md
index 9f02088bdf..0c82387cc8 100644
--- a/packages/backend-tasks/api-report.md
+++ b/packages/backend-tasks/api-report.md
@@ -43,6 +43,7 @@ export interface TaskScheduleDefinition {
}
| Duration;
initialDelay?: Duration;
+ scope?: 'global' | 'local';
timeout: Duration;
}
diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json
index 0456a34bff..20eab4e58e 100644
--- a/packages/backend-tasks/package.json
+++ b/packages/backend-tasks/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-tasks",
"description": "Common distributed task management library for Backstage backends",
- "version": "0.3.0-next.2",
+ "version": "0.3.1-next.0",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -33,7 +33,7 @@
"start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/backend-common": "^0.13.2-next.1",
+ "@backstage/backend-common": "^0.13.3-next.0",
"@backstage/config": "^1.0.0",
"@backstage/errors": "^1.0.0",
"@backstage/types": "^1.0.0",
@@ -48,8 +48,8 @@
"zod": "^3.9.5"
},
"devDependencies": {
- "@backstage/backend-test-utils": "^0.1.23-next.1",
- "@backstage/cli": "^0.17.0-next.2",
+ "@backstage/backend-test-utils": "^0.1.24-next.0",
+ "@backstage/cli": "^0.17.1-next.0",
"@types/cron": "^1.7.3",
"wait-for-expect": "^3.0.2"
},
diff --git a/packages/backend-tasks/src/tasks/LocalTaskWorker.test.ts b/packages/backend-tasks/src/tasks/LocalTaskWorker.test.ts
new file mode 100644
index 0000000000..bdbd976def
--- /dev/null
+++ b/packages/backend-tasks/src/tasks/LocalTaskWorker.test.ts
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { getVoidLogger } from '@backstage/backend-common';
+import { AbortController } from 'node-abort-controller';
+import { LocalTaskWorker } from './LocalTaskWorker';
+
+describe('LocalTaskWorker', () => {
+ const logger = getVoidLogger();
+
+ it('runs the happy path (with iso duration) and handles cancellation', async () => {
+ const fn = jest.fn();
+ const controller = new AbortController();
+
+ const worker = new LocalTaskWorker('a', fn, logger);
+ worker.start(
+ {
+ version: 2,
+ initialDelayDuration: 'PT0.2S',
+ cadence: 'PT0.2S',
+ timeoutAfterDuration: 'PT1S',
+ },
+ { signal: controller.signal },
+ );
+
+ // TODO(freben): Rewrite to fake timers - tried, but it wouldn't work
+ expect(fn).toBeCalledTimes(0);
+ await new Promise(r => setTimeout(r, 100));
+ expect(fn).toBeCalledTimes(0);
+ await new Promise(r => setTimeout(r, 200));
+ expect(fn).toBeCalledTimes(1);
+ await new Promise(r => setTimeout(r, 200));
+ expect(fn).toBeCalledTimes(2);
+ controller.abort();
+ await new Promise(r => setTimeout(r, 200));
+ expect(fn).toBeCalledTimes(2);
+ });
+
+ it('runs the happy path (with a cron expression) and handles cancellation', async () => {
+ const fn = jest.fn();
+ const controller = new AbortController();
+
+ // Await until system time is just past a second boundary (since cron is
+ // wall clock based)
+ await new Promise(r => setTimeout(r, 1000 - (Date.now() % 1000) + 10));
+
+ const worker = new LocalTaskWorker('a', fn, logger);
+ worker.start(
+ {
+ version: 2,
+ initialDelayDuration: 'PT0.2S',
+ cadence: '* * * * * *',
+ timeoutAfterDuration: 'PT1S',
+ },
+ { signal: controller.signal },
+ );
+
+ // TODO(freben): Rewrite to fake timers - tried, but it wouldn't work
+ expect(fn).toBeCalledTimes(0);
+ await new Promise(r => setTimeout(r, 100));
+ expect(fn).toBeCalledTimes(0);
+ await new Promise(r => setTimeout(r, 200));
+ expect(fn).toBeCalledTimes(1);
+ await new Promise(r => setTimeout(r, 1000));
+ expect(fn).toBeCalledTimes(2);
+ controller.abort();
+ await new Promise(r => setTimeout(r, 1000));
+ expect(fn).toBeCalledTimes(2);
+ });
+
+ it('can trigger to abort wait', async () => {
+ const fn = jest.fn();
+
+ const worker = new LocalTaskWorker('a', fn, logger);
+ worker.start({
+ version: 2,
+ initialDelayDuration: 'PT0.2S',
+ cadence: 'PT0.2S',
+ timeoutAfterDuration: 'PT1S',
+ });
+
+ // TODO(freben): Rewrite to fake timers - tried, but it wouldn't work
+ expect(fn).toBeCalledTimes(0);
+ await new Promise(r => setTimeout(r, 100));
+ expect(fn).toBeCalledTimes(0);
+ await new Promise(r => setTimeout(r, 200));
+ expect(fn).toBeCalledTimes(1);
+ worker.trigger();
+ await new Promise(r => setTimeout(r, 10));
+ expect(fn).toBeCalledTimes(2);
+ });
+});
diff --git a/packages/backend-tasks/src/tasks/LocalTaskWorker.ts b/packages/backend-tasks/src/tasks/LocalTaskWorker.ts
new file mode 100644
index 0000000000..89f314a1ec
--- /dev/null
+++ b/packages/backend-tasks/src/tasks/LocalTaskWorker.ts
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ConflictError } from '@backstage/errors';
+import { CronTime } from 'cron';
+import { DateTime, Duration } from 'luxon';
+import { AbortController, AbortSignal } from 'node-abort-controller';
+import { Logger } from 'winston';
+import { TaskFunction, TaskSettingsV2 } from './types';
+import { delegateAbortController, sleep } from './util';
+
+/**
+ * Implements tasks that run locally without cross-host collaboration.
+ *
+ * @private
+ */
+export class LocalTaskWorker {
+ private abortWait: AbortController | undefined;
+
+ constructor(
+ private readonly taskId: string,
+ private readonly fn: TaskFunction,
+ private readonly logger: Logger,
+ ) {}
+
+ start(settings: TaskSettingsV2, options?: { signal?: AbortSignal }) {
+ this.logger.info(
+ `Task worker starting: ${this.taskId}, ${JSON.stringify(settings)}`,
+ );
+
+ (async () => {
+ try {
+ if (settings.initialDelayDuration) {
+ await this.sleep(
+ Duration.fromISO(settings.initialDelayDuration),
+ options?.signal,
+ );
+ }
+
+ while (!options?.signal?.aborted) {
+ const startTime = process.hrtime();
+ await this.runOnce(settings, options?.signal);
+ const timeTaken = process.hrtime(startTime);
+ await this.waitUntilNext(
+ settings,
+ (timeTaken[0] + timeTaken[1] / 1e9) * 1000,
+ options?.signal,
+ );
+ }
+
+ this.logger.info(`Task worker finished: ${this.taskId}`);
+ } catch (e) {
+ this.logger.warn(`Task worker failed unexpectedly, ${e}`);
+ }
+ })();
+ }
+
+ trigger(): void {
+ if (!this.abortWait) {
+ throw new ConflictError(`Task ${this.taskId} is currently running`);
+ }
+ this.abortWait.abort();
+ }
+
+ /**
+ * Makes a single attempt at running the task to completion.
+ */
+ private async runOnce(
+ settings: TaskSettingsV2,
+ signal?: AbortSignal,
+ ): Promise {
+ // Abort the task execution either if the worker is stopped, or if the
+ // task timeout is hit
+ const taskAbortController = delegateAbortController(signal);
+ const timeoutHandle = setTimeout(() => {
+ taskAbortController.abort();
+ }, Duration.fromISO(settings.timeoutAfterDuration).as('milliseconds'));
+
+ try {
+ await this.fn(taskAbortController.signal);
+ } catch (e) {
+ // ignore intentionally
+ }
+
+ // release resources
+ clearTimeout(timeoutHandle);
+ taskAbortController.abort();
+ }
+
+ /**
+ * Sleeps until it's time to run the task again.
+ */
+ private async waitUntilNext(
+ settings: TaskSettingsV2,
+ lastRunMillis: number,
+ signal?: AbortSignal,
+ ) {
+ if (signal?.aborted) {
+ return;
+ }
+
+ const isCron = !settings.cadence.startsWith('P');
+ let dt: number;
+
+ if (isCron) {
+ const nextRun = +new CronTime(settings.cadence).sendAt().toDate();
+ dt = nextRun - Date.now();
+ } else {
+ dt =
+ Duration.fromISO(settings.cadence).as('milliseconds') - lastRunMillis;
+ }
+
+ dt = Math.max(dt, 0);
+
+ this.logger.debug(
+ `task: ${this.taskId} will next occur around ${DateTime.now().plus(
+ Duration.fromMillis(dt),
+ )}`,
+ );
+
+ await this.sleep(Duration.fromMillis(dt), signal);
+ }
+
+ private async sleep(
+ duration: Duration,
+ abortSignal?: AbortSignal,
+ ): Promise {
+ this.abortWait = delegateAbortController(abortSignal);
+ await sleep(duration, this.abortWait.signal);
+ this.abortWait.abort(); // cleans up resources
+ this.abortWait = undefined;
+ }
+}
diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.test.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.test.ts
index 004426211c..1204431434 100644
--- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.test.ts
+++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.test.ts
@@ -16,11 +16,11 @@
import { getVoidLogger } from '@backstage/backend-common';
import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils';
+import { ConflictError, NotFoundError } from '@backstage/errors';
import { Duration } from 'luxon';
+import { AbortSignal } from 'node-abort-controller';
import { migrateBackendTasks } from '../database/migrateBackendTasks';
import { PluginTaskSchedulerImpl } from './PluginTaskSchedulerImpl';
-import { ConflictError, NotFoundError } from '@backstage/errors';
-import { AbortSignal } from 'node-abort-controller';
jest.useFakeTimers();
@@ -49,7 +49,7 @@ describe('PluginTaskManagerImpl', () => {
// This is just to test the wrapper code; most of the actual tests are in
// TaskWorker.test.ts
- describe('scheduleTask', () => {
+ describe('scheduleTask with global scope', () => {
it.each(databases.eachSupportedId())(
'can run the v1 happy path, %p',
async databaseId => {
@@ -62,6 +62,7 @@ describe('PluginTaskManagerImpl', () => {
timeout: Duration.fromMillis(5000),
frequency: Duration.fromMillis(5000),
fn,
+ scope: 'global',
});
await promise;
@@ -82,6 +83,7 @@ describe('PluginTaskManagerImpl', () => {
timeout: Duration.fromMillis(5000),
frequency: { cron: '* * * * * *' },
fn,
+ scope: 'global',
});
await promise;
@@ -91,7 +93,7 @@ describe('PluginTaskManagerImpl', () => {
);
});
- describe('triggerTask', () => {
+ describe('triggerTask with global scope', () => {
it.each(databases.eachSupportedId())(
'can manually trigger a task, %p',
async databaseId => {
@@ -105,6 +107,7 @@ describe('PluginTaskManagerImpl', () => {
frequency: Duration.fromObject({ years: 1 }),
initialDelay: Duration.fromObject({ years: 1 }),
fn,
+ scope: 'global',
});
await manager.triggerTask('task1');
@@ -127,6 +130,7 @@ describe('PluginTaskManagerImpl', () => {
timeout: Duration.fromMillis(5000),
frequency: Duration.fromObject({ years: 1 }),
fn,
+ scope: 'global',
});
await expect(() => manager.triggerTask('task2')).rejects.toThrow(
@@ -151,6 +155,7 @@ describe('PluginTaskManagerImpl', () => {
resolve();
await new Promise(r => setTimeout(r, 20000));
},
+ scope: 'global',
});
await promise;
@@ -162,6 +167,106 @@ describe('PluginTaskManagerImpl', () => {
);
});
+ // This is just to test the wrapper code; most of the actual tests are in
+ // TaskWorker.test.ts
+ describe('scheduleTask with local scope', () => {
+ it('can run the v1 happy path', async () => {
+ const { manager } = await init('SQLITE_3');
+
+ const fn = jest.fn();
+ const promise = new Promise(resolve => fn.mockImplementation(resolve));
+ await manager.scheduleTask({
+ id: 'task1',
+ timeout: Duration.fromMillis(5000),
+ frequency: Duration.fromMillis(5000),
+ fn,
+ scope: 'local',
+ });
+
+ await promise;
+ expect(fn).toHaveBeenCalledWith(expect.any(AbortSignal));
+ }, 60_000);
+
+ it('can run the v2 happy path', async () => {
+ const { manager } = await init('SQLITE_3');
+
+ const fn = jest.fn();
+ const promise = new Promise(resolve => fn.mockImplementation(resolve));
+ await manager.scheduleTask({
+ id: 'task2',
+ timeout: Duration.fromMillis(5000),
+ frequency: { cron: '* * * * * *' },
+ fn,
+ scope: 'local',
+ });
+
+ await promise;
+ expect(fn).toHaveBeenCalledWith(expect.any(AbortSignal));
+ }, 60_000);
+ });
+
+ describe('triggerTask with local scope', () => {
+ it('can manually trigger a task', async () => {
+ const { manager } = await init('SQLITE_3');
+
+ const fn = jest.fn();
+ const promise = new Promise(resolve => fn.mockImplementation(resolve));
+ await manager.scheduleTask({
+ id: 'task1',
+ timeout: Duration.fromMillis(5000),
+ frequency: Duration.fromObject({ years: 1 }),
+ initialDelay: Duration.fromObject({ years: 1 }),
+ fn,
+ scope: 'local',
+ });
+
+ await manager.triggerTask('task1');
+ jest.advanceTimersByTime(5000);
+
+ await promise;
+ expect(fn).toHaveBeenCalledWith(expect.any(AbortSignal));
+ }, 60_000);
+
+ it('cant trigger a non-existent task', async () => {
+ const { manager } = await init('SQLITE_3');
+
+ const fn = jest.fn();
+ await manager.scheduleTask({
+ id: 'task1',
+ timeout: Duration.fromMillis(5000),
+ frequency: Duration.fromObject({ years: 1 }),
+ fn,
+ scope: 'local',
+ });
+
+ await expect(() => manager.triggerTask('task2')).rejects.toThrow(
+ NotFoundError,
+ );
+ }, 60_000);
+
+ it('cant trigger a running task', async () => {
+ const { manager } = await init('SQLITE_3');
+
+ const { promise, resolve } = defer();
+
+ await manager.scheduleTask({
+ id: 'task1',
+ timeout: Duration.fromMillis(5000),
+ frequency: Duration.fromObject({ years: 1 }),
+ fn: async () => {
+ resolve();
+ await new Promise(r => setTimeout(r, 20000));
+ },
+ scope: 'local',
+ });
+
+ await promise;
+ await expect(() => manager.triggerTask('task1')).rejects.toThrow(
+ ConflictError,
+ );
+ }, 60_000);
+ });
+
// This is just to test the wrapper code; most of the actual tests are in
// TaskWorker.test.ts
describe('createScheduledTaskRunner', () => {
@@ -176,6 +281,7 @@ describe('PluginTaskManagerImpl', () => {
.createScheduledTaskRunner({
timeout: Duration.fromMillis(5000),
frequency: Duration.fromMillis(5000),
+ scope: 'global',
})
.run({
id: 'task1',
diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts
index 44f46e7237..6db8b9f4f5 100644
--- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts
+++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerImpl.ts
@@ -16,6 +16,7 @@
import { Knex } from 'knex';
import { Logger } from 'winston';
+import { LocalTaskWorker } from './LocalTaskWorker';
import { TaskWorker } from './TaskWorker';
import {
PluginTaskScheduler,
@@ -24,62 +25,73 @@ import {
TaskScheduleDefinition,
} from './types';
import { validateId } from './util';
-import { DB_TASKS_TABLE, DbTasksRow } from '../database/tables';
-import { ConflictError, NotFoundError } from '@backstage/errors';
/**
* Implements the actual task management.
*/
export class PluginTaskSchedulerImpl implements PluginTaskScheduler {
+ private readonly localTasksById = new Map();
+
constructor(
private readonly databaseFactory: () => Promise,
private readonly logger: Logger,
) {}
async triggerTask(id: string): Promise {
+ const localTask = this.localTasksById.get(id);
+ if (localTask) {
+ localTask.trigger();
+ return;
+ }
+
const knex = await this.databaseFactory();
-
- // check if task exists
- const rows = await knex(DB_TASKS_TABLE)
- .select(knex.raw(1))
- .where('id', '=', id);
- if (rows.length !== 1) {
- throw new NotFoundError(`Task ${id} does not exist`);
- }
-
- const updatedRows = await knex(DB_TASKS_TABLE)
- .where('id', '=', id)
- .whereNull('current_run_ticket')
- .update({
- next_run_start_at: knex.fn.now(),
- });
- if (updatedRows < 1) {
- throw new ConflictError(`Task ${id} is currently running`);
- }
+ await TaskWorker.trigger(knex, id);
}
async scheduleTask(
task: TaskScheduleDefinition & TaskInvocationDefinition,
): Promise {
validateId(task.id);
+ const scope = task.scope ?? 'global';
- const knex = await this.databaseFactory();
- const worker = new TaskWorker(task.id, task.fn, knex, this.logger);
+ if (scope === 'global') {
+ const knex = await this.databaseFactory();
+ const worker = new TaskWorker(task.id, task.fn, knex, this.logger);
- await worker.start(
- {
- version: 2,
- cadence:
- 'cron' in task.frequency
- ? task.frequency.cron
- : task.frequency.toISO(),
- initialDelayDuration: task.initialDelay?.toISO(),
- timeoutAfterDuration: task.timeout.toISO(),
- },
- {
- signal: task.signal,
- },
- );
+ await worker.start(
+ {
+ version: 2,
+ cadence:
+ 'cron' in task.frequency
+ ? task.frequency.cron
+ : task.frequency.toISO(),
+ initialDelayDuration: task.initialDelay?.toISO(),
+ timeoutAfterDuration: task.timeout.toISO(),
+ },
+ {
+ signal: task.signal,
+ },
+ );
+ } else {
+ const worker = new LocalTaskWorker(task.id, task.fn, this.logger);
+
+ worker.start(
+ {
+ version: 2,
+ cadence:
+ 'cron' in task.frequency
+ ? task.frequency.cron
+ : task.frequency.toISO(),
+ initialDelayDuration: task.initialDelay?.toISO(),
+ timeoutAfterDuration: task.timeout.toISO(),
+ },
+ {
+ signal: task.signal,
+ },
+ );
+
+ this.localTasksById.set(task.id, worker);
+ }
}
createScheduledTaskRunner(schedule: TaskScheduleDefinition): TaskRunner {
diff --git a/packages/backend-tasks/src/tasks/TaskScheduler.test.ts b/packages/backend-tasks/src/tasks/TaskScheduler.test.ts
index 2a5deddb19..e59f24c277 100644
--- a/packages/backend-tasks/src/tasks/TaskScheduler.test.ts
+++ b/packages/backend-tasks/src/tasks/TaskScheduler.test.ts
@@ -17,8 +17,8 @@
import { DatabaseManager, getVoidLogger } from '@backstage/backend-common';
import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils';
import { Duration } from 'luxon';
-import { TaskScheduler } from './TaskScheduler';
import waitForExpect from 'wait-for-expect';
+import { TaskScheduler } from './TaskScheduler';
describe('TaskScheduler', () => {
const logger = getVoidLogger();
diff --git a/packages/backend-tasks/src/tasks/TaskWorker.test.ts b/packages/backend-tasks/src/tasks/TaskWorker.test.ts
index 0c64d06287..14688d0f98 100644
--- a/packages/backend-tasks/src/tasks/TaskWorker.test.ts
+++ b/packages/backend-tasks/src/tasks/TaskWorker.test.ts
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-import { AbortController } from 'node-abort-controller';
import { getVoidLogger } from '@backstage/backend-common';
import { TestDatabases } from '@backstage/backend-test-utils';
import { Duration } from 'luxon';
+import { AbortController } from 'node-abort-controller';
import waitForExpect from 'wait-for-expect';
import { migrateBackendTasks } from '../database/migrateBackendTasks';
import { DbTasksRow, DB_TASKS_TABLE } from '../database/tables';
diff --git a/packages/backend-tasks/src/tasks/TaskWorker.ts b/packages/backend-tasks/src/tasks/TaskWorker.ts
index 02bc115ddd..a60a0a4730 100644
--- a/packages/backend-tasks/src/tasks/TaskWorker.ts
+++ b/packages/backend-tasks/src/tasks/TaskWorker.ts
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import { ConflictError, NotFoundError } from '@backstage/errors';
+import { CronTime } from 'cron';
import { Knex } from 'knex';
import { DateTime, Duration } from 'luxon';
import { AbortSignal } from 'node-abort-controller';
@@ -22,12 +24,11 @@ import { Logger } from 'winston';
import { DbTasksRow, DB_TASKS_TABLE } from '../database/tables';
import { TaskFunction, TaskSettingsV2, taskSettingsV2Schema } from './types';
import { delegateAbortController, nowPlus, sleep } from './util';
-import { CronTime } from 'cron';
const DEFAULT_WORK_CHECK_FREQUENCY = Duration.fromObject({ seconds: 5 });
/**
- * Performs the actual work of a task.
+ * Implements tasks that run across worker hosts, with collaborative locking.
*
* @private
*/
@@ -76,12 +77,32 @@ export class TaskWorker {
})();
}
+ static async trigger(knex: Knex, taskId: string): Promise {
+ // check if task exists
+ const rows = await knex(DB_TASKS_TABLE)
+ .select(knex.raw(1))
+ .where('id', '=', taskId);
+ if (rows.length !== 1) {
+ throw new NotFoundError(`Task ${taskId} does not exist`);
+ }
+
+ const updatedRows = await knex(DB_TASKS_TABLE)
+ .where('id', '=', taskId)
+ .whereNull('current_run_ticket')
+ .update({
+ next_run_start_at: knex.fn.now(),
+ });
+ if (updatedRows < 1) {
+ throw new ConflictError(`Task ${taskId} is currently running`);
+ }
+ }
+
/**
* Makes a single attempt at running the task to completion, if ready.
*
* @returns The outcome of the attempt
*/
- async runOnce(
+ private async runOnce(
signal?: AbortSignal,
): Promise<
| { result: 'not-ready-yet' }
diff --git a/packages/backend-tasks/src/tasks/types.ts b/packages/backend-tasks/src/tasks/types.ts
index 1e09e52cd0..f9ada1dd17 100644
--- a/packages/backend-tasks/src/tasks/types.ts
+++ b/packages/backend-tasks/src/tasks/types.ts
@@ -14,10 +14,10 @@
* limitations under the License.
*/
+import { CronTime } from 'cron';
import { Duration } from 'luxon';
import { AbortSignal } from 'node-abort-controller';
import { z } from 'zod';
-import { CronTime } from 'cron';
/**
* A function that can be called as a scheduled task.
@@ -93,14 +93,37 @@ export interface TaskScheduleDefinition {
* will happen as soon as possible according to the cadence.
*
* NOTE: This is a per-worker delay. If you have a cluster of workers all
- * collaborating on a task, then you may still see the task being processed by
- * other long-lived workers, while any given single worker is in its initial
- * sleep delay time e.g. after a deployment. Therefore this parameter is not
- * useful for "globally" pausing work; its main intended use is for individual
- * machines to get a chance to reach some equilibrium at startup before
- * triggering heavy batch workloads.
+ * collaborating on a task that has its `scope` field set to `'global'`, then
+ * you may still see the task being processed by other long-lived workers,
+ * while any given single worker is in its initial sleep delay time e.g. after
+ * a deployment. Therefore this parameter is not useful for "globally" pausing
+ * work; its main intended use is for individual machines to get a chance to
+ * reach some equilibrium at startup before triggering heavy batch workloads.
*/
initialDelay?: Duration;
+
+ /**
+ * Sets the scope of concurrency control / locking to apply for invocations of
+ * this task.
+ *
+ * @remarks
+ *
+ * When the scope is set to the default value `'global'`, the scheduler will
+ * attempt to ensure that only one worker machine runs the task at a time,
+ * according to the given cadence. This means that as the number of worker
+ * hosts increases, the invocation frequency of this task will not go up.
+ * Instead the load is spread randomly across hosts. This setting is useful
+ * for tasks that access shared resources, for example catalog ingestion tasks
+ * where you do not want many machines to repeatedly import the same data and
+ * trample over each other.
+ *
+ * When the scope is set to `'local'`, there is no concurrency control across
+ * hosts. Each host runs the task according to the given cadence similarly to
+ * `setInterval`, but the runtime ensures that there are no overlapping runs.
+ *
+ * @defaultValue 'global'
+ */
+ scope?: 'global' | 'local';
}
/**
@@ -149,24 +172,23 @@ export interface PluginTaskScheduler {
/**
* Manually triggers a task by ID.
*
- * If the task doesn't exist, a NotFoundError is thrown.
- * If the task is currently running, a ConflictError is thrown.
+ * If the task doesn't exist, a NotFoundError is thrown. If the task is
+ * currently running, a ConflictError is thrown.
*
* @param id - The task ID
- *
*/
triggerTask(id: string): Promise;
/**
- * Schedules a task function for coordinated exclusive invocation across
- * workers. This convenience method performs both the scheduling and
- * invocation in one go.
+ * Schedules a task function for recurring runs.
*
* @remarks
*
- * If the task was already scheduled since before by us or by another party,
- * its options are just overwritten with the given options, and things
- * continue from there.
+ * The `scope` task field controls whether to use coordinated exclusive
+ * invocation across workers, or to just coordinate within the current worker.
+ *
+ * This convenience method performs both the scheduling and invocation in one
+ * go.
*
* @param task - The task definition
*/
diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md
index 79f07c4ff4..4a6a5a0c25 100644
--- a/packages/backend-test-utils/CHANGELOG.md
+++ b/packages/backend-test-utils/CHANGELOG.md
@@ -1,5 +1,22 @@
# @backstage/backend-test-utils
+## 0.1.24-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/cli@0.17.1-next.0
+
+## 0.1.23
+
+### Patch Changes
+
+- 0654c87cf2: `TestDatabases.create` will no longer set up an `afterAll` test handler if no databases are supported.
+- Updated dependencies
+ - @backstage/cli@0.17.0
+ - @backstage/backend-common@0.13.2
+
## 0.1.23-next.1
### Patch Changes
diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json
index cb487f3e3f..eb6f7e0aba 100644
--- a/packages/backend-test-utils/package.json
+++ b/packages/backend-test-utils/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-test-utils",
"description": "Test helpers library for Backstage backends",
- "version": "0.1.23-next.1",
+ "version": "0.1.24-next.0",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -34,8 +34,8 @@
"start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/backend-common": "^0.13.2-next.1",
- "@backstage/cli": "^0.17.0-next.1",
+ "@backstage/backend-common": "^0.13.3-next.0",
+ "@backstage/cli": "^0.17.1-next.0",
"@backstage/config": "^1.0.0",
"better-sqlite3": "^7.5.0",
"knex": "^1.0.2",
@@ -46,7 +46,7 @@
"uuid": "^8.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.17.0-next.1"
+ "@backstage/cli": "^0.17.1-next.0"
},
"files": [
"dist"
diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md
index f5d01249a5..8a6a052a20 100644
--- a/packages/backend/CHANGELOG.md
+++ b/packages/backend/CHANGELOG.md
@@ -1,5 +1,104 @@
# example-backend
+## 0.2.71-next.0
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.13.3-next.0
+ - @backstage/plugin-scaffolder-backend@1.2.0-next.0
+ - @backstage/plugin-kubernetes-backend@0.5.1-next.0
+ - @backstage/integration@1.2.0-next.0
+ - @backstage/plugin-catalog-backend@1.1.2-next.0
+ - @backstage/plugin-app-backend@0.3.32-next.0
+ - @backstage/plugin-auth-backend@0.13.1-next.0
+ - @backstage/plugin-rollbar-backend@0.1.29-next.0
+ - @backstage/plugin-techdocs-backend@1.1.1-next.0
+ - @backstage/plugin-search-backend-module-elasticsearch@0.1.4-next.0
+ - @backstage/plugin-jenkins-backend@0.1.22-next.0
+ - @backstage/plugin-search-backend@0.5.2-next.0
+ - @backstage/backend-tasks@0.3.1-next.0
+ - @backstage/plugin-auth-node@0.2.1-next.0
+ - example-app@0.2.71-next.0
+ - @backstage/plugin-azure-devops-backend@0.3.11-next.0
+ - @backstage/plugin-badges-backend@0.1.26-next.0
+ - @backstage/plugin-code-coverage-backend@0.1.30-next.0
+ - @backstage/plugin-graphql-backend@0.1.22-next.0
+ - @backstage/plugin-kafka-backend@0.2.25-next.0
+ - @backstage/plugin-permission-backend@0.5.7-next.0
+ - @backstage/plugin-permission-node@0.6.1-next.0
+ - @backstage/plugin-proxy-backend@0.2.26-next.0
+ - @backstage/plugin-scaffolder-backend-module-rails@0.3.7-next.0
+ - @backstage/plugin-search-backend-module-pg@0.3.3-next.0
+ - @backstage/plugin-search-backend-node@0.6.1-next.0
+ - @backstage/plugin-tech-insights-backend@0.3.1-next.0
+ - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.16-next.0
+ - @backstage/plugin-tech-insights-node@0.2.10-next.0
+ - @backstage/plugin-todo-backend@0.1.29-next.0
+
+## 0.2.70
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog-backend@1.1.0
+ - @backstage/plugin-techdocs-backend@1.1.0
+ - @backstage/plugin-scaffolder-backend@1.1.0
+ - @backstage/integration@1.1.0
+ - @backstage/plugin-search-backend@0.5.0
+ - @backstage/plugin-auth-backend@0.13.0
+ - @backstage/backend-tasks@0.3.0
+ - @backstage/plugin-permission-common@0.6.0
+ - @backstage/plugin-permission-node@0.6.0
+ - @backstage/catalog-model@1.0.1
+ - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.15
+ - @backstage/plugin-kafka-backend@0.2.24
+ - @backstage/plugin-auth-node@0.2.0
+ - @backstage/plugin-jenkins-backend@0.1.20
+ - @backstage/plugin-badges-backend@0.1.25
+ - @backstage/plugin-tech-insights-node@0.2.9
+ - @backstage/plugin-todo-backend@0.1.28
+ - @backstage/backend-common@0.13.2
+ - @backstage/plugin-kubernetes-backend@0.5.0
+ - @backstage/plugin-search-backend-node@0.6.0
+ - @backstage/plugin-search-backend-module-elasticsearch@0.1.3
+ - @backstage/plugin-search-backend-module-pg@0.3.2
+ - @backstage/plugin-permission-backend@0.5.6
+ - @backstage/plugin-tech-insights-backend@0.3.0
+ - @backstage/plugin-azure-devops-backend@0.3.10
+ - @backstage/plugin-scaffolder-backend-module-rails@0.3.6
+ - example-app@0.2.70
+ - @backstage/catalog-client@1.0.1
+ - @backstage/plugin-app-backend@0.3.31
+ - @backstage/plugin-code-coverage-backend@0.1.29
+ - @backstage/plugin-graphql-backend@0.1.21
+ - @backstage/plugin-proxy-backend@0.2.25
+ - @backstage/plugin-rollbar-backend@0.1.28
+
+## 0.2.70-next.2
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-auth-backend@0.13.0-next.2
+ - @backstage/plugin-catalog-backend@1.1.0-next.3
+ - @backstage/plugin-kafka-backend@0.2.24-next.1
+ - @backstage/plugin-search-backend@0.5.0-next.2
+ - @backstage/plugin-permission-common@0.6.0-next.1
+ - @backstage/plugin-permission-node@0.6.0-next.2
+ - @backstage/plugin-jenkins-backend@0.1.20-next.2
+ - @backstage/plugin-todo-backend@0.1.28-next.2
+ - @backstage/backend-common@0.13.2-next.2
+ - @backstage/plugin-kubernetes-backend@0.5.0-next.1
+ - @backstage/plugin-search-backend-node@0.6.0-next.1
+ - @backstage/plugin-scaffolder-backend-module-rails@0.3.6-next.2
+ - @backstage/integration@1.1.0-next.2
+ - @backstage/plugin-techdocs-backend@1.1.0-next.2
+ - example-app@0.2.70-next.2
+ - @backstage/plugin-search-backend-module-elasticsearch@0.1.3-next.1
+ - @backstage/plugin-search-backend-module-pg@0.3.2-next.1
+ - @backstage/plugin-app-backend@0.3.31-next.1
+
## 0.2.70-next.1
### Patch Changes
diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile
index dd35d4ddbc..86f6e17861 100644
--- a/packages/backend/Dockerfile
+++ b/packages/backend/Dockerfile
@@ -13,18 +13,18 @@ FROM node:16-bullseye-slim
WORKDIR /app
+# install sqlite3 dependencies, you can skip this if you don't use sqlite3 in the image
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \
+ rm -rf /var/lib/apt/lists/* && \
+ yarn config set python /usr/bin/python3
+
# Copy repo skeleton first, to avoid unnecessary docker cache invalidation.
# The skeleton contains the package.json of each package in the monorepo,
# and along with yarn.lock and the root package.json, that's enough to run yarn install.
COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./
RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz
-# install sqlite3 dependencies
-RUN apt-get update && \
- apt-get install -y libsqlite3-dev python3 cmake g++ && \
- rm -rf /var/lib/apt/lists/* && \
- yarn config set python /usr/bin/python3
-
RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)"
# Then copy the rest of the backend bundle, along with any other files we might want.
diff --git a/packages/backend/package.json b/packages/backend/package.json
index aed934a028..df06840aa0 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -1,6 +1,6 @@
{
"name": "example-backend",
- "version": "0.2.70-next.1",
+ "version": "0.2.71-next.0",
"main": "dist/index.cjs.js",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -26,39 +26,39 @@
"build-image": "docker build ../.. -f Dockerfile --tag example-backend"
},
"dependencies": {
- "@backstage/backend-common": "^0.13.2-next.1",
- "@backstage/backend-tasks": "^0.3.0-next.1",
- "@backstage/catalog-client": "^1.0.1-next.0",
- "@backstage/catalog-model": "^1.0.1-next.0",
+ "@backstage/backend-common": "^0.13.3-next.0",
+ "@backstage/backend-tasks": "^0.3.1-next.0",
+ "@backstage/catalog-client": "^1.0.1",
+ "@backstage/catalog-model": "^1.0.1",
"@backstage/config": "^1.0.0",
- "@backstage/integration": "^1.1.0-next.1",
- "@backstage/plugin-app-backend": "^0.3.31-next.0",
- "@backstage/plugin-auth-backend": "^0.13.0-next.1",
- "@backstage/plugin-auth-node": "^0.2.0-next.0",
- "@backstage/plugin-azure-devops-backend": "^0.3.10-next.0",
- "@backstage/plugin-badges-backend": "^0.1.25-next.1",
- "@backstage/plugin-catalog-backend": "^1.1.0-next.1",
- "@backstage/plugin-code-coverage-backend": "^0.1.29-next.1",
- "@backstage/plugin-graphql-backend": "^0.1.21-next.0",
- "@backstage/plugin-jenkins-backend": "^0.1.20-next.1",
- "@backstage/plugin-kubernetes-backend": "^0.4.14-next.0",
- "@backstage/plugin-kafka-backend": "^0.2.24-next.0",
- "@backstage/plugin-permission-backend": "^0.5.6-next.1",
- "@backstage/plugin-permission-common": "^0.6.0-next.0",
- "@backstage/plugin-permission-node": "^0.6.0-next.1",
- "@backstage/plugin-proxy-backend": "^0.2.25-next.0",
- "@backstage/plugin-rollbar-backend": "^0.1.28-next.0",
- "@backstage/plugin-scaffolder-backend": "^1.1.0-next.1",
- "@backstage/plugin-scaffolder-backend-module-rails": "^0.3.6-next.1",
- "@backstage/plugin-search-backend": "^0.5.0-next.1",
- "@backstage/plugin-search-backend-node": "^0.5.3-next.0",
- "@backstage/plugin-search-backend-module-elasticsearch": "^0.1.3-next.0",
- "@backstage/plugin-search-backend-module-pg": "^0.3.2-next.0",
- "@backstage/plugin-techdocs-backend": "^1.0.1-next.1",
- "@backstage/plugin-tech-insights-backend": "^0.3.0-next.1",
- "@backstage/plugin-tech-insights-node": "^0.2.9-next.1",
- "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.15-next.1",
- "@backstage/plugin-todo-backend": "^0.1.28-next.1",
+ "@backstage/integration": "^1.2.0-next.0",
+ "@backstage/plugin-app-backend": "^0.3.32-next.0",
+ "@backstage/plugin-auth-backend": "^0.13.1-next.0",
+ "@backstage/plugin-auth-node": "^0.2.1-next.0",
+ "@backstage/plugin-azure-devops-backend": "^0.3.11-next.0",
+ "@backstage/plugin-badges-backend": "^0.1.26-next.0",
+ "@backstage/plugin-catalog-backend": "^1.1.2-next.0",
+ "@backstage/plugin-code-coverage-backend": "^0.1.30-next.0",
+ "@backstage/plugin-graphql-backend": "^0.1.22-next.0",
+ "@backstage/plugin-jenkins-backend": "^0.1.22-next.0",
+ "@backstage/plugin-kubernetes-backend": "^0.5.1-next.0",
+ "@backstage/plugin-kafka-backend": "^0.2.25-next.0",
+ "@backstage/plugin-permission-backend": "^0.5.7-next.0",
+ "@backstage/plugin-permission-common": "^0.6.0",
+ "@backstage/plugin-permission-node": "^0.6.1-next.0",
+ "@backstage/plugin-proxy-backend": "^0.2.26-next.0",
+ "@backstage/plugin-rollbar-backend": "^0.1.29-next.0",
+ "@backstage/plugin-scaffolder-backend": "^1.2.0-next.0",
+ "@backstage/plugin-scaffolder-backend-module-rails": "^0.3.7-next.0",
+ "@backstage/plugin-search-backend": "^0.5.2-next.0",
+ "@backstage/plugin-search-backend-node": "^0.6.1-next.0",
+ "@backstage/plugin-search-backend-module-elasticsearch": "^0.1.4-next.0",
+ "@backstage/plugin-search-backend-module-pg": "^0.3.3-next.0",
+ "@backstage/plugin-techdocs-backend": "^1.1.1-next.0",
+ "@backstage/plugin-tech-insights-backend": "^0.3.1-next.0",
+ "@backstage/plugin-tech-insights-node": "^0.2.10-next.0",
+ "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.16-next.0",
+ "@backstage/plugin-todo-backend": "^0.1.29-next.0",
"@gitbeaker/node": "^35.1.0",
"@octokit/rest": "^18.5.3",
"better-sqlite3": "^7.5.0",
@@ -75,7 +75,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
- "@backstage/cli": "^0.17.0-next.1",
+ "@backstage/cli": "^0.17.1-next.0",
"@types/dockerode": "^3.3.0",
"@types/express": "^4.17.6",
"@types/express-serve-static-core": "^4.17.5",
diff --git a/packages/backend/src/plugins/auth.ts b/packages/backend/src/plugins/auth.ts
index da8eedcabc..8a60b4b4bd 100644
--- a/packages/backend/src/plugins/auth.ts
+++ b/packages/backend/src/plugins/auth.ts
@@ -14,7 +14,11 @@
* limitations under the License.
*/
-import { createRouter } from '@backstage/plugin-auth-backend';
+import {
+ createRouter,
+ providers,
+ defaultAuthProviderFactories,
+} from '@backstage/plugin-auth-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
@@ -27,5 +31,64 @@ export default async function createPlugin(
database: env.database,
discovery: env.discovery,
tokenManager: env.tokenManager,
+ providerFactories: {
+ ...defaultAuthProviderFactories,
+
+ // NOTE: DO NOT add this many resolvers in your own instance!
+ // It is important that each real user always gets resolved to
+ // the same sign-in identity. The code below will not do that.
+ // It is here for demo purposes only.
+ github: providers.github.create({
+ signIn: {
+ resolver: providers.github.resolvers.usernameMatchingUserEntityName(),
+ },
+ }),
+ gitlab: providers.gitlab.create({
+ signIn: {
+ async resolver({ result: { fullProfile } }, ctx) {
+ return ctx.signInWithCatalogUser({
+ entityRef: {
+ name: fullProfile.id,
+ },
+ });
+ },
+ },
+ }),
+ microsoft: providers.microsoft.create({
+ signIn: {
+ resolver:
+ providers.microsoft.resolvers.emailMatchingUserEntityAnnotation(),
+ },
+ }),
+ google: providers.google.create({
+ signIn: {
+ resolver:
+ providers.google.resolvers.emailLocalPartMatchingUserEntityName(),
+ },
+ }),
+ okta: providers.okta.create({
+ signIn: {
+ resolver:
+ providers.okta.resolvers.emailMatchingUserEntityAnnotation(),
+ },
+ }),
+ bitbucket: providers.bitbucket.create({
+ signIn: {
+ resolver:
+ providers.bitbucket.resolvers.usernameMatchingUserEntityAnnotation(),
+ },
+ }),
+ onelogin: providers.onelogin.create({
+ signIn: {
+ async resolver({ result: { fullProfile } }, ctx) {
+ return ctx.signInWithCatalogUser({
+ entityRef: {
+ name: fullProfile.id,
+ },
+ });
+ },
+ },
+ }),
+ },
});
}
diff --git a/packages/backend/src/plugins/techInsights.ts b/packages/backend/src/plugins/techInsights.ts
index 94ce27656a..80ac559859 100644
--- a/packages/backend/src/plugins/techInsights.ts
+++ b/packages/backend/src/plugins/techInsights.ts
@@ -38,6 +38,7 @@ export default async function createPlugin(
database: env.database,
scheduler: env.scheduler,
discovery: env.discovery,
+ tokenManager: env.tokenManager,
factRetrievers: [
createFactRetrieverRegistration({
cadence: '1 1 1 * *', // Example cron, At 01:01 on day-of-month 1.
diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md
index 4830fd8fb0..968afe294b 100644
--- a/packages/catalog-client/CHANGELOG.md
+++ b/packages/catalog-client/CHANGELOG.md
@@ -1,5 +1,12 @@
# @backstage/catalog-client
+## 1.0.1
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/catalog-model@1.0.1
+
## 1.0.1-next.0
### Patch Changes
diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json
index b01635a0e9..a5af4e21c1 100644
--- a/packages/catalog-client/package.json
+++ b/packages/catalog-client/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/catalog-client",
"description": "An isomorphic client for the catalog backend",
- "version": "1.0.1-next.0",
+ "version": "1.0.1",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -33,12 +33,12 @@
"clean": "backstage-cli package clean"
},
"dependencies": {
- "@backstage/catalog-model": "^1.0.1-next.0",
+ "@backstage/catalog-model": "^1.0.1",
"@backstage/errors": "^1.0.0",
"cross-fetch": "^3.1.5"
},
"devDependencies": {
- "@backstage/cli": "^0.17.0-next.1",
+ "@backstage/cli": "^0.17.1-next.0",
"@types/jest": "^26.0.7",
"msw": "^0.35.0"
},
diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md
index 89756babda..6dd90da2be 100644
--- a/packages/catalog-model/CHANGELOG.md
+++ b/packages/catalog-model/CHANGELOG.md
@@ -1,5 +1,21 @@
# @backstage/catalog-model
+## 1.0.1
+
+### Patch Changes
+
+- e0a51384ac: build(deps): bump `ajv` from 7.0.3 to 8.10.0
+- c12f8374d1: Added a connection between www-artist and artist-lookup components
+
+
+ Screenshots
+
+ 
+
+ 
+
+
+
## 1.0.1-next.1
### Patch Changes
diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json
index 96ccca75cd..4154e1b8df 100644
--- a/packages/catalog-model/package.json
+++ b/packages/catalog-model/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/catalog-model",
"description": "Types and validators that help describe the model of a Backstage Catalog",
- "version": "1.0.1-next.1",
+ "version": "1.0.1",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -43,7 +43,7 @@
"uuid": "^8.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.17.0-next.2",
+ "@backstage/cli": "^0.17.1-next.0",
"@types/jest": "^26.0.7",
"@types/json-schema": "^7.0.5",
"@types/lodash": "^4.14.151",
diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md
index a6070daf8a..de67cbaf80 100644
--- a/packages/cli/CHANGELOG.md
+++ b/packages/cli/CHANGELOG.md
@@ -1,5 +1,89 @@
# @backstage/cli
+## 0.17.1-next.0
+
+### Patch Changes
+
+- 97cce67ac7: Add instructions to `create-github-app` command.
+- 08e12a3a14: Add package global-agent to support behind a proxy for backstage-cli commands like versions:bump.
+- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
+- 344ea56acc: Bump `commander` to version 9.1.0
+- 8ab2a8226b: Updated the `create-github-app` command to throw an error if the organization argument is a user or a non existing organization.
+- Updated dependencies
+ - @backstage/config-loader@1.1.1-next.0
+
+## 0.17.0
+
+### Minor Changes
+
+- 1f7d4763ab: **BREAKING**: Bump the version range of `jest` from `^26.0.1` to `^27.5.1`. You can find the complete list of breaking changes [here](https://github.com/facebook/jest/releases/tag/v27.0.0).
+
+ We strongly recommend to have completed the [package role migration](https://backstage.io/docs/tutorials/package-role-migration) before upgrading to this version, as the package roles are used to automatically determine the testing environment for each package. If you instead want to set an explicit test environment for each package, you can do so for example in the `"jest"` section in `package.json`. The default test environment for all packages is now `node`, which is also the new Jest default.
+
+ Note that one of the breaking changes of Jest 27 is that the `jsdom` environment no longer includes `setImmediate` and `clearImmediate`, which means you might need to update some of your frontend packages. Another notable change is that `jest.useFakeTimers` now defaults to the `'modern'` implementation, which also mocks microtasks.
+
+### Patch Changes
+
+- e80ecad93c: Bump the `rushstack` api generator libraries to their latest versions
+- c54ce828bd: build(deps): bump `eslint-plugin-jest` from 25.3.4 to 26.1.2
+- f151dfee5a: build(deps): bump `eslint-webpack-plugin` from 2.6.0 to 3.1.1
+- 7e7ba704be: build(deps): bump `@spotify/eslint-config-base` from 12.0.0 to 13.0.0
+- ecd72391fb: build(deps): bump `@spotify/eslint-config-typescript`
+- 6a341b2d87: build(deps): bump `@spotify/eslint-config-react` from 12.0.0 to 13.0.0
+- 3c26b2edb5: build(deps): bump `npm-packlist` from 3.0.0 to 5.0.0
+- ed3551b7be: Introduced a new experimental test configuration with a number of changes. It switches the coverage provider from `v8` to the default Babel provider, along with always enabling source maps in the Sucrase transform. It also adds a custom module loader that caches both file transforms and VM script objects across all projects in a test run, which provides a big performance boost when running tests from the project root, increasing speed and reducing memory usage.
+
+ This new configuration is not enabled by default. It is enabled by setting the environment variable `BACKSTAGE_NEXT_TESTS` to a non-empty value.
+
+- 6ad0c45648: Added an experimental `package fix` command which applies automated fixes to the target package. The initial fix that is available is to add missing monorepo dependencies to the target package.
+- 5b3079694e: Stop logging "Stopped watcher" when shutting down the development backend.
+- f512554910: Updated the plugin template to install version 14 of `@testing-library/user-event`.
+
+ To apply this change to your own project, update the `devDependencies` section in your `package.json` files:
+
+ ```diff
+ "devDependencies": {
+ ... omitted dev dependencies ...
+ - "@testing-library/user-event": "^13.1.8",
+ + "@testing-library/user-event": "^14.0.0",
+ ... omitted dev dependencies ...
+ }
+ ```
+
+- df7862cfa6: Fixed a bug were the `react-hot-loader` transform was being applied to backend development builds.
+- 230ad0826f: Bump to using `@types/node` v16
+- c47509e1a0: Implemented changes suggested by Deepsource.io including multiple double non-null assertion operators and unexpected awaits for non-promise values.
+- 948a56f401: Added a new experimental `repo list-deprecations` command, which scans the entire project for usage of deprecated APIs.
+- 4782f9e925: Fixed misleading log message during frontend plugin creation.
+- 0383cd0228: The `versions:*` commands no longer warns about duplicate plugin libraries, such as `@backstage/plugin-catalog-common`.
+- Updated dependencies
+ - @backstage/config-loader@1.1.0
+
+## 0.17.0-next.3
+
+### Patch Changes
+
+- e80ecad93c: Bump the `rushstack` api generator libraries to their latest versions
+- 3c26b2edb5: build(deps): bump `npm-packlist` from 3.0.0 to 5.0.0
+- f512554910: Updated the plugin template to install version 14 of `@testing-library/user-event`.
+
+ To apply this change to your own project, update the `devDependencies` section in your `package.json` files:
+
+ ```diff
+ "devDependencies": {
+ ... omitted dev dependencies ...
+ - "@testing-library/user-event": "^13.1.8",
+ + "@testing-library/user-event": "^14.0.0",
+ ... omitted dev dependencies ...
+ }
+ ```
+
+- df7862cfa6: Fixed a bug were the `react-hot-loader` transform was being applied to backend development builds.
+- 230ad0826f: Bump to using `@types/node` v16
+- 0383cd0228: The `versions:*` commands no longer warns about duplicate plugin libraries, such as `@backstage/plugin-catalog-common`.
+- Updated dependencies
+ - @backstage/config-loader@1.1.0-next.1
+
## 0.17.0-next.2
### Patch Changes
diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js
index 6b9201559b..e5e08b4546 100644
--- a/packages/cli/config/jest.js
+++ b/packages/cli/config/jest.js
@@ -20,6 +20,11 @@ const crypto = require('crypto');
const glob = require('util').promisify(require('glob'));
const { version } = require('../package.json');
+const envOptions = {
+ nextTests: Boolean(process.env.BACKSTAGE_NEXT_TESTS),
+ enableSourceMaps: Boolean(process.env.ENABLE_SOURCE_MAPS),
+};
+
const transformIgnorePattern = [
'@material-ui',
'@rjsf',
@@ -118,7 +123,7 @@ async function getProjectConfig(targetPath, displayName) {
...(displayName && { displayName }),
rootDir: path.resolve(targetPath, 'src'),
coverageDirectory: path.resolve(targetPath, 'coverage'),
- coverageProvider: 'v8',
+ coverageProvider: envOptions.nextTests ? undefined : 'v8',
collectCoverageFrom: ['**/*.{js,jsx,ts,tsx,mjs,cjs}', '!**/*.d.ts'],
moduleNameMapper: {
'\\.(css|less|scss|sss|styl)$': require.resolve('jest-css-modules'),
@@ -127,7 +132,9 @@ async function getProjectConfig(targetPath, displayName) {
transform: {
'\\.(js|jsx|ts|tsx|mjs|cjs)$': [
require.resolve('./jestSucraseTransform.js'),
- { enableSourceMaps: Boolean(process.env.ENABLE_SOURCE_MAPS) },
+ {
+ enableSourceMaps: envOptions.enableSourceMaps || envOptions.nextTests,
+ },
],
'\\.(bmp|gif|jpg|jpeg|png|frag|xml|svg|eot|woff|woff2|ttf)$':
require.resolve('./jestFileTransform.js'),
@@ -137,6 +144,10 @@ async function getProjectConfig(targetPath, displayName) {
// A bit more opinionated
testMatch: ['**/*.test.{js,jsx,ts,tsx,mjs,cjs}'],
+ moduleLoader: envOptions.nextTests
+ ? require.resolve('./jestCachingModuleLoader')
+ : undefined,
+
transformIgnorePatterns: [`/node_modules/(?:${transformIgnorePattern})/`],
...getRoleConfig(closestPkgJson?.backstage?.role),
diff --git a/packages/cli/config/jestCachingModuleLoader.js b/packages/cli/config/jestCachingModuleLoader.js
new file mode 100644
index 0000000000..9ef29d7485
--- /dev/null
+++ b/packages/cli/config/jestCachingModuleLoader.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const fs = require('fs');
+const { default: JestRuntime } = require('jest-runtime');
+
+const fileTransformCache = new Map();
+const scriptTransformCache = new Map();
+
+let runtimeGeneration = 0;
+
+module.exports = class CachingJestRuntime extends JestRuntime {
+ // Each Jest run creates a new runtime, including when rerunning tests in
+ // watch mode. This keeps track of whether we've switched runtime instance.
+ __runtimeGeneration = runtimeGeneration++;
+
+ transformFile(filename, options) {
+ const entry = fileTransformCache.get(filename);
+ if (entry) {
+ // Only check modification time if it's from a different runtime generation
+ if (entry.generation === this.__runtimeGeneration) {
+ return entry.code;
+ }
+
+ // Keep track of the modification time of files so that we can properly
+ // reprocess them in watch mode.
+ const { mtimeMs } = fs.statSync(filename);
+ if (mtimeMs > entry.mtimeMs) {
+ const code = super.transformFile(filename, options);
+ fileTransformCache.set(filename, {
+ code,
+ mtimeMs,
+ generation: this.__runtimeGeneration,
+ });
+ return code;
+ }
+
+ fileTransformCache.set(filename, {
+ ...entry,
+ generation: this.__runtimeGeneration,
+ });
+ return entry.code;
+ }
+
+ const code = super.transformFile(filename, options);
+ fileTransformCache.set(filename, {
+ code,
+ mtimeMs: fs.statSync(filename).mtimeMs,
+ generation: this.__runtimeGeneration,
+ });
+ return code;
+ }
+
+ // This may or may not be a good idea. Theoretically I don't know why this would impact
+ // test correctness and flakiness, but it seems like it may introduce flakiness and strange failures.
+ // It does seem to speed up test execution by a fair amount though.
+ createScriptFromCode(scriptSource, filename) {
+ let script = scriptTransformCache.get(scriptSource);
+ if (!script) {
+ script = super.createScriptFromCode(scriptSource, filename);
+ // Tried to store the script object in a WeakRef here. It starts out at
+ // about 90% hit rate, but eventually drops all the way to 20%, and overall
+ // it seemed to increase memory usage by 20% or so.
+ scriptTransformCache.set(scriptSource, script);
+ }
+ return script;
+ }
+};
diff --git a/packages/cli/package.json b/packages/cli/package.json
index bd8964ef68..67af644dfa 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/cli",
"description": "CLI for developing Backstage plugins and apps",
- "version": "0.17.0-next.2",
+ "version": "0.17.1-next.0",
"private": false,
"publishConfig": {
"access": "public"
@@ -33,7 +33,7 @@
"dependencies": {
"@backstage/cli-common": "^0.1.8",
"@backstage/config": "^1.0.0",
- "@backstage/config-loader": "^1.0.1-next.0",
+ "@backstage/config-loader": "^1.1.1-next.0",
"@backstage/errors": "^1.0.0",
"@backstage/release-manifests": "^0.0.2",
"@backstage/types": "^1.0.0",
@@ -62,7 +62,7 @@
"buffer": "^6.0.3",
"chalk": "^4.0.0",
"chokidar": "^3.3.1",
- "commander": "^6.1.0",
+ "commander": "^9.1.0",
"css-loader": "^6.5.1",
"diff": "^5.0.0",
"esbuild": "^0.14.10",
@@ -80,18 +80,21 @@
"eslint-webpack-plugin": "^3.1.1",
"express": "^4.17.1",
"fork-ts-checker-webpack-plugin": "^7.0.0-alpha.8",
- "fs-extra": "10.0.1",
+ "fs-extra": "10.1.0",
"glob": "^7.1.7",
+ "global-agent": "^3.0.0",
"handlebars": "^4.7.3",
"html-webpack-plugin": "^5.3.1",
"inquirer": "^8.2.0",
"jest": "^27.5.1",
+ "jest-runtime": "^27.5.1",
"jest-css-modules": "^2.1.0",
"jest-transform-yaml": "^1.0.0",
"json-schema": "^0.4.0",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.4.2",
"minimatch": "5.0.1",
+ "node-fetch": "^2.6.7",
"node-libs-browser": "^2.2.1",
"npm-packlist": "^5.0.0",
"ora": "^5.3.0",
@@ -122,13 +125,13 @@
"zod": "^3.11.6"
},
"devDependencies": {
- "@backstage/backend-common": "^0.13.2-next.1",
+ "@backstage/backend-common": "^0.13.3-next.0",
"@backstage/config": "^1.0.0",
- "@backstage/core-app-api": "^1.0.1-next.0",
- "@backstage/core-components": "^0.9.3-next.1",
- "@backstage/core-plugin-api": "^1.0.0",
- "@backstage/dev-utils": "^1.0.1-next.0",
- "@backstage/test-utils": "^1.0.1-next.1",
+ "@backstage/core-app-api": "^1.0.1",
+ "@backstage/core-components": "^0.9.3",
+ "@backstage/core-plugin-api": "^1.0.1",
+ "@backstage/dev-utils": "^1.0.2-next.0",
+ "@backstage/test-utils": "^1.0.2-next.0",
"@backstage/theme": "^0.2.15",
"@types/diff": "^5.0.0",
"@types/express": "^4.17.6",
diff --git a/packages/cli/src/commands/app/build.ts b/packages/cli/src/commands/app/build.ts
index 67b71632c7..f90052bc83 100644
--- a/packages/cli/src/commands/app/build.ts
+++ b/packages/cli/src/commands/app/build.ts
@@ -15,20 +15,20 @@
*/
import fs from 'fs-extra';
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { buildBundle } from '../../lib/bundler';
import { getEnvironmentParallelism } from '../../lib/parallel';
import { loadCliConfig } from '../../lib/config';
import { paths } from '../../lib/paths';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
const { name } = await fs.readJson(paths.resolveTarget('package.json'));
await buildBundle({
entry: 'src/index',
parallelism: getEnvironmentParallelism(),
- statsJsonEnabled: cmd.stats,
+ statsJsonEnabled: opts.stats,
...(await loadCliConfig({
- args: cmd.config,
+ args: opts.config,
fromPackage: name,
})),
});
diff --git a/packages/cli/src/commands/app/serve.ts b/packages/cli/src/commands/app/serve.ts
index 716d47bd4c..e41c2367da 100644
--- a/packages/cli/src/commands/app/serve.ts
+++ b/packages/cli/src/commands/app/serve.ts
@@ -17,14 +17,14 @@
import fs from 'fs-extra';
import chalk from 'chalk';
import uniq from 'lodash/uniq';
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { serveBundle } from '../../lib/bundler';
import { loadCliConfig } from '../../lib/config';
import { paths } from '../../lib/paths';
import { Lockfile } from '../../lib/versioning';
import { forbiddenDuplicatesFilter, includedFilter } from '../versions/lint';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
const lockFilePath = paths.resolveTargetRoot('yarn.lock');
if (fs.existsSync(lockFilePath)) {
try {
@@ -80,9 +80,9 @@ export default async (cmd: Command) => {
const { name } = await fs.readJson(paths.resolveTarget('package.json'));
const waitForExit = await serveBundle({
entry: 'src/index',
- checksEnabled: cmd.check,
+ checksEnabled: opts.check,
...(await loadCliConfig({
- args: cmd.config,
+ args: opts.config,
fromPackage: name,
withFilteredKeys: true,
})),
diff --git a/packages/cli/src/commands/backend/build.ts b/packages/cli/src/commands/backend/build.ts
index 5d4e17e392..c85eecfed3 100644
--- a/packages/cli/src/commands/backend/build.ts
+++ b/packages/cli/src/commands/backend/build.ts
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { buildPackage, Output } from '../../lib/builder';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
await buildPackage({
outputs: new Set([Output.cjs, Output.types]),
- minify: cmd.minify,
- useApiExtractor: cmd.experimentalTypeBuild,
+ minify: opts.minify,
+ useApiExtractor: opts.experimentalTypeBuild,
});
};
diff --git a/packages/cli/src/commands/backend/bundle.ts b/packages/cli/src/commands/backend/bundle.ts
index ec5fa0a131..78d4d72d92 100644
--- a/packages/cli/src/commands/backend/bundle.ts
+++ b/packages/cli/src/commands/backend/bundle.ts
@@ -18,7 +18,7 @@ import os from 'os';
import fs from 'fs-extra';
import { resolve as resolvePath } from 'path';
import tar, { CreateOptions } from 'tar';
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { createDistWorkspace } from '../../lib/packager';
import { paths } from '../../lib/paths';
import { getEnvironmentParallelism } from '../../lib/parallel';
@@ -27,7 +27,7 @@ import { buildPackage, Output } from '../../lib/builder';
const BUNDLE_FILE = 'bundle.tar.gz';
const SKELETON_FILE = 'skeleton.tar.gz';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
const targetDir = paths.resolveTarget('dist');
const pkg = await fs.readJson(paths.resolveTarget('package.json'));
@@ -38,7 +38,7 @@ export default async (cmd: Command) => {
try {
await createDistWorkspace([pkg.name], {
targetDir: tmpDir,
- buildDependencies: Boolean(cmd.buildDependencies),
+ buildDependencies: Boolean(opts.buildDependencies),
buildExcludes: [pkg.name],
parallelism: getEnvironmentParallelism(),
skeleton: SKELETON_FILE,
diff --git a/packages/cli/src/commands/backend/dev.ts b/packages/cli/src/commands/backend/dev.ts
index b14a1f3e20..2ee43958a2 100644
--- a/packages/cli/src/commands/backend/dev.ts
+++ b/packages/cli/src/commands/backend/dev.ts
@@ -15,11 +15,11 @@
*/
import fs from 'fs-extra';
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { paths } from '../../lib/paths';
import { serveBackend } from '../../lib/bundler/backend';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
// Cleaning dist/ before we start the dev process helps work around an issue
// where we end up with the entrypoint executing multiple times, causing
// a port bind conflict among other things.
@@ -27,9 +27,9 @@ export default async (cmd: Command) => {
const waitForExit = await serveBackend({
entry: 'src/index',
- checksEnabled: cmd.check,
- inspectEnabled: cmd.inspect,
- inspectBrkEnabled: cmd.inspectBrk,
+ checksEnabled: opts.check,
+ inspectEnabled: opts.inspect,
+ inspectBrkEnabled: opts.inspectBrk,
});
await waitForExit();
diff --git a/packages/cli/src/commands/build/command.ts b/packages/cli/src/commands/build/command.ts
index 5c8065dbb4..fcaf58e1ee 100644
--- a/packages/cli/src/commands/build/command.ts
+++ b/packages/cli/src/commands/build/command.ts
@@ -14,27 +14,27 @@
* limitations under the License.
*/
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { buildPackage, Output } from '../../lib/builder';
import { findRoleFromCommand, getRoleInfo } from '../../lib/role';
import { paths } from '../../lib/paths';
import { buildFrontend } from './buildFrontend';
import { buildBackend } from './buildBackend';
-export async function command(cmd: Command): Promise {
- const role = await findRoleFromCommand(cmd);
+export async function command(opts: OptionValues): Promise {
+ const role = await findRoleFromCommand(opts);
if (role === 'frontend') {
return buildFrontend({
targetDir: paths.targetDir,
- configPaths: cmd.config as string[],
- writeStats: Boolean(cmd.stats),
+ configPaths: opts.config as string[],
+ writeStats: Boolean(opts.stats),
});
}
if (role === 'backend') {
return buildBackend({
targetDir: paths.targetDir,
- skipBuildDependencies: Boolean(cmd.skipBuildDependencies),
+ skipBuildDependencies: Boolean(opts.skipBuildDependencies),
});
}
@@ -54,7 +54,7 @@ export async function command(cmd: Command): Promise {
return buildPackage({
outputs,
- minify: Boolean(cmd.minify),
- useApiExtractor: Boolean(cmd.experimentalTypeBuild),
+ minify: Boolean(opts.minify),
+ useApiExtractor: Boolean(opts.experimentalTypeBuild),
});
}
diff --git a/packages/cli/src/commands/buildWorkspace.ts b/packages/cli/src/commands/buildWorkspace.ts
index 7a7aa28ad6..97bf2f1239 100644
--- a/packages/cli/src/commands/buildWorkspace.ts
+++ b/packages/cli/src/commands/buildWorkspace.ts
@@ -15,10 +15,9 @@
*/
import fs from 'fs-extra';
-import { Command } from 'commander';
import { createDistWorkspace } from '../lib/packager';
-export default async (dir: string, _cmd: Command, packages: string[]) => {
+export default async (dir: string, packages: string[]) => {
if (!(await fs.pathExists(dir))) {
throw new Error(`Target workspace directory doesn't exist, '${dir}'`);
}
diff --git a/packages/cli/src/commands/config/docs.ts b/packages/cli/src/commands/config/docs.ts
index 7a807f7c78..98e683e87c 100644
--- a/packages/cli/src/commands/config/docs.ts
+++ b/packages/cli/src/commands/config/docs.ts
@@ -16,17 +16,17 @@
import { JsonObject } from '@backstage/types';
import { mergeConfigSchemas } from '@backstage/config-loader';
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { JSONSchema7 as JSONSchema } from 'json-schema';
import openBrowser from 'react-dev-utils/openBrowser';
import { loadCliConfig } from '../../lib/config';
const DOCS_URL = 'https://config.backstage.io';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
const { schema: appSchemas } = await loadCliConfig({
args: [],
- fromPackage: cmd.package,
+ fromPackage: opts.package,
mockEnv: true,
});
diff --git a/packages/cli/src/commands/config/print.ts b/packages/cli/src/commands/config/print.ts
index b640ee4f37..9ef725ebf8 100644
--- a/packages/cli/src/commands/config/print.ts
+++ b/packages/cli/src/commands/config/print.ts
@@ -14,36 +14,36 @@
* limitations under the License.
*/
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { stringify as stringifyYaml } from 'yaml';
import { AppConfig, ConfigReader } from '@backstage/config';
import { loadCliConfig } from '../../lib/config';
import { ConfigSchema, ConfigVisibility } from '@backstage/config-loader';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
const { schema, appConfigs } = await loadCliConfig({
- args: cmd.config,
- fromPackage: cmd.package,
- mockEnv: cmd.lax,
- fullVisibility: !cmd.frontend,
+ args: opts.config,
+ fromPackage: opts.package,
+ mockEnv: opts.lax,
+ fullVisibility: !opts.frontend,
});
- const visibility = getVisibilityOption(cmd);
+ const visibility = getVisibilityOption(opts);
const data = serializeConfigData(appConfigs, schema, visibility);
- if (cmd.format === 'json') {
+ if (opts.format === 'json') {
process.stdout.write(`${JSON.stringify(data, null, 2)}\n`);
} else {
process.stdout.write(`${stringifyYaml(data)}\n`);
}
};
-function getVisibilityOption(cmd: Command): ConfigVisibility {
- if (cmd.frontend && cmd.withSecrets) {
+function getVisibilityOption(opts: OptionValues): ConfigVisibility {
+ if (opts.frontend && opts.withSecrets) {
throw new Error('Not allowed to combine frontend and secret config');
}
- if (cmd.frontend) {
+ if (opts.frontend) {
return 'frontend';
- } else if (cmd.withSecrets) {
+ } else if (opts.withSecrets) {
return 'secret';
}
return 'backend';
diff --git a/packages/cli/src/commands/config/schema.ts b/packages/cli/src/commands/config/schema.ts
index be228e1e7c..f9e6573be6 100644
--- a/packages/cli/src/commands/config/schema.ts
+++ b/packages/cli/src/commands/config/schema.ts
@@ -14,17 +14,17 @@
* limitations under the License.
*/
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { JSONSchema7 as JSONSchema } from 'json-schema';
import { stringify as stringifyYaml } from 'yaml';
import { loadCliConfig } from '../../lib/config';
import { JsonObject } from '@backstage/types';
import { mergeConfigSchemas } from '@backstage/config-loader';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
const { schema } = await loadCliConfig({
args: [],
- fromPackage: cmd.package,
+ fromPackage: opts.package,
mockEnv: true,
});
@@ -38,7 +38,7 @@ export default async (cmd: Command) => {
merged.description =
'This is the schema describing the structure of the app-config.yaml configuration file.';
- if (cmd.format === 'json') {
+ if (opts.format === 'json') {
process.stdout.write(`${JSON.stringify(merged, null, 2)}\n`);
} else {
process.stdout.write(`${stringifyYaml(merged)}\n`);
diff --git a/packages/cli/src/commands/config/validate.ts b/packages/cli/src/commands/config/validate.ts
index 8d528b8300..c3d05291e0 100644
--- a/packages/cli/src/commands/config/validate.ts
+++ b/packages/cli/src/commands/config/validate.ts
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { loadCliConfig } from '../../lib/config';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
await loadCliConfig({
- args: cmd.config,
- fromPackage: cmd.package,
- mockEnv: cmd.lax,
- fullVisibility: !cmd.frontend,
- withDeprecatedKeys: cmd.deprecated,
+ args: opts.config,
+ fromPackage: opts.package,
+ mockEnv: opts.lax,
+ fullVisibility: !opts.frontend,
+ withDeprecatedKeys: opts.deprecated,
});
};
diff --git a/packages/cli/src/commands/create-github-app/index.ts b/packages/cli/src/commands/create-github-app/index.ts
index c62234c636..32fa1e9a6d 100644
--- a/packages/cli/src/commands/create-github-app/index.ts
+++ b/packages/cli/src/commands/create-github-app/index.ts
@@ -19,11 +19,13 @@ import chalk from 'chalk';
import { stringify as stringifyYaml } from 'yaml';
import { paths } from '../../lib/paths';
import { GithubCreateAppServer } from './GithubCreateAppServer';
+import fetch from 'node-fetch';
// This is an experimental command that at this point does not support GitHub Enterprise
// due to lacking support for creating apps from manifests.
// https://docs.github.com/en/free-pro-team@latest/developers/apps/creating-a-github-app-from-a-manifest
export default async (org: string) => {
+ await verifyGithubOrg(org);
const { slug, name, ...config } = await GithubCreateAppServer.run({ org });
const fileName = `github-app-${slug}-credentials.yaml`;
@@ -35,5 +37,38 @@ export default async (org: string) => {
'This file contains sensitive credentials, it should not be committed to version control and handled with care!',
),
);
- // TODO: log instructions on how to use the newly created app configuration.
+ console.log(
+ "Here's an example on how to update the integrations section in app-config.yaml",
+ );
+ console.log(
+ chalk.green(`
+integrations:
+ github:
+ - host: github.com
+ apps:
+ - $include: ${fileName}`),
+ );
};
+
+async function verifyGithubOrg(org: string): Promise {
+ let response;
+
+ try {
+ response = await fetch(
+ `https://api.github.com/orgs/${encodeURIComponent(org)}`,
+ );
+ } catch (e) {
+ console.log(
+ chalk.yellow(
+ 'Warning: Unable to verify existence of GitHub organization. ',
+ e,
+ ),
+ );
+ }
+
+ if (response?.status === 404) {
+ throw new Error(
+ `GitHub organization '${org}' does not exist. Please verify the name and try again.`,
+ );
+ }
+}
diff --git a/packages/cli/src/commands/create-plugin/createPlugin.ts b/packages/cli/src/commands/create-plugin/createPlugin.ts
index c80129662c..a12060bbd2 100644
--- a/packages/cli/src/commands/create-plugin/createPlugin.ts
+++ b/packages/cli/src/commands/create-plugin/createPlugin.ts
@@ -23,7 +23,7 @@ import { resolve as resolvePath, join as joinPath } from 'path';
import camelCase from 'lodash/camelCase';
import upperFirst from 'lodash/upperFirst';
import os from 'os';
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { assertError } from '@backstage/errors';
import {
parseOwnerIds,
@@ -195,7 +195,7 @@ export async function movePlugin(
});
}
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
const codeownersPath = await getCodeownersFilePath(paths.targetRoot);
const questions: Question[] = [
@@ -242,21 +242,21 @@ export default async (cmd: Command) => {
const answers: Answers = await inquirer.prompt(questions);
const pluginId =
- cmd.backend && !answers.id.endsWith('-backend')
+ opts.backend && !answers.id.endsWith('-backend')
? `${answers.id}-backend`
: answers.id;
- const name = cmd.scope
- ? `@${cmd.scope.replace(/^@/, '')}/plugin-${pluginId}`
+ const name = opts.scope
+ ? `@${opts.scope.replace(/^@/, '')}/plugin-${pluginId}`
: `plugin-${pluginId}`;
const pluginVar = `${camelCase(answers.id)}Plugin`;
const extensionName = `${upperFirst(camelCase(answers.id))}Page`;
- const npmRegistry = cmd.npmRegistry && cmd.scope ? cmd.npmRegistry : '';
- const privatePackage = cmd.private === false ? false : true;
+ const npmRegistry = opts.npmRegistry && opts.scope ? opts.npmRegistry : '';
+ const privatePackage = opts.private === false ? false : true;
const isMonoRepo = await fs.pathExists(paths.resolveTargetRoot('lerna.json'));
const appPackage = paths.resolveTargetRoot('packages/app');
const templateDir = paths.resolveOwn(
- cmd.backend
+ opts.backend
? 'templates/default-backend-plugin'
: 'templates/default-plugin',
);
@@ -309,7 +309,7 @@ export default async (cmd: Command) => {
Task.section('Building the plugin');
await buildPlugin(pluginDir);
- if ((await fs.pathExists(appPackage)) && !cmd.backend) {
+ if ((await fs.pathExists(appPackage)) && !opts.backend) {
Task.section('Adding plugin as dependency in app');
await addPluginDependencyToApp(paths.targetRoot, name, pluginVersion);
diff --git a/packages/cli/src/commands/create/create.ts b/packages/cli/src/commands/create/create.ts
index 64067e1b7e..c784307738 100644
--- a/packages/cli/src/commands/create/create.ts
+++ b/packages/cli/src/commands/create/create.ts
@@ -17,7 +17,7 @@
import os from 'os';
import fs from 'fs-extra';
import { join as joinPath } from 'path';
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { FactoryRegistry } from '../../lib/create/FactoryRegistry';
import { paths } from '../../lib/paths';
import { assertError } from '@backstage/errors';
@@ -40,12 +40,10 @@ function parseOptions(optionStrings: string[]): Record {
return options;
}
-export default async (cmd: Command) => {
- const cmdOpts = cmd.opts();
+export default async (opts: OptionValues) => {
+ const factory = await FactoryRegistry.interactiveSelect(opts.select);
- const factory = await FactoryRegistry.interactiveSelect(cmdOpts.select);
-
- const providedOptions = parseOptions(cmdOpts.option);
+ const providedOptions = parseOptions(opts.option);
const options = await FactoryRegistry.populateOptions(
factory,
providedOptions,
@@ -93,9 +91,9 @@ export default async (cmd: Command) => {
await factory.create(options, {
isMonoRepo,
defaultVersion,
- scope: cmdOpts.scope?.replace(/^@/, ''),
- npmRegistry: cmdOpts.npmRegistry,
- private: Boolean(cmdOpts.private),
+ scope: opts.scope?.replace(/^@/, ''),
+ npmRegistry: opts.npmRegistry,
+ private: Boolean(opts.private),
createTemporaryDirectory,
markAsModified() {
modified = true;
diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts
index 2f345e8663..1a7b2c4f08 100644
--- a/packages/cli/src/commands/index.ts
+++ b/packages/cli/src/commands/index.ts
@@ -15,17 +15,17 @@
*/
import { assertError } from '@backstage/errors';
-import { CommanderStatic } from 'commander';
+import { Command } from 'commander';
import { exitWithError } from '../lib/errors';
const configOption = [
'--config ',
'Config files to load instead of app-config.yaml',
- (opt: string, opts: string[]) => [...opts, opt],
+ (opt: string, opts: string[]) => (opts ? [...opts, opt] : [opt]),
Array(),
] as const;
-export function registerRepoCommand(program: CommanderStatic) {
+export function registerRepoCommand(program: Command) {
const command = program
.command('repo [command]')
.description('Command that run across an entire Backstage project');
@@ -69,7 +69,7 @@ export function registerRepoCommand(program: CommanderStatic) {
);
}
-export function registerScriptCommand(program: CommanderStatic) {
+export function registerScriptCommand(program: Command) {
const command = program
.command('package [command]')
.description('Lifecycle scripts for individual packages');
@@ -110,13 +110,13 @@ export function registerScriptCommand(program: CommanderStatic) {
.option(
'--config ',
'Config files to load instead of app-config.yaml. Applies to app packages only.',
- (opt: string, opts: string[]) => [...opts, opt],
+ (opt: string, opts: string[]) => (opts ? [...opts, opt] : [opt]),
Array(),
)
.action(lazy(() => import('./build').then(m => m.command)));
command
- .command('lint')
+ .command('lint [directories...]')
.option(
'--format ',
'Lint report output format',
@@ -131,7 +131,7 @@ export function registerScriptCommand(program: CommanderStatic) {
.allowUnknownOption(true) // Allows the command to run, but we still need to parse raw args
.helpOption(', --backstage-cli-help') // Let Jest handle help
.description('Run tests, forwarding args to Jest, defaulting to watch mode')
- .action(lazy(() => import('./testCommand').then(m => m.default)));
+ .action(lazy(() => import('./test').then(m => m.default)));
command
.command('fix', { hidden: true })
@@ -155,7 +155,7 @@ export function registerScriptCommand(program: CommanderStatic) {
.action(lazy(() => import('./pack').then(m => m.post)));
}
-export function registerMigrateCommand(program: CommanderStatic) {
+export function registerMigrateCommand(program: Command) {
const command = program
.command('migrate [command]')
.description('Migration utilities');
@@ -182,7 +182,7 @@ export function registerMigrateCommand(program: CommanderStatic) {
);
}
-export function registerCommands(program: CommanderStatic) {
+export function registerCommands(program: Command) {
// TODO(Rugvip): Deprecate in favor of package variant
program
.command('app:build')
@@ -302,7 +302,7 @@ export function registerCommands(program: CommanderStatic) {
// TODO(Rugvip): Deprecate in favor of package variant
program
- .command('lint')
+ .command('lint [directories...]')
.option(
'--format ',
'Lint report output format',
@@ -320,7 +320,7 @@ export function registerCommands(program: CommanderStatic) {
.description(
'Run tests, forwarding args to Jest, defaulting to watch mode [DEPRECATED]',
)
- .action(lazy(() => import('./testCommand').then(m => m.default)));
+ .action(lazy(() => import('./test').then(m => m.default)));
program
.command('config:docs')
@@ -423,7 +423,7 @@ export function registerCommands(program: CommanderStatic) {
.action(lazy(() => import('./clean/clean').then(m => m.default)));
program
- .command('build-workspace ...')
+ .command('build-workspace [packages...]')
.description('Builds a temporary dist workspace from the provided packages')
.action(lazy(() => import('./buildWorkspace').then(m => m.default)));
diff --git a/packages/cli/src/commands/install/install.ts b/packages/cli/src/commands/install/install.ts
index bd3a05ebc1..e395088b3e 100644
--- a/packages/cli/src/commands/install/install.ts
+++ b/packages/cli/src/commands/install/install.ts
@@ -22,7 +22,7 @@ import {
import { fetchPackageInfo } from '../../lib/versioning';
import { NotFoundError } from '../../lib/errors';
import * as stepDefinitionMap from './steps';
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import fs from 'fs-extra';
const stepDefinitions = Object.values(stepDefinitionMap);
@@ -154,7 +154,7 @@ async function loadPeerPluginDeps(
}
}
-export default async (pluginId?: string, cmd?: Command) => {
+export default async (pluginId?: string, cmd?: OptionValues) => {
const from = pluginId || cmd?.from;
// TODO(himanshu): If no plugin id is provided, it should list all plugins available. Maybe in some other command?
if (!from) {
diff --git a/packages/cli/src/commands/lint.ts b/packages/cli/src/commands/lint.ts
index 823d24fbe8..87c353f56f 100644
--- a/packages/cli/src/commands/lint.ts
+++ b/packages/cli/src/commands/lint.ts
@@ -14,27 +14,29 @@
* limitations under the License.
*/
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
import { paths } from '../lib/paths';
import { ESLint } from 'eslint';
-export default async (cmd: Command, cmdArgs: string[]) => {
+export default async (directories: string[], opts: OptionValues) => {
const eslint = new ESLint({
cwd: paths.targetDir,
- fix: cmd.fix,
+ fix: opts.fix,
extensions: ['js', 'jsx', 'ts', 'tsx', 'mjs', 'cjs'],
});
- const results = await eslint.lintFiles(cmdArgs ?? ['.']);
+ const results = await eslint.lintFiles(
+ directories.length ? directories : ['.'],
+ );
- if (cmd.fix) {
+ if (opts.fix) {
await ESLint.outputFixes(results);
}
- const formatter = await eslint.loadFormatter(cmd.format);
+ const formatter = await eslint.loadFormatter(opts.format);
// This formatter uses the cwd to format file paths, so let's have that happen from the root instead
- if (cmd.format === 'eslint-formatter-friendly') {
+ if (opts.format === 'eslint-formatter-friendly') {
process.chdir(paths.targetRoot);
}
const resultText = formatter.format(results);
diff --git a/packages/cli/src/commands/oldBuild.ts b/packages/cli/src/commands/oldBuild.ts
index 86ab5c4300..c0899d4d02 100644
--- a/packages/cli/src/commands/oldBuild.ts
+++ b/packages/cli/src/commands/oldBuild.ts
@@ -15,12 +15,12 @@
*/
import { buildPackage, Output } from '../lib/builder';
-import { Command } from 'commander';
+import { OptionValues } from 'commander';
-export default async (cmd: Command) => {
+export default async (opts: OptionValues) => {
let outputs = new Set