diff --git a/.changeset/angry-bottles-mix.md b/.changeset/angry-bottles-mix.md
deleted file mode 100644
index cd05ef6514..0000000000
--- a/.changeset/angry-bottles-mix.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Added a new experimental and hidden `backstage-cli repo lint` command that can be used to lint all packages in the project, similar to `lerna run lint`.
diff --git a/.changeset/beige-feet-tap.md b/.changeset/beige-feet-tap.md
deleted file mode 100644
index b37d249700..0000000000
--- a/.changeset/beige-feet-tap.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-techdocs-backend': patch
----
-
-Do not use cross-fetch in the backend
diff --git a/.changeset/blue-jobs-know.md b/.changeset/blue-jobs-know.md
deleted file mode 100644
index 35feed552b..0000000000
--- a/.changeset/blue-jobs-know.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-The `versions:bump --release next` command is updated to compare the `main` and `next` release manifests and prefer the latest.
diff --git a/.changeset/brave-singers-burn.md b/.changeset/brave-singers-burn.md
deleted file mode 100644
index e8ccfb42e7..0000000000
--- a/.changeset/brave-singers-burn.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-The following processors now properly accept an `ScmIntegrationRegistry` (an
-interface) instead of an `ScmIntegrations` (which is a concrete class).
-
-- `AzureDevOpsDiscoveryProcessor`
-- `CodeOwnersProcessor`
-- `GitLabDiscoveryProcessor`
-- `GithubDiscoveryProcessor`
-- `GithubMultiOrgReaderProcessor`
-- `GithubOrgReaderProcessor`
diff --git a/.changeset/bright-games-eat.md b/.changeset/bright-games-eat.md
deleted file mode 100644
index 3bae70283f..0000000000
--- a/.changeset/bright-games-eat.md
+++ /dev/null
@@ -1,24 +0,0 @@
----
-'@backstage/create-app': patch
----
-
-Remove SearchContextProvider from ``
-
-The `SidebarSearchModal` exported from `plugin-search` internally renders `SearchContextProvider`, so it can be removed from `Root.tsx`:
-
-```diff
--import {
-- SidebarSearchModal,
-- SearchContextProvider,
--} from '@backstage/plugin-search';
-+import { SidebarSearchModal } from '@backstage/plugin-search';
-
-... omitted ...
-
- } to="/search">
--
--
--
-+
-
-```
diff --git a/.changeset/bright-nails-grin.md b/.changeset/bright-nails-grin.md
deleted file mode 100644
index 434a17efbb..0000000000
--- a/.changeset/bright-nails-grin.md
+++ /dev/null
@@ -1,78 +0,0 @@
----
-'@backstage/backend-common': patch
-'@backstage/catalog-client': patch
-'@backstage/cli': patch
-'@backstage/config-loader': patch
-'@backstage/core-app-api': patch
-'@backstage/core-components': patch
-'@backstage/core-plugin-api': patch
-'@backstage/errors': patch
-'@backstage/integration': patch
-'@backstage/integration-react': patch
-'@backstage/release-manifests': 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-auth-backend': patch
-'@backstage/plugin-auth-node': patch
-'@backstage/plugin-azure-devops': patch
-'@backstage/plugin-badges': patch
-'@backstage/plugin-bazaar': patch
-'@backstage/plugin-bitrise': patch
-'@backstage/plugin-catalog': patch
-'@backstage/plugin-catalog-backend': patch
-'@backstage/plugin-catalog-backend-module-msgraph': patch
-'@backstage/plugin-catalog-graphql': patch
-'@backstage/plugin-catalog-import': patch
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-circleci': patch
-'@backstage/plugin-cloudbuild': 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-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-newrelic-dashboard': patch
-'@backstage/plugin-org': patch
-'@backstage/plugin-pagerduty': patch
-'@backstage/plugin-permission-backend': patch
-'@backstage/plugin-permission-common': patch
-'@backstage/plugin-permission-react': patch
-'@backstage/plugin-rollbar': patch
-'@backstage/plugin-rollbar-backend': patch
-'@backstage/plugin-scaffolder': patch
-'@backstage/plugin-scaffolder-backend': 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-tech-insights': patch
-'@backstage/plugin-tech-radar': patch
-'@backstage/plugin-techdocs': patch
-'@backstage/plugin-techdocs-backend': patch
-'@backstage/plugin-todo': patch
-'@backstage/plugin-user-settings': patch
-'@backstage/plugin-xcmetrics': patch
----
-
-Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
diff --git a/.changeset/brown-impalas-greet.md b/.changeset/brown-impalas-greet.md
deleted file mode 100644
index 1717c33451..0000000000
--- a/.changeset/brown-impalas-greet.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend': patch
----
-
-Fix error handling of the `runCommand` helper to return `Error`
-instance.
diff --git a/.changeset/chilly-goats-suffer.md b/.changeset/chilly-goats-suffer.md
new file mode 100644
index 0000000000..da98b4019b
--- /dev/null
+++ b/.changeset/chilly-goats-suffer.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+Applied fix from version 0.17.2 of this package, which is part of the v0.69.2 release of Backstage.
diff --git a/.changeset/clever-pears-turn.md b/.changeset/clever-pears-turn.md
deleted file mode 100644
index 33e08c231b..0000000000
--- a/.changeset/clever-pears-turn.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-'@backstage/plugin-catalog': patch
-'@backstage/plugin-catalog-backend': patch
-'@backstage/plugin-catalog-graph': patch
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-org': patch
-'@backstage/plugin-scaffolder': patch
-'@backstage/plugin-tech-insights-backend': patch
----
-
-Use updated type names from `@backstage/catalog-client`
diff --git a/.changeset/curvy-worms-exercise.md b/.changeset/curvy-worms-exercise.md
deleted file mode 100644
index b88e9b5891..0000000000
--- a/.changeset/curvy-worms-exercise.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/catalog-model': patch
----
-
-Deprecated `parseLocationReference` and `stringifyLocationReference`,
-introducing `parseLocationRef` and `stringifyLocationRef` in their place.
diff --git a/.changeset/cyan-oranges-sit.md b/.changeset/cyan-oranges-sit.md
deleted file mode 100644
index 8a3244745f..0000000000
--- a/.changeset/cyan-oranges-sit.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/catalog-model': patch
----
-
-Deprecates the `Location` type export from this package. Imports of the `Location` type should now be done from the `@backstage/catalog-client` package instead.
diff --git a/.changeset/dependabot-8ed326b.md b/.changeset/dependabot-8ed326b.md
deleted file mode 100644
index 88a91baeac..0000000000
--- a/.changeset/dependabot-8ed326b.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-search-backend-module-elasticsearch': patch
----
-
-chore(deps-dev): bump `@elastic/elasticsearch-mock` from 0.3.0 to 1.0.0
diff --git a/.changeset/dry-lies-move.md b/.changeset/dry-lies-move.md
deleted file mode 100644
index b0eb1be6f7..0000000000
--- a/.changeset/dry-lies-move.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-todo-backend': patch
----
-
-Replace usage of `serializeEntityRef` with `stringifyEntityRef`
diff --git a/.changeset/eight-adults-joke.md b/.changeset/eight-adults-joke.md
new file mode 100644
index 0000000000..ffda738213
--- /dev/null
+++ b/.changeset/eight-adults-joke.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-analytics-module-ga': patch
+---
+
+Added CSP instructions to README
diff --git a/.changeset/fair-bees-join.md b/.changeset/fair-bees-join.md
deleted file mode 100644
index 455547cec2..0000000000
--- a/.changeset/fair-bees-join.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/catalog-model': patch
----
-
-Deprecated `ENTITY_DEFAULT_NAMESPACE` constant in favour of `DEFAULT_NAMESPACE`.
diff --git a/.changeset/fair-emus-check.md b/.changeset/fair-emus-check.md
deleted file mode 100644
index 328d5498b9..0000000000
--- a/.changeset/fair-emus-check.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog': patch
----
-
-Replaced use of deprecated `compareEntityToRef` utility.
diff --git a/.changeset/fair-eyes-collect.md b/.changeset/fair-eyes-collect.md
deleted file mode 100644
index 5a0cfafaab..0000000000
--- a/.changeset/fair-eyes-collect.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/catalog-model': patch
----
-
-Deprecated `compareEntityToRef` due to low usage and provided value.
diff --git a/.changeset/fast-ducks-sell.md b/.changeset/fast-ducks-sell.md
deleted file mode 100644
index 2ad654124d..0000000000
--- a/.changeset/fast-ducks-sell.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-Support "dependencyOf" relation in Resource entities
diff --git a/.changeset/fast-lizards-fly.md b/.changeset/fast-lizards-fly.md
deleted file mode 100644
index e6772b056f..0000000000
--- a/.changeset/fast-lizards-fly.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend': patch
----
-
-Bump `passport-oauth2` to version 1.6.1
diff --git a/.changeset/fast-mangos-tell.md b/.changeset/fast-mangos-tell.md
deleted file mode 100644
index bfcf429485..0000000000
--- a/.changeset/fast-mangos-tell.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend': minor
----
-
-**BREAKING**: Updated `TemplateAction` and related types to have its type parameter extend `JsonObject` instead of `InputBase`. The `createTemplateAction` has also been updated to pass through the `TInput` type parameter to the return type, meaning the `TemplateAction` retains its type. This can lead to breakages during type checking especially within tests.
diff --git a/.changeset/fast-paws-arrive.md b/.changeset/fast-paws-arrive.md
new file mode 100644
index 0000000000..9c5f4f444f
--- /dev/null
+++ b/.changeset/fast-paws-arrive.md
@@ -0,0 +1,31 @@
+---
+'@backstage/create-app': patch
+---
+
+Update the template to reflect the renaming of `DocsResultListItem` to `TechDocsSearchResultListItem` from `@backstage/plugin-techdocs`.
+
+To apply this change to an existing app, make the following change to `packages/app/src/components/search/SearchPage.tsx`:
+
+```diff
+-import { DocsResultListItem } from '@backstage/plugin-techdocs';
++import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
+```
+
+```diff
+ case 'techdocs':
+ return (
+-
+```
+
+The `TechDocsIndexPage` now uses `DefaultTechDocsHome` as fall back if no children is provided as `LegacyTechDocsHome` is marked as deprecated. If you do not use a custom techdocs homepage, you can therefore update your app to the following:
+
+```diff
+- }>
+-
+-
++ } />
+```
diff --git a/.changeset/fast-stingrays-hope.md b/.changeset/fast-stingrays-hope.md
deleted file mode 100644
index 688f14c548..0000000000
--- a/.changeset/fast-stingrays-hope.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-'@backstage/plugin-catalog': patch
-'@backstage/plugin-catalog-backend': patch
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-catalog-backend-module-ldap': patch
----
-
-Import `Location` from the `@backstage/catalog-client` package.
diff --git a/.changeset/flat-crabs-smash.md b/.changeset/flat-crabs-smash.md
deleted file mode 100644
index b56b340605..0000000000
--- a/.changeset/flat-crabs-smash.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-The `versions:bump` command now filters out `npm_` environment configuration when running `yarn install`. This has the effect of allowing it to consider local configuration files within the repository, which is the behavior that one would expect.
diff --git a/.changeset/funny-crabs-drop.md b/.changeset/funny-crabs-drop.md
deleted file mode 100644
index 764f7c042a..0000000000
--- a/.changeset/funny-crabs-drop.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog': minor
----
-
-Removed `CatalogClientWrapper` as usage have been replaced by the `fetchApiRef`.
diff --git a/.changeset/green-bobcats-burn.md b/.changeset/green-bobcats-burn.md
deleted file mode 100644
index c28f4da678..0000000000
--- a/.changeset/green-bobcats-burn.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-'@backstage/plugin-permission-backend': minor
----
-
-Add a warning if the permission backend is used without setting `permission.enabled=true`.
-
-**BREAKING** Permission backend's `createRouter` now requires a `config` option.
-
-```diff
-// packages/backend/src/plugins/permission.ts
-
-...
-export default async function createPlugin({
- ...
-+ config,
-}: PluginEnvironment) {
- return createRouter({
- ...
-+ config,
- });
-}
-```
diff --git a/.changeset/happy-lemons-drop.md b/.changeset/happy-lemons-drop.md
deleted file mode 100644
index e4c6f52409..0000000000
--- a/.changeset/happy-lemons-drop.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-permission-common': minor
----
-
-**BREAKING** `PermissionCriteria` now requires at least one condition in `anyOf` and `allOf` arrays. This addresses some ambiguous behavior outlined in #9280.
diff --git a/.changeset/hip-carrots-suffer.md b/.changeset/hip-carrots-suffer.md
deleted file mode 100644
index 3823cf982f..0000000000
--- a/.changeset/hip-carrots-suffer.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-techdocs-backend': patch
----
-
-Fix bug where tech docs collator stores search indices with wrong entity ref casing. Make the collator to conform legacyPathCasing configuration option.
diff --git a/.changeset/honest-shrimps-clap.md b/.changeset/honest-shrimps-clap.md
deleted file mode 100644
index 12ae623704..0000000000
--- a/.changeset/honest-shrimps-clap.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-'@backstage/catalog-client': minor
----
-
-**BREAKING**: Removed the explicit `DiscoveryApi` and `FetchApi` export symbols,
-which were unnecessary duplicates from the well known core ones.
-
-The `CATALOG_FILTER_EXISTS` symbol's value has changed. However, this should not
-affect any code in practice.
diff --git a/.changeset/hungry-apples-sparkle.md b/.changeset/hungry-apples-sparkle.md
deleted file mode 100644
index 6cfad2d2da..0000000000
--- a/.changeset/hungry-apples-sparkle.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/catalog-model': patch
----
-
-Deprecated the `EntityRefContext` type which had limited use.
diff --git a/.changeset/khaki-socks-wash.md b/.changeset/khaki-socks-wash.md
new file mode 100644
index 0000000000..241ac75be3
--- /dev/null
+++ b/.changeset/khaki-socks-wash.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+Set timeout for scaffolder octokit client
diff --git a/.changeset/lazy-jeans-obey.md b/.changeset/lazy-jeans-obey.md
deleted file mode 100644
index 9124b983dc..0000000000
--- a/.changeset/lazy-jeans-obey.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-Update internal `Location` validation.
diff --git a/.changeset/little-carpets-itch.md b/.changeset/little-carpets-itch.md
new file mode 100644
index 0000000000..6a4d95c140
--- /dev/null
+++ b/.changeset/little-carpets-itch.md
@@ -0,0 +1,14 @@
+---
+'@backstage/plugin-scaffolder': patch
+---
+
+Added some deprecations as follows:
+
+- **DEPRECATED**: `TemplateCardComponent` and `TaskPageComponent` props have been deprecated, and moved to a `components` prop instead. You can pass them in through there instead.
+- **DEPRECATED**: `TemplateList` and `TemplateListProps` has been deprecated. Please use the `TemplateCard` to create your own list component instead.
+- **DEPRECATED**: `setSecret` has been deprecated in favour of `setSecrets` when calling `useTemplateSecrets`
+
+Other notable changes:
+
+- `scaffolderApi.scaffold()` `values` type has been narrowed from `Record` to `Record` instead.
+- Moved all navigation internally over to using `routeRefs` and `subRouteRefs`
diff --git a/.changeset/little-ravens-kick.md b/.changeset/little-ravens-kick.md
deleted file mode 100644
index 1e14f2f37e..0000000000
--- a/.changeset/little-ravens-kick.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-The `versions:bump` command now also considers the root `package.json` when searching for updates. It has also received updates to its output, including a link the [Backstage upgrade helper](https://backstage.github.io/upgrade-helper) and silenced `yarn install` output.
diff --git a/.changeset/lovely-goats-press.md b/.changeset/lovely-goats-press.md
new file mode 100644
index 0000000000..fc3c0b4763
--- /dev/null
+++ b/.changeset/lovely-goats-press.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': patch
+---
+
+Collapse techdocs sidebar on small devices
diff --git a/.changeset/mighty-beds-fix.md b/.changeset/mighty-beds-fix.md
deleted file mode 100644
index 3e5ab735dd..0000000000
--- a/.changeset/mighty-beds-fix.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-'@backstage/catalog-client': patch
-'@backstage/techdocs-common': patch
-'@backstage/plugin-catalog-backend': patch
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-github-deployments': patch
-'@backstage/plugin-scaffolder-backend': patch
-'@backstage/plugin-todo-backend': patch
----
-
-Updated to use new names for `parseLocationRef` and `stringifyLocationRef`
diff --git a/.changeset/moody-knives-jump.md b/.changeset/moody-knives-jump.md
deleted file mode 100644
index 84e80d9f84..0000000000
--- a/.changeset/moody-knives-jump.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-cicd-statistics': patch
----
-
-Updated `@backstage/core-plugin-api` dependency.
diff --git a/.changeset/olive-flies-reflect.md b/.changeset/olive-flies-reflect.md
deleted file mode 100644
index 80075d8fb0..0000000000
--- a/.changeset/olive-flies-reflect.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/catalog-model': minor
----
-
-**BREAKING**: Remove deprecated validation methods `analyzeLocationSchema`, `locationSchema` and `locationSpecSchema`.
-This functionality was primarily used internally by the `catalog-backend`.
diff --git a/.changeset/patched.json b/.changeset/patched.json
index 1029c8f106..486cfe13a5 100644
--- a/.changeset/patched.json
+++ b/.changeset/patched.json
@@ -1,3 +1,5 @@
{
- "currentReleaseVersion": {}
+ "currentReleaseVersion": {
+ "@backstage/plugin-scaffolder-backend": "0.17.2"
+ }
}
diff --git a/.changeset/perfect-papayas-crash.md b/.changeset/perfect-papayas-crash.md
deleted file mode 100644
index 99c93d1b8d..0000000000
--- a/.changeset/perfect-papayas-crash.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-permission-node': minor
----
-
-**BREAKING** `PermissionCriteria` now requires at least one condition in `anyOf` and `allOf` arrays. This addresses some ambiguous behavior outlined in #9280.
diff --git a/.changeset/pink-onions-ring.md b/.changeset/pink-onions-ring.md
deleted file mode 100644
index 2b81ad4b43..0000000000
--- a/.changeset/pink-onions-ring.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog': minor
----
-
-**BREAKING** Completely removed the `EntitySystemDiagramCard` component which was deprecated in a previous release. Any remaining references to this component are now broken and should be replaced with `EntityCatalogGraphCard`, which can be imported from package `@backstage/plugin-catalog-graph`.
diff --git a/.changeset/plenty-boxes-wink.md b/.changeset/plenty-boxes-wink.md
deleted file mode 100644
index 0011641938..0000000000
--- a/.changeset/plenty-boxes-wink.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/catalog-model': minor
----
-
-**BREAKING**: Remove deprecated `serializeEntityRef` which is replaced by `stringifyEntityRef`.
diff --git a/.changeset/polite-dots-train.md b/.changeset/polite-dots-train.md
deleted file mode 100644
index dbd11d3e60..0000000000
--- a/.changeset/polite-dots-train.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend-module-yeoman': patch
----
-
-Bump `yeoman-environment` dependency from `^3.6.0` to `^3.9.1`.
diff --git a/.changeset/proud-fishes-carry.md b/.changeset/proud-fishes-carry.md
deleted file mode 100644
index 3dd8a445e6..0000000000
--- a/.changeset/proud-fishes-carry.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-catalog': minor
----
-
-Removed deprecated `Router` and `EntityPageLayout` exports.
-`Router` is replaced by plugin extensions and `EntityPageLayout` is replaced by `CatalogEntityPage`.
diff --git a/.changeset/purple-files-hang.md b/.changeset/purple-files-hang.md
deleted file mode 100644
index 680de46a80..0000000000
--- a/.changeset/purple-files-hang.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/catalog-client': patch
----
-
-Export the `Location` type that was previously exported by the `@backstage/catalog-model` package.
diff --git a/.changeset/seven-rocks-share.md b/.changeset/seven-rocks-share.md
deleted file mode 100644
index db131a85dc..0000000000
--- a/.changeset/seven-rocks-share.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/integration-react': patch
----
-
-Updated the `ScmAuth` error message for missing provider configurations to link to `ScmAuthApi` setup documentation.
diff --git a/.changeset/shaggy-readers-explain.md b/.changeset/shaggy-readers-explain.md
new file mode 100644
index 0000000000..29266e5a32
--- /dev/null
+++ b/.changeset/shaggy-readers-explain.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+Cleanup API report
diff --git a/.changeset/shy-peaches-begin.md b/.changeset/shy-peaches-begin.md
deleted file mode 100644
index 4787fe8dea..0000000000
--- a/.changeset/shy-peaches-begin.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
----
-
-Fix CatalogPage showing all components when owned filter was pre-selected
diff --git a/.changeset/silly-ghosts-dance.md b/.changeset/silly-ghosts-dance.md
deleted file mode 100644
index e83fc87521..0000000000
--- a/.changeset/silly-ghosts-dance.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-techdocs': patch
----
-
-Improve overall appearance of highlighted code in docs.
diff --git a/.changeset/smart-items-fry.md b/.changeset/smart-items-fry.md
new file mode 100644
index 0000000000..625db82ce7
--- /dev/null
+++ b/.changeset/smart-items-fry.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+Applied fix from `v0.17.1` of this package which is part of the `v0.69.1` release of Backstage.
diff --git a/.changeset/sour-hats-love.md b/.changeset/sour-hats-love.md
deleted file mode 100644
index f2cc88e66a..0000000000
--- a/.changeset/sour-hats-love.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-common': patch
----
-
-Updated `isDatabaseConflictError` to handle modern sqlite conflict errors
diff --git a/.changeset/spicy-items-itch.md b/.changeset/spicy-items-itch.md
deleted file mode 100644
index e6617a42a3..0000000000
--- a/.changeset/spicy-items-itch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-jenkins-backend': patch
----
-
-The `DefaultJenkinsInfoProvider.fromConfig` now requires an implementation of the `CatalogApi` rather than a `CatalogClient` instance.
diff --git a/.changeset/spicy-lies-grin.md b/.changeset/spicy-lies-grin.md
new file mode 100644
index 0000000000..b7e020f1db
--- /dev/null
+++ b/.changeset/spicy-lies-grin.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend-module-ldap': patch
+---
+
+Fixed bug in Catalog LDAP module to acknowledge page events to continue receiving entries if pagePause=true
diff --git a/.changeset/stupid-cows-design.md b/.changeset/stupid-cows-design.md
deleted file mode 100644
index 2df99664fb..0000000000
--- a/.changeset/stupid-cows-design.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/catalog-model': patch
----
-
-Deprecates the following exports which all have very limited and internal use. `ENTITY_META_GENERATED_FIELDS`, `entityHasChanges`, `generateEntityEtag`, `generateEntityUid`, `generateUpdatedEntity`, `ENTITY_META_GENERATED_FIELDS`.
diff --git a/.changeset/sweet-keys-dress.md b/.changeset/sweet-keys-dress.md
deleted file mode 100644
index 4217f2fcf4..0000000000
--- a/.changeset/sweet-keys-dress.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Updated the default [sucrase](https://github.com/alangpierce/sucrase)-based Jest transform to include source maps if the environment variable `ENABLE_SOURCE_MAPS` is non-empty. This can be used to better support editor test debugging integrations.
diff --git a/.changeset/swift-rules-hunt.md b/.changeset/swift-rules-hunt.md
new file mode 100644
index 0000000000..15707bbf90
--- /dev/null
+++ b/.changeset/swift-rules-hunt.md
@@ -0,0 +1,5 @@
+---
+'@backstage/techdocs-common': patch
+---
+
+adds passing projectID to the Storage client
diff --git a/.changeset/tasty-eagles-retire.md b/.changeset/tasty-eagles-retire.md
deleted file mode 100644
index c39f30d57f..0000000000
--- a/.changeset/tasty-eagles-retire.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-'@backstage/catalog-client': patch
----
-
-Deprecated the following types used by the catalog client, and created new
-corresponding types to make them more consistent:
-
-- `CatalogEntitiesRequest` -> `GetEntitiesRequest`
-- `CatalogListResponse` was removed and generally replaced with `GetEntitiesResponse` (which does not use a type parameter argument)
-- `CatalogEntityAncestorsRequest`-> `GetEntityAncestorsRequest`
-- `CatalogEntityAncestorsResponse` -> `GetEntityAncestorsResponse`
diff --git a/.changeset/tasty-taxis-dance.md b/.changeset/tasty-taxis-dance.md
deleted file mode 100644
index 34ed30f686..0000000000
--- a/.changeset/tasty-taxis-dance.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-'@backstage/catalog-client': patch
-'@backstage/plugin-catalog': patch
-'@backstage/plugin-catalog-backend': patch
-'@backstage/plugin-catalog-backend-module-ldap': patch
-'@backstage/plugin-catalog-backend-module-msgraph': patch
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-github-deployments': patch
-'@backstage/plugin-scaffolder-backend': patch
-'@backstage/plugin-todo': patch
-'@backstage/plugin-todo-backend': patch
----
-
-Replaces use of deprecated catalog-model constants.
diff --git a/.changeset/techdocs-cats-whisper.md b/.changeset/techdocs-cats-whisper.md
new file mode 100644
index 0000000000..290f8a1d7a
--- /dev/null
+++ b/.changeset/techdocs-cats-whisper.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': patch
+---
+
+Remove copyright from old footer in documentation generated with previous version of `mkdocs-techdocs-plugin` (`v0.2.2`).
diff --git a/.changeset/techdocs-toes-lie.md b/.changeset/techdocs-toes-lie.md
new file mode 100644
index 0000000000..14ca2567e2
--- /dev/null
+++ b/.changeset/techdocs-toes-lie.md
@@ -0,0 +1,5 @@
+---
+'@techdocs/cli': patch
+---
+
+Bump `@backstage/techdocs-common` to `0.11.10` to use `spotify/techdocs:v0.3.7` which upgrades `mkdocs-theme` as a dependency of `mkdocs-techdocs-core`.
diff --git a/.changeset/techdocs-war-on-war.md b/.changeset/techdocs-war-on-war.md
new file mode 100644
index 0000000000..28722feed3
--- /dev/null
+++ b/.changeset/techdocs-war-on-war.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': patch
+---
+
+Fixed a bug that could cause searches in the in-context TechDocs search bar to show results from a different TechDocs site.
diff --git a/.changeset/three-roses-swim.md b/.changeset/three-roses-swim.md
deleted file mode 100644
index ae6ad44845..0000000000
--- a/.changeset/three-roses-swim.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-'@backstage/techdocs-common': patch
-'@backstage/plugin-auth-backend': patch
-'@backstage/plugin-badges': patch
-'@backstage/plugin-badges-backend': patch
-'@backstage/plugin-catalog': patch
-'@backstage/plugin-catalog-backend': patch
-'@backstage/plugin-catalog-graph': patch
-'@backstage/plugin-catalog-react': patch
-'@backstage/plugin-cost-insights': patch
-'@backstage/plugin-ilert': patch
-'@backstage/plugin-org': patch
-'@backstage/plugin-pagerduty': patch
-'@backstage/plugin-search': patch
-'@backstage/plugin-techdocs-backend': patch
----
-
-Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`.
diff --git a/.changeset/tidy-boxes-sell.md b/.changeset/tidy-boxes-sell.md
deleted file mode 100644
index 82ee16af57..0000000000
--- a/.changeset/tidy-boxes-sell.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-'@backstage/plugin-search': minor
----
-
-**BREAKING**: `useSearch` doesn't return anymore `open` and `toggleModal`.
-The two properties have been moved to the `useSearchModal` hook.
-
-```
-import { SearchModal, useSearchModal } from '@backstage/plugin-search';
-
-const Foo = () => {
- const { state, setOpen, toggleModal } = useSearchModal();
-
- return (
-
- );
-};
-```
diff --git a/.changeset/tiny-lobsters-exercise.md b/.changeset/tiny-lobsters-exercise.md
new file mode 100644
index 0000000000..78cc753bab
--- /dev/null
+++ b/.changeset/tiny-lobsters-exercise.md
@@ -0,0 +1,29 @@
+---
+'@backstage/plugin-techdocs': minor
+---
+
+**BREAKING:**
+Table column utilities `createNameColumn`, `createOwnerColumn`, `createTypeColumn` as well as actions utilities `createCopyDocsUrlAction` and `createStarEntityAction` are no longer directly exported. Instead accessible through DocsTable and EntityListDocsTable.
+
+Use as following:
+
+```tsx
+DocsTable.columns.createNameColumn();
+DocsTable.columns.createOwnerColumn();
+DocsTable.columns.createTypeColumn();
+
+DocsTable.actions.createCopyDocsUrlAction();
+DocsTable.actions.createStarEntityAction();
+```
+
+- Renamed `DocsResultListItem` to `TechDocsSearchResultListItem`, leaving the old name in place as a deprecations.
+
+- Renamed `TechDocsPage` to `TechDocsReaderPage`, leaving the old name in place as a deprecations.
+
+- Renamed `TechDocsPageRenderFunction` to `TechDocsPageRenderFunction`, leaving the old name in place as a deprecations.
+
+- Renamed `TechDocsPageHeader` to `TechDocsReaderPageHeader`, leaving the old name in place as a deprecations.
+
+- `LegacyTechDocsHome` marked as deprecated and will be deleted in next release, use `TechDocsCustomHome` instead.
+
+- `LegacyTechDocsPage` marked as deprecated and will be deleted in next release, use `TechDocsReaderPage` instead.
diff --git a/.changeset/tough-clocks-enjoy.md b/.changeset/tough-clocks-enjoy.md
new file mode 100644
index 0000000000..90e00382df
--- /dev/null
+++ b/.changeset/tough-clocks-enjoy.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Tweaked the wording of the "does not have a location" errors to include the actual missing annotation name, to help users better in fixing their inputs.
diff --git a/.changeset/tough-pets-beg.md b/.changeset/tough-pets-beg.md
new file mode 100644
index 0000000000..7fdcc6dc01
--- /dev/null
+++ b/.changeset/tough-pets-beg.md
@@ -0,0 +1,5 @@
+---
+'@backstage/integration': patch
+---
+
+Fix Bitbucket Cloud and Bitbucket Server line number reference.
diff --git a/.changeset/tough-stingrays-sit.md b/.changeset/tough-stingrays-sit.md
deleted file mode 100644
index 5cef08c8e3..0000000000
--- a/.changeset/tough-stingrays-sit.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-Optimized entity provider mutations with large numbers of new additions, such as big initial startup commits
diff --git a/.changeset/twenty-dodos-rule.md b/.changeset/twenty-dodos-rule.md
deleted file mode 100644
index 5167811a3d..0000000000
--- a/.changeset/twenty-dodos-rule.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/catalog-model': patch
----
-
-Deprecates `EDIT_URL_ANNOTATION`, `LOCATION_ANNOTATION`, `ORIGIN_LOCATION_ANNOTATION`, `SOURCE_LOCATION_ANNOTATION`, `VIEW_URL_ANNOTATION`
-and replaces these constants all prefixed with ANNOTATION\_ `ANNOTATION_EDIT_URL`, `ANNOTATION_LOCATION`, `ANNOTATION_ORIGIN_LOCATION`, `ANNOTATION_SOURCE_LOCATION`, `ANNOTATION_VIEW_URL`
diff --git a/.changeset/unlucky-queens-brush.md b/.changeset/unlucky-queens-brush.md
new file mode 100644
index 0000000000..c080856246
--- /dev/null
+++ b/.changeset/unlucky-queens-brush.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Added ability for SidebarSubmenuItem to handle external links correctly via the "to" prop
diff --git a/.changeset/wise-foxes-confess.md b/.changeset/wise-foxes-confess.md
new file mode 100644
index 0000000000..8322b66555
--- /dev/null
+++ b/.changeset/wise-foxes-confess.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+Fix the support for custom defaultBranch values for Bitbucket Cloud at the `publish:bitbucket` scaffolder action.
diff --git a/.changeset/witty-mails-search.md b/.changeset/witty-mails-search.md
deleted file mode 100644
index a98fc52884..0000000000
--- a/.changeset/witty-mails-search.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend-module-cookiecutter': minor
-'@backstage/plugin-scaffolder-backend-module-rails': minor
-'@backstage/plugin-scaffolder-backend-module-yeoman': minor
----
-
-Updated to the latest version of `@backstage/plugin-scaffolder-backend`, meaning the `TemplateAction` now exposes the precise input type rather than `any`.
diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt
index 8303510e77..6359493d4b 100644
--- a/.github/styles/vocab.txt
+++ b/.github/styles/vocab.txt
@@ -3,6 +3,8 @@ accessors
addon
addons
Airbrake
+Airbrakes
+airbrake
Anddddd
Apdex
api
@@ -17,6 +19,7 @@ autoscaling
Autoscaling
autoselect
Avro
+aws
backrub
backported
backporting
@@ -275,6 +278,8 @@ sqlite
squidfunk
src
stdout
+stringify
+stringified
subcomponent
subcomponents
subkey
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 82bf46a17a..49c97bb197 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,5 +1,4 @@
name: CI
-
on:
pull_request:
paths-ignore:
diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml
index 8b92c000ed..7931f7ade5 100644
--- a/.github/workflows/deploy_microsite.yml
+++ b/.github/workflows/deploy_microsite.yml
@@ -1,5 +1,4 @@
name: Deploy Microsite
-
on:
push:
branches:
diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml
index 3fbc2fafe5..4997668563 100644
--- a/.github/workflows/deploy_nightly.yml
+++ b/.github/workflows/deploy_nightly.yml
@@ -1,5 +1,4 @@
name: Deploy Nightly Release
-
on:
schedule:
- cron: '0 2 * * *' # run at 2 AM UTC
diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml
index ed02a313fe..9b7a233767 100644
--- a/.github/workflows/deploy_packages.yml
+++ b/.github/workflows/deploy_packages.yml
@@ -1,5 +1,4 @@
name: Deploy Packages
-
on:
workflow_dispatch:
push:
@@ -189,7 +188,7 @@ jobs:
run: yarn tsc:full
- name: build packages
- run: yarn lerna -- run --ignore example-app build
+ run: yarn lerna -- run --ignore example-app --ignore example-backend build
# Publishes current version of packages that are not already present in the registry
- name: publish
diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml
index 7e0458cb21..75c154792c 100644
--- a/.github/workflows/sync_code-formatting.yml
+++ b/.github/workflows/sync_code-formatting.yml
@@ -1,5 +1,4 @@
name: Sync code formatting
-
on:
push:
branches:
diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml
index ed97cf05f1..58e0a1ac0f 100644
--- a/.github/workflows/sync_dependabot-changesets.yml
+++ b/.github/workflows/sync_dependabot-changesets.yml
@@ -2,7 +2,7 @@ name: Sync Dependabot changeset
on:
pull_request_target:
paths:
- - .github/workflows/dependabot-changeset-maker.yml
+ - '.github/workflows/sync_dependabot-changesets.yml'
- '**/yarn.lock'
jobs:
diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml
index 4b44caafba..f4d9afc0df 100644
--- a/.github/workflows/sync_release-manifest.yml
+++ b/.github/workflows/sync_release-manifest.yml
@@ -5,6 +5,7 @@ on:
version:
description: Version number, without any 'v' prefix
required: true
+
jobs:
create-new-version:
runs-on: ubuntu-latest
diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml
index 93b6c696d0..0bf0340f68 100644
--- a/.github/workflows/sync_snyk-github-issues.yml
+++ b/.github/workflows/sync_snyk-github-issues.yml
@@ -1,5 +1,4 @@
name: Sync Snyk GitHub issues
-
on:
schedule:
- cron: '0 */4 * * *'
diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml
index f9e6679173..bf50748dc0 100644
--- a/.github/workflows/sync_snyk-monitor.yml
+++ b/.github/workflows/sync_snyk-monitor.yml
@@ -1,11 +1,10 @@
name: Sync Snyk Monitoring
-
on:
workflow_dispatch:
push:
branches: [master]
paths:
- - '.github/workflows/snyk-monitor.yml'
+ - '.github/workflows/sync_snyk-monitor.yml'
- '**/.snyk'
- '**/package.json'
- 'yarn.lock'
diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml
index e028387190..58d715c5a8 100644
--- a/.github/workflows/sync_version-packages.yml
+++ b/.github/workflows/sync_version-packages.yml
@@ -1,5 +1,4 @@
name: Sync Version Packages PR
-
on:
push:
branches:
diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml
index 57298d69dd..55c1c23587 100644
--- a/.github/workflows/verify_docs-quality.yml
+++ b/.github/workflows/verify_docs-quality.yml
@@ -1,9 +1,9 @@
name: Verify Docs Quality
-
on:
pull_request:
branches: [master]
paths:
+ - '.github/workflows/verify_docs-quality.yml'
- '**.md'
jobs:
diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml
index 6694ace02b..3e39aee1ae 100644
--- a/.github/workflows/verify_e2e-linux.yml
+++ b/.github/workflows/verify_e2e-linux.yml
@@ -1,5 +1,4 @@
name: E2E Test Linux
-
on:
pull_request:
paths-ignore:
diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml
index 3806eade25..7caf880366 100644
--- a/.github/workflows/verify_e2e-techdocs.yml
+++ b/.github/workflows/verify_e2e-techdocs.yml
@@ -1,5 +1,4 @@
name: E2E Test Techdocs
-
on:
pull_request:
paths-ignore:
diff --git a/.github/workflows/verify_e2e-tugboat.yml b/.github/workflows/verify_e2e-tugboat.yml
index a9c810ff68..1054ccf579 100644
--- a/.github/workflows/verify_e2e-tugboat.yml
+++ b/.github/workflows/verify_e2e-tugboat.yml
@@ -1,5 +1,6 @@
name: E2E Test Tugboat
on: deployment_status
+
jobs:
set-pending:
if: github.event.deployment_status.state != 'success' && github.event.deployment_status.state != 'failed'
diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml
index b4347898e6..0977831d19 100644
--- a/.github/workflows/verify_e2e-windows.yml
+++ b/.github/workflows/verify_e2e-windows.yml
@@ -1,11 +1,11 @@
-name: E2E Test Windows
-
# Building on windows is really slow, so this workflow is separate from e2e.yml and only builds on changes
# to the cli itself. They're more likely to introduce issues on windows, compared to changes to core and yarn.lock.
+
+name: E2E Test Windows
on:
pull_request:
paths:
- - '.github/workflows/e2e-win.yml'
+ - '.github/workflows/verify_e2e-windows.yml'
- 'packages/cli/**'
- 'packages/e2e-test/**'
- 'packages/create-app/**'
@@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
- os: [windows-latest]
+ os: [windows-2019]
node-version: [14.x, 16.x]
env:
diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml
index ac05f72be5..24a6ff5351 100644
--- a/.github/workflows/verify_microsite.yml
+++ b/.github/workflows/verify_microsite.yml
@@ -1,9 +1,8 @@
name: Verify Microsite
-
on:
pull_request:
paths:
- - '.github/workflows/microsite-build-check.yml'
+ - '.github/workflows/verify_microsite.yml'
- 'microsite/**'
- 'docs/**'
diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml
index 2142f52445..60f58f4c66 100644
--- a/.github/workflows/verify_storybook.yml
+++ b/.github/workflows/verify_storybook.yml
@@ -2,7 +2,7 @@ name: Verify Storybook
on:
pull_request:
paths:
- - '.github/workflows/chromatic-storybook-test.yml'
+ - '.github/workflows/verify_storybook.yml'
- 'storybook/**'
- 'packages/config/src/**'
- 'packages/theme/src/**'
diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml
index 55959510d3..9ae4397bba 100644
--- a/.github/workflows/verify_windows.yml
+++ b/.github/workflows/verify_windows.yml
@@ -1,13 +1,15 @@
name: Verify Master Branch on Windows
-
on:
workflow_dispatch:
push:
branches: [master]
+ pull_request:
+ paths:
+ - '.github/workflows/verify_windows.yml'
jobs:
build:
- runs-on: windows-latest
+ runs-on: windows-2019
strategy:
matrix:
diff --git a/ADOPTERS.md b/ADOPTERS.md
index 1682e13316..eb83726b8d 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -1,3 +1,7 @@
+# Adopters
+
+_If you're using Backstage in your organization, please try to add your company name to this list. This really helps the project to gain momentum and credibility. It's a small contribution back to the project with a big impact._
+
| Organization | Contact | Description of Use |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. |
@@ -74,7 +78,7 @@
| [GoTo](https://www.goto.com) | [Lorenzo Orsatti](https://github.com/lorsatti) | Improve onboarding experience of new developers. Discover faster and painlessly developer documentation, API definitions and team information. Provide useful dev metrics in a central place. Provide easy-to-use templates for new services. |
| [Telstra](https://www.telstra.com.au) | [@kiranpatel11](https://github.com/kiranpatel11), [JasonC](https://github.com/JasonC17) | Primary usage: software catalog and templates Emerging usage : TechDocs, Explore Ecosystem, TechRadar, etc |
| [Mosaico](https://www.mosaico.com.br/) | [Wédney Yuri](https://github.com/wedneyyuri),[@tino.milton](https://github.com/miltonjacomini) | A centralized service catalog of our documentation for our service engineers. |
-| [Mox Bank](https://www.mox.com/) | [Nick Laqua](https://github.com/nick-laqua-dragon) | "Single pane of glass" developer portal for providing a best-in-class developer experience to our product teams and making Mox the best tech environment in Hongkong 🥰🚀 |
+| [Mox Bank](https://www.mox.com/) | [Nick Laqua](https://github.com/nick-laqua-dragon) | "Single pane of glass" developer portal for providing a best-in-class developer experience to our product teams and making Mox the best tech environment in Hongkong 🥰🚀 |
| [Keyloop](https://www.keyloop.com/) | [Andre Wanlin](https://github.com/awanlin) | Future-motive Developer Portal to help our teams create technology to make everything about buying and owning a car better. 🚗 |
| [Simply Business](https://sbtech.simplybusiness.co.uk/) | [@addersuk](https://github.com/addersuk), [@LightningStairs](https://github.com/LightningStairs), [@punitcse](https://github.com/punitcse), [@moltenice](https://github.com/moltenice) | Central developer portal to access everything a developer needs such as docs, internal service catalog, and the ability to quickly create a new service from a template. Internally developed Backstage plugins allow us to customise the experience to how we work. |
| [Overwolf](https://www.overwolf.com) | [@tomwolfgang](https://github.com/tomwolfgang) | Dev portal - software catalog, tech-docs, scaffolding |
@@ -93,3 +97,6 @@
| [Invitae](https://www.invitae.com/en) | [@ryan-hanchett](https://github.com/ryan-hanchett), [@gmandler42](https://github.com/gmandler42) | Centralized Developer Experience portal, putting all of our tooling behind a single pane of glass and creating a living service catalog. |
| [Fortum](https://www.fortum.com/) | [@brunoamaroalmeida](https://github.com/brunoamaroalmeida), [@dhaval-vithalani](https://github.com/dhaval-vithalani), [@sunilkumarmohanty](https://github.com/sunilkumarmohanty) | A central portal containing information about our applications, services, processes and other software assets to be used by Fortum software engineering community. |
| [Procore](https://www.procore.com/jobs/engineering) | [@shayon](https://github.com/Shayon), [@jamesdabbs-procore](https://github.com/jamesdabbs-procore) | Developer portal - centralized software catalog and templates to enable self serve and reduce cognitive load. |
+| [Bradesco](https://banco.bradesco/html/classic/sobre/index.shtm) | [@danilosoarescardoso](https://github.com/danilosoarescardoso) | Centralized developer portal with software catalog, software templates, techdocs and some plugins from community and by our own. |
+| [SeatGeek](https://seatgeek.com) | [@zhammer](https://github.com/zhammer) | Software catalog and documentation platform |
+| [Grupo Boticário](https://www.grupoboticario.com.br/) | [@chicoribas](https://github.com/chicoribas), [@fndiaz](https://github.com/fndiaz), [@digogid](https://github.com/digogid), [@manumbs](https://github.com/manumbs), [@haooliveira84](https://github.com/haooliveira84), [@Rhullyam](https://github.com/Rhullyam) | Centralized developer portal with catalog, documentation, and software templates to build a ready to go application, including pipelines (CI/CD) and cloud services provisioning |
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f054de05ce..e853a68ad3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,7 +2,7 @@
Our vision for Backstage is for it to become the trusted standard toolbox (read: UX layer) for the open source infrastructure landscape. Think of it like Kubernetes for developer experience. We realize this is an ambitious goal. We can’t do it alone.
-Therefore we want to create strong community of contributors -- all working together to create the kind of delightful experience that our developers deserve.
+Therefore we want to create a strong community of contributors -- all working together to create the kind of delightful experience that our developers deserve.
Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. ❤️
@@ -100,7 +100,7 @@ Signed-off-by: Jane Smith
- In case you forgot to add it to the last N commits in your branch, use `git rebase --signoff HEAD~N` and replace N with the number of new commits you created in your branch.
- If you have a very deep branch with a lot of commits, run `git rebase -i --signoff $(git merge-base -a master HEAD)`, double check to make sense of the commits (keep all lines as `pick`) and save and close the editor. This should bulk sign all the commits in your PR. Do be careful though. If you have a complex flow with a lot of branching and re-merging of work branches and stuff, merge-base may not be the right solution for you.
-Note: If you have already pushed you branch to a remote, you might have to force push: `git push -f` after the rebase.
+Note: If you have already pushed your branch to a remote, you might have to force push: `git push -f` after the rebase.
### Using GitHub Desktop?
diff --git a/GOVERNANCE.md b/GOVERNANCE.md
index 3bcef61021..5bafa19c81 100644
--- a/GOVERNANCE.md
+++ b/GOVERNANCE.md
@@ -24,7 +24,7 @@ To become a maintainer you need to demonstrate the following:
- Monitor Discord (delayed response is perfectly acceptable).
- Triage GitHub issues and perform pull request reviews for other maintainers and the community.
- Triage build issues - file issues for known flaky builds or bugs, and either fix or find someone to fix any master build breakages.
-- During GitHub issue triage, apply all applicable ([labels](https://github.com/backstage/backstage/labels)) to each new issue. Labels are extremely useful for future issue follow up. Which labels to apply is somewhat subjective so just use your best judgment. A few of the most important labels that are not self explanatory are:
+- During GitHub issue triage, apply all applicable ([labels](https://github.com/backstage/backstage/labels)) to each new issue. Labels are extremely useful for future issue follow-up. Which labels to apply is somewhat subjective so just use your best judgment. A few of the most important labels that are not self-explanatory are:
- good first issue: Mark any issue that can reasonably be accomplished by a new contributor with this label.
- help wanted: Unless it is immediately obvious that someone is going to work on an issue (and if so assign it), mark it help wanted.
- Make sure that ongoing PRs are moving forward at the right pace or closing them.
diff --git a/STYLE.md b/STYLE.md
index d968d387fc..d74616a88c 100644
--- a/STYLE.md
+++ b/STYLE.md
@@ -131,7 +131,7 @@ We use [API Extractor](https://api-extractor.com/pages/overview/demo_docs/) to g
The doc comments are of the good old `/** ... */` format, with tags of the format `@` used to mark various things. The [TSDoc website](https://tsdoc.org/) has a good index of all available tags.
-There are a few things to pay attention to make the documentation show up in a nice way on the website...
+There are a few things to pay attention to, in order to make the documentation show up in a nice way on the website...
## Declare exported functions using the `function` keyword
@@ -163,7 +163,7 @@ If the parameters of a function are destructed in the parameter list, they will

-Instead prefer to use a single parameter variable and then move the destructuring into the function body instead, which will look much nicer:
+Instead prefer to use a single parameter variable and then move the destructuring into the function body, which will look much nicer:

diff --git a/app-config.yaml b/app-config.yaml
index b025064c74..ab68d4398f 100644
--- a/app-config.yaml
+++ b/app-config.yaml
@@ -211,14 +211,6 @@ catalog:
- Location
processors:
- githubOrg:
- providers:
- - target: https://github.com
- token: ${GITHUB_TOKEN}
- #### Example for how to add your GitHub Enterprise instance using the API:
- # - target: https://ghe.example.net
- # apiBaseUrl: https://ghe.example.net/api
- # token: ${GHE_TOKEN}
ldapOrg:
### Example for how to add your enterprise LDAP server
# providers:
diff --git a/contrib/chart/backstage/templates/ingress.yaml b/contrib/chart/backstage/templates/ingress.yaml
index 3fa052485e..cac9b61553 100644
--- a/contrib/chart/backstage/templates/ingress.yaml
+++ b/contrib/chart/backstage/templates/ingress.yaml
@@ -15,7 +15,6 @@ metadata:
{{- if .Values.issuer.email }}
cert-manager.io/cluster-issuer: {{ .Values.issuer.clusterIssuer }}
{{- end }}
- kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($scheme = https) {
diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md
index 6b1b8cb4e7..a95b276365 100644
--- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md
+++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md
@@ -182,12 +182,12 @@ Use the following `auth` configuration when running Backstage on AWS:
auth:
providers:
awsalb:
- issuer:
- issuer: https://login.microsoftonline.com/{TENANT_ID}/v2.0
- region: { AWS_REGION }
+ development:
+ issuer: https://login.microsoftonline.com//v2.0
+ region:
```
-Replace `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App and `{AWS_REGION}` with the AWS region identifier where the ALB is deployed (for example: `eu-central-1`).
+Replace `` with the value of `Directory (tenant) ID` of the AAD App and `` with the AWS region identifier where the ALB is deployed (for example: `eu-central-1`).
## Conclusion
diff --git a/docs/assets/getting-started/sidebar-with-catalog.png b/docs/assets/getting-started/sidebar-with-catalog.png
new file mode 100644
index 0000000000..d80346c211
Binary files /dev/null and b/docs/assets/getting-started/sidebar-with-catalog.png differ
diff --git a/docs/assets/getting-started/sidebar-without-catalog.png b/docs/assets/getting-started/sidebar-without-catalog.png
new file mode 100644
index 0000000000..bfeab13235
Binary files /dev/null and b/docs/assets/getting-started/sidebar-without-catalog.png differ
diff --git a/docs/assets/getting-started/simple-homepage.png b/docs/assets/getting-started/simple-homepage.png
new file mode 100644
index 0000000000..128707e9ff
Binary files /dev/null and b/docs/assets/getting-started/simple-homepage.png differ
diff --git a/docs/auth/bitbucket/provider.md b/docs/auth/bitbucket/provider.md
index ee87c2d4e6..c54fb75ffa 100644
--- a/docs/auth/bitbucket/provider.md
+++ b/docs/auth/bitbucket/provider.md
@@ -67,7 +67,7 @@ Bitbucket username to `bitbucket.org/username` annotations of `User` entities in
the catalog. Note that you must populate your catalog with matching entities or
users will not be able to sign in.
-The second resolver is the `bitbucketUsernameSignInResolver`, which works the
+The second resolver is the `bitbucketUserIdSignInResolver`, which works the
same way, but uses the Bitbucket user ID instead, and matches on the
`bitbucket.org/user-id` annotation.
diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md
index 6f58abe769..36967f352a 100644
--- a/docs/deployment/docker.md
+++ b/docs/deployment/docker.md
@@ -56,7 +56,7 @@ Once the host build is complete, we are ready to build our image. The following
`Dockerfile` is included when creating a new app with `@backstage/create-app`:
```Dockerfile
-FROM node:14-buster-slim
+FROM node:16-bullseye-slim
WORKDIR /app
# Copy repo skeleton first, to avoid unnecessary docker cache invalidation.
@@ -65,6 +65,12 @@ WORKDIR /app
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.
@@ -134,23 +140,28 @@ the repo root:
```Dockerfile
# Stage 1 - Create yarn install skeleton layer
-FROM node:14-buster-slim AS packages
+FROM node:16-bullseye-slim AS packages
WORKDIR /app
COPY package.json yarn.lock ./
COPY packages packages
+
# Comment this out if you don't have any internal plugins
COPY plugins plugins
RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -exec rm -rf {} \+
# Stage 2 - Install dependencies and build packages
-FROM node:14-buster-slim AS build
+FROM node:16-bullseye-slim AS build
WORKDIR /app
COPY --from=packages /app .
+# install sqlite3 dependencies
+RUN apt-get update && apt-get install -y libsqlite3-dev python3 cmake g++ && \
+ yarn config set python /usr/bin/python3
+
RUN yarn install --frozen-lockfile --network-timeout 600000 && rm -rf "$(yarn cache dir)"
COPY . .
@@ -159,7 +170,7 @@ RUN yarn tsc
RUN yarn --cwd packages/backend backstage-cli backend:bundle --build-dependencies
# Stage 3 - Build the actual backend image and install production dependencies
-FROM node:14-buster-slim
+FROM node:16-bullseye-slim
WORKDIR /app
@@ -167,6 +178,12 @@ WORKDIR /app
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/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md
index 821f39ff6e..80c9458aee 100644
--- a/docs/features/software-catalog/catalog-customization.md
+++ b/docs/features/software-catalog/catalog-customization.md
@@ -93,7 +93,7 @@ export type CustomFilters = DefaultEntityFilters & {
To control this filter, we can create a React component that shows checkboxes
for the security tiers. This component will make use of the
-`useEntityListProvider` hook, which accepts this extended filter type as a
+`useEntityList` hook, which accepts this extended filter type as a
[generic](https://www.typescriptlang.org/docs/handbook/2/generics.html)
parameter:
@@ -103,7 +103,7 @@ export const EntitySecurityTierPicker = () => {
const {
filters: { securityTiers },
updateFilters,
- } = useEntityListProvider();
+ } = useEntityList();
// Toggles the value, depending on whether it's already selected
function onChange(value: string) {
diff --git a/docs/features/software-catalog/external-integrations.md b/docs/features/software-catalog/external-integrations.md
index b14fd732d7..59caf9475c 100644
--- a/docs/features/software-catalog/external-integrations.md
+++ b/docs/features/software-catalog/external-integrations.md
@@ -367,11 +367,11 @@ The class will have this basic structure:
```ts
import { UrlReader } from '@backstage/backend-common';
-import { LocationSpec } from '@backstage/catalog-model';
import {
results,
CatalogProcessor,
CatalogProcessorEmit,
+ LocationSpec,
} from '@backstage/plugin-catalog-backend';
// A processor that reads from the fictional System-X
@@ -448,13 +448,14 @@ behavior for `system-x` that we implemented earlier.
```ts
import { UrlReader } from '@backstage/backend-common';
-import { Entity, LocationSpec } from '@backstage/catalog-model';
+import { Entity } from '@backstage/catalog-model';
import {
results,
CatalogProcessor,
CatalogProcessorEmit,
CatalogProcessorCache,
CatalogProcessorParser,
+ LocationSpec,
} from '@backstage/plugin-catalog-backend';
// It's recommended to always bump the CACHE_KEY version if you make
@@ -472,8 +473,8 @@ type CacheItem = {
export class SystemXReaderProcessor implements CatalogProcessor {
constructor(private readonly reader: UrlReader) {}
- // It's recommended to give the processor a unique name.
getProcessorName() {
+ // The processor name must be unique.
return 'system-x-processor';
}
diff --git a/docs/features/techdocs/cli.md b/docs/features/techdocs/cli.md
index 8122fefdcd..a5dc8c3c54 100644
--- a/docs/features/techdocs/cli.md
+++ b/docs/features/techdocs/cli.md
@@ -123,7 +123,7 @@ Options:
--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.
- github:https://ghe.mycompany.net.com/org/repo.
+ url:https://ghe.mycompany.net.com/org/repo.
This value is same as the backstage.io/techdocs-ref annotation of the corresponding
Backstage entity.
It is completely fine to skip this as it is only being used to set repo_url in mkdocs.yml
diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md
index fc68008ae8..34eca2429a 100644
--- a/docs/getting-started/app-custom-theme.md
+++ b/docs/getting-started/app-custom-theme.md
@@ -257,68 +257,4 @@ const LogoFull = () => {
## Custom Homepage
In addition to a custom theme, a custom logo, you can also customize the
-homepage of your app. To do that we need to go through a few steps.
-
-### Setting up the Home Page
-
-1. Create a Home Page Component that will be used for composition.
-
-`packages/app/src/components/home/HomePage.tsx`
-
-```tsx
-import React from 'react';
-
-export const HomePage = () => {
- return {
- /* TODO: Compose a Home Page here */
- };
-};
-```
-
-2. Add a route where the homepage will live, presumably `/`.
-
-`packages/app/src/App.tsx`
-
-```tsx
-import { HomepageCompositionRoot } from '@backstage/plugin-home';
-import { HomePage } from './components/home/HomePage';
-
-// ...
-}>
-
-;
-// ...
-```
-
-### Composing your Home Page
-
-Composing a Home Page is no different from creating a regular React Component,
-i.e. the App Integrator is free to include whatever content they like. However,
-there are components developed with the Home Page in mind. If you are looking
-for components to use when composing your homepage, you can take a look at the
-[collection of Homepage components](https://backstage.io/?path=/story/plugins-home-components)
-in storybook. If you don't find a component that suits your needs but want to
-contribute, check the
-[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing).
-
-> If you want to use one of the available homepage templates you can find the
-> [templates](https://backstage.io/storybook/?path=/story/plugins-home-templates)
-> in the storybook under the "Home" plugin. And if you would like to contribute
-> a template, please see the
-> [Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing)
-
-```tsx
-import React from 'react';
-import Grid from '@material-ui/core/Grid';
-import { HomePageCompanyLogo } from '@backstage/plugin-home';
-
-export const HomePage = () => {
- return (
-
-
-
-
-
- );
-};
-```
+homepage of your app. Read the full guide on the [next page](homepage.md).
diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md
index 55285e7f4e..082fbf5b70 100644
--- a/docs/getting-started/configuration.md
+++ b/docs/getting-started/configuration.md
@@ -28,7 +28,7 @@ At the end of this tutorial, you can expect:
These instructions can be skipped if you already have a PostgreSQL server
installed and created a schema and user. The example below is for Linux, but
-luckily there's detailed instructions on how to
+luckily there are detailed instructions on how to
[install PostgreSQL](https://www.postgresql.org/download/) to help you get
started.
@@ -113,7 +113,7 @@ new component, or register an existing one it will be saved in the database.
Later in this tutorial you'll add a service, and you can test if it's persistent
as advertised.
-If you want to read more about the database configuration, here's some helpful
+If you want to read more about the database configuration, here are some helpful
links:
- [Configuring Plugin Databases](../tutorials/configuring-plugin-databases.md#privileges)
@@ -122,7 +122,7 @@ links:
### Setting up authentication
-There's multiple authentication providers available for you to use with
+There are multiple authentication providers available for you to use with
Backstage, feel free to follow
[the instructions for adding authentication](../auth/).
@@ -191,7 +191,7 @@ components: {
That should be it. You can stop your Backstage App. When you start it again and
go to your Backstage portal in your browser, you should have your login prompt!
-To learn more about Authentication in Backstage, there's the following docs you
+To learn more about Authentication in Backstage, here are some docs you
could read:
- [Adding Authentication](../auth/)
@@ -208,7 +208,7 @@ and Groups can also be loaded from an organization. While using GitHub Apps
might be the best way to set up integrations, for this tutorial you'll use a
Personal Access Token.
-Create your Personal Access Token by opening the
+Create your Personal Access Token by opening
[the GitHub token creation page](https://github.com/settings/tokens/new). Use a
name to identify this token and put it in the notes field. Choose a number of
days for expiration. If you have a hard time picking a number, we suggest to go
diff --git a/docs/getting-started/create-an-app.md b/docs/getting-started/create-an-app.md
index 1d65f25d1b..05c12ffb75 100644
--- a/docs/getting-started/create-an-app.md
+++ b/docs/getting-started/create-an-app.md
@@ -16,8 +16,7 @@ may want to [Run Backstage Locally](./running-backstage-locally.md) instead.
## Create an app
To create a Backstage app, you will need to have
-[Node.js](https://nodejs.org/en/download/) Active LTS Release installed
-(currently v14).
+Node.js [Active LTS Release](https://nodejs.org/en/about/releases/) installed.
Backstage provides a utility for creating new apps. It guides you through the
initial setup of selecting the name of the app and a database for the backend.
diff --git a/docs/getting-started/homepage.md b/docs/getting-started/homepage.md
new file mode 100644
index 0000000000..59272a285b
--- /dev/null
+++ b/docs/getting-started/homepage.md
@@ -0,0 +1,166 @@
+---
+id: homepage
+title: Backstage homepage - Setup and Customization
+description: Documentation on setting up and customizing Backstage homepage
+---
+
+## Homepage
+
+Having a good Backstage homepage can significantly improve the discoverability of the platform. You want your users to find all the things they need right from the homepage and never have to remember direct URLs in Backstage. The [Home plugin](https://github.com/backstage/backstage/tree/master/plugins/home) introduces a system for composing a homepage for Backstage in order to surface relevant info and provide convenient shortcuts for common tasks. It's designed with composability in mind with an open ecosystem that allows anyone to contribute with any component, to be included in any homepage.
+
+For App Integrators, the system is designed to be composable to give total freedom in designing a Homepage that suits the needs of the organization. From the perspective of a Component Developer who wishes to contribute with building blocks to be included in Homepages, there's a convenient interface for bundling the different parts and exporting them with both error boundary and lazy loading handled under the surface.
+
+At the end of this tutorial, you can expect:
+
+- Your Backstage app to have a dedicated homepage instead of Software Catalog.
+- Understand the composability of homepage and how to start customizing it for your own organization.
+
+### Prerequisites
+
+Before we begin, make sure
+
+- You have created your own standalone Backstage app using [`@backstage/create-app`](index.md#create-your-backstage-app) and not using a fork of the [backstage](https://github.com/backstage/backstage) repository.
+- You do not have an existing homepage, and by default you are redirected to Software Catalog when you open Backstage.
+
+Now, let's get started by installing the home plugin and creating a simple homepage for your Backstage app.
+
+### Setup homepage
+
+#### 1. Install the plugin
+
+```
+# From your Backstage application directory
+cd packages/app
+yarn add @backstage/plugin-home
+```
+
+#### 2. Create a new HomePage component
+
+Inside your `packages/app` directory, create a new file where our new homepage component is going to live. Create `packages/app/src/components/home/HomePage.tsx` with the following initial code
+
+```tsx
+import React from 'react';
+
+export const HomePage = () => {
+ /* We will shortly compose a pretty homepage here. */
+ return
Welcome to Backstage!
;
+};
+```
+
+#### 3. Update router for the root `/` route
+
+If you don't have a homepage already, most likely you have a redirect setup to use the Catalog homepage as a homepage.
+
+Inside your `packages/app/src/App.tsx`, look for
+
+```tsx
+const routes = (
+
+
+```
+
+Let's replace the `` line and use the new component we created in the previous step as the new homepage.
+
+```diff
+// File: packages/app/src/App.tsx
+
++ import { HomepageCompositionRoot } from '@backstage/plugin-home';
++ import { HomePage } from './components/home/HomePage';
+
+// ...
+const routes = (
+
+-
++ }>
++
++
+// ...
+
+)
+```
+
+### 4. Update sidebar items
+
+Let's update the route for "Home" in the Backstage sidebar to point to the new homepage. We'll also add a Sidebar item to quickly open Catalog.
+
+
+
+
+
+
+
+
Before
+
After
+
+
+
+The code for the Backstage sidebar is most likely inside your [`packages/app/src/components/Root/Root.tsx`](https://github.com/backstage/backstage/blob/master/packages/app/src/components/Root/Root.tsx).
+
+Let's make the following changes
+
+```diff
+// Other imports
++ import CategoryIcon from '@material-ui/icons/Category';
+
+export const Root = ({ children }: PropsWithChildren<{}>) => (
+
+
+
+ # ...
+ }>
+ {/* Global nav, not org-specific */}
+-
++
++
+
+
+
+
+ {/* End global nav */}
+
+```
+
+That's it! You should now have _(although slightly boring)_ a homepage!
+
+
+
+In the next steps, we will make it interesting and useful!
+
+### Use the default template
+
+There is a default homepage template ([storybook link](https://backstage.io/storybook/?path=/story/plugins-home-templates--default-template)) which we will use to set up our homepage. Checkout the [blog post announcement](https://backstage.io/blog/2022/01/25/backstage-homepage-templates) about the Backstage homepage templates for more information.
+
+
+
+### Composing your homepage
+
+Composing a homepage is no different from creating a regular React Component,
+i.e. the App Integrator is free to include whatever content they like. However,
+there are components developed with the homepage in mind. If you are looking
+for components to use when composing your homepage, you can take a look at the
+[collection of Homepage components](https://backstage.io/storybook?path=/story/plugins-home-components)
+in storybook. If you don't find a component that suits your needs but want to
+contribute, check the
+[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing).
+
+> If you want to use one of the available homepage templates you can find the
+> [templates](https://backstage.io/storybook/?path=/story/plugins-home-templates)
+> in the storybook under the "Home" plugin. And if you would like to contribute
+> a template, please see the
+> [Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing)
+
+```tsx
+import React from 'react';
+import Grid from '@material-ui/core/Grid';
+import { HomePageCompanyLogo } from '@backstage/plugin-home';
+
+export const HomePage = () => {
+ return (
+
+
+
+
+
+ );
+};
+```
diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md
index a622313739..8c2f6bc865 100644
--- a/docs/getting-started/index.md
+++ b/docs/getting-started/index.md
@@ -25,7 +25,7 @@ guide to do a repository-based installation.
[Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/)
- An account with elevated rights to install the dependencies
- `curl` or `wget` installed
-- Node.js Active LTS Release installed (currently v14) using one of these
+- Node.js [Active LTS Release](https://nodejs.org/en/about/releases/) installed using one of these
methods:
- Using `nvm` (recommended)
- [Installing nvm](https://github.com/nvm-sh/nvm#install--update-script)
diff --git a/docs/getting-started/running-backstage-locally.md b/docs/getting-started/running-backstage-locally.md
index daad7bf195..3443b85285 100644
--- a/docs/getting-started/running-backstage-locally.md
+++ b/docs/getting-started/running-backstage-locally.md
@@ -13,13 +13,14 @@ trying to contribute, follow the instructions to
- Node.js
-First make sure you are using Node.js with an Active LTS Release, currently v14.
+First make sure you are using Node.js with an [Active LTS Release](https://nodejs.org/en/about/releases/).
This is made easy with a version manager such as
[nvm](https://github.com/nvm-sh/nvm) which allows for version switching.
```bash
-# Installing a new version
-nvm install 14
+# Installing current LTS release
+nvm install --lts
+> Installing latest LTS version.
> Downloading and installing node v14.15.1...
> Now using node v14.15.1 (npm v6.14.8)
diff --git a/docs/integrations/azure/discovery.md b/docs/integrations/azure/discovery.md
index ad452f47af..1deec423a7 100644
--- a/docs/integrations/azure/discovery.md
+++ b/docs/integrations/azure/discovery.md
@@ -12,7 +12,7 @@ DevOps organization and register entities matching the configured path. This can
be useful as an alternative to static locations or manually adding things to the
catalog.
-To use the discovery processor, you'll need a GitHub integration
+To use the discovery processor, you'll need a Azure integration
[set up](locations.md) with a `AZURE_TOKEN`. Then you can add a location target
to the catalog configuration:
diff --git a/docs/integrations/github/locations.md b/docs/integrations/github/locations.md
index 330b03eab9..3395c61117 100644
--- a/docs/integrations/github/locations.md
+++ b/docs/integrations/github/locations.md
@@ -57,6 +57,22 @@ public GitHub, for which we can infer them). The `apiBaseUrl` will always be
preferred over the other if a `token` is given, otherwise `rawBaseUrl` will be
preferred.
+### Token scopes
+
+When creating a personal access token on GitHub, you must select scopes to
+define the level of access for the token. The scopes required vary depending on
+your use of the integration:
+
+- Reading software components:
+ - `repo`
+- Reading organization data:
+ - `read:org`
+ - `read:user`
+ - `user:email`
+- Publishing software templates:
+ - `repo`
+ - `workflow` (if templates include GitHub workflows)
+
## Authentication with GitHub Apps
Alternatively, Backstage can use GitHub Apps for backend authentication. This
diff --git a/docs/integrations/github/org.md b/docs/integrations/github/org.md
index 7140ffa505..5843944e8a 100644
--- a/docs/integrations/github/org.md
+++ b/docs/integrations/github/org.md
@@ -22,19 +22,6 @@ entities that mirror your org setup.
The processor that performs the import, `GithubOrgReaderProcessor`, comes
installed with the default setup of Backstage.
-If you have _replaced_ the set of processors in your installation using
-`replaceProcessors`, you can import and add it as follows:
-
-```ts
-// Typically in packages/backend/src/plugins/catalog.ts
-import { GithubOrgReaderProcessor } from '@backstage/plugin-catalog-backend';
-
-builder.replaceProcessors(
- GithubOrgReaderProcessor.fromConfig(config, { logger }),
- // ...
-);
-```
-
## Configuration
The following configuration enables an import of the teams and users under the
@@ -51,10 +38,12 @@ If Backstage is configured to use GitHub Apps authentication you must grant
`Read-Only` access for `Members` under `Organization` in order to ingest users
correctly. You can modify the app's permissions under the organization settings,
`https://github.com/organizations/{ORG}/settings/apps/{APP_NAME}/permissions`.
+

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

Locations point out the specific org(s) you want to import. The `type` of these
@@ -65,3 +54,22 @@ The authorization for loading org information comes from a configured
[GitHub integration](locations.md#configuration). When using a personal access
token, the token needs to have at least the scopes `read:org`, `read:user`, and
`user:email` in the given `target`.
+
+## Addendum
+
+Some Backstage apps have _replaced_ the catalog processors to override the
+default catalog processing behavior. These apps will already have a call to
+`replaceProcessors` in the catalog initialization.
+
+In the unlikely scenario that this applies to your app, you can import and
+add the `GithubOrgReaderProcessor` as follows:
+
+```ts
+// Typically in packages/backend/src/plugins/catalog.ts
+import { GithubOrgReaderProcessor } from '@backstage/plugin-catalog-backend';
+
+builder.replaceProcessors(
+ // ... other processor replacements
+ GithubOrgReaderProcessor.fromConfig(config, { logger }),
+);
+```
diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md
index c4a08afc56..75f0606752 100644
--- a/docs/local-dev/cli-build-system.md
+++ b/docs/local-dev/cli-build-system.md
@@ -334,13 +334,19 @@ The following is an example of a `Dockerfile` that can be used to package the
output of `backstage-cli backend:bundle` into an image:
```Dockerfile
-FROM node:14-buster-slim
+FROM node:16-bullseye-slim
WORKDIR /app
COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./
RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz
-RUN yarn install --production --frozen-lockfile --network-timeout 300000 && rm -rf "$(yarn cache dir)"
+# 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)"
COPY packages/backend/dist/bundle.tar.gz app-config.yaml ./
RUN tar xzf bundle.tar.gz && rm bundle.tar.gz
diff --git a/docs/overview/adopting.md b/docs/overview/adopting.md
index 152be21a2c..0765d4a452 100644
--- a/docs/overview/adopting.md
+++ b/docs/overview/adopting.md
@@ -25,7 +25,7 @@ This team will have **four** primary objectives:
2. Drive adoption of customers (developers at your company).
-3. Work with senior tech leadership and architects to ensure your organizations
+3. Work with senior tech leadership and architects to ensure your organization's
best practices for software development are encoded into a set of
[Software Templates](../features/software-templates/index.md).
@@ -62,7 +62,7 @@ products they maintain.
### Tactics
-Example of tactics we have used to evangelize Backstage internally:
+Examples of tactics we have used to evangelize Backstage internally:
- Arrange "Lunch & Learns" and seminars. Frequently offer teams interested in
Backstage development to come to a seminar where you show, for example, how to
@@ -77,13 +77,13 @@ Example of tactics we have used to evangelize Backstage internally:
- Show & tell meetings. In order to build an internal community around Backstage
we have quarterly meetings where anyone working on Backstage is invited to
- present their work. This is a not only a great way to get early feedback, but
+ present their work. This is not only a great way to get early feedback, but
also helps coordination between teams that are building overlapping
experiences.
- Provide metrics. Add instrumentation to your Backstage deployment and make
- metrics available to contributing teams. At Spotify we have even gone so far
- as sending out weekly digest email showing how usage metrics have changed for
+ metrics available to contributing teams. At Spotify, we have even gone so far
+ as to send out weekly digest emails showing how usage metrics have changed for
individual plugins.
- Pro-actively identify new plugins. Reach out to teams that own internal UIs or
@@ -109,12 +109,12 @@ successful impact on your software development process:
- **Deploys to production** Cousin to the metric above: How many times does an
engineer push changes into production.
-- **MTTR** With clear ownership of all the pieces in your micro services
+- **MTTR** With clear ownership of all the pieces in your microservices
ecosystem and all tools integrated into one place, Backstage makes it quicker
for teams to find the root cause of failures, and fix them.
- **Context switching** Reducing context switching can help engineers stay in
- the "zone". We measure the number of different tools an engineer have to
+ the "zone". We measure the number of different tools an engineer has to
interact with in order to get a certain job done (e.g. push a change, follow
it into production and validate it did not break anything).
diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md
index 5d27cc4184..358dc53852 100644
--- a/docs/overview/architecture-overview.md
+++ b/docs/overview/architecture-overview.md
@@ -281,11 +281,11 @@ stores as a means of improving performance or reliability. Similar to how
databases are supported, plugins receive logically separated cache connections,
which are powered by [Keyv](https://github.com/lukechilds/keyv) under the hood.
-At this time of writing, Backstage can be configured to use one of two cache
-stores: memory, which is mainly used for local testing, and memcache, which is a
-cache store better suited for production deployment. The right cache store for
-your Backstage instance will depend on your own run-time constraints and those
-required of the plugins you're running.
+At this time of writing, Backstage can be configured to use one of three cache
+stores: memory, which is mainly used for local testing, memcache or Redis,
+which are cache stores better suited for production deployment. The right cache
+store for your Backstage instance will depend on your own run-time constraints
+and those required of the plugins you're running.
### Use memory for cache
@@ -304,6 +304,15 @@ backend:
connection: user:pass@cache.example.com:11211
```
+### Use Redis for cache
+
+```yaml
+backend:
+ cache:
+ store: redis
+ connection: user:pass@cache.example.com:6379
+```
+
Contributions supporting other cache stores are welcome!
## Containerization
diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md
index 1c620348bb..8ecd7c4a38 100644
--- a/docs/overview/roadmap.md
+++ b/docs/overview/roadmap.md
@@ -21,7 +21,7 @@ mean features in the radar, but not yet scheduled.
The long-term roadmap (12 - 36 months) is not detailed in the public roadmap.
Third-party contributions are also not currently included in the roadmap. Let us
-know about any ongoing developments and we’re happy to include it here as well.
+know about any ongoing developments and we’re happy to include them here as well.
## What’s next
diff --git a/docs/plugins/github-apps.md b/docs/plugins/github-apps.md
index 1be1502b6b..434c9a4882 100644
--- a/docs/plugins/github-apps.md
+++ b/docs/plugins/github-apps.md
@@ -109,11 +109,21 @@ privateKey: |
This will result in backstage preventing the use of any installation that is not
within the allow list.
-### Permissions for pull requests
+### App permissions
-These are the minimum permissions required for creating a pull request with
-Backstage software templates:
+When creating a GitHub App, you must select permissions to define the level of
+access for the app. The permissions required vary depending on your use of the
+integration:
-- Read and Write permissions for `Contents`.
-- Read and write permissions for `Pull Requests` and `Issues`.
-- Read permissions on `Metadata`.
+- Reading software components:
+ - `Contents`: `Read-only`
+- Reading organization data:
+ - `Members`: `Read-only`
+- Publishing software templates:
+
+ - `Administration`: `Read & write` (for creating repositories)
+ - `Contents`: `Read & write`
+ - `Metadata`: `Read-only`
+ - `Pull requests`: `Read & write`
+ - `Issues`: `Read & write`
+ - `Workflows`: `Read & write` (if templates include GitHub workflows)
diff --git a/docs/publishing.md b/docs/publishing.md
index 2951f7d30b..fbbef93493 100644
--- a/docs/publishing.md
+++ b/docs/publishing.md
@@ -65,8 +65,8 @@ process is used to release an emergency fix as version `6.5.1` in the patch rele
master branch as well. Create a PR that contains the following:
- [ ] The fix, which you can likely cherry-pick from your patch branch: `git cherry-pick origin/patch/v1.18.0^`
- - [ ] An updated `CHANGELOG.md` of all patched patches from the tip of the patch branch, which you can get using `git checkout origin/patch/v1.18.0 -- plugins/foo/CHANGELOG.md`.
- - [ ] A changeset with the message "Applied the fix from version `6.5.1` of this package, which is part of the `v1.18.1` release of Backstage.",
+ - [ ] An updated `CHANGELOG.md` of all patched packages from the tip of the patch branch, `git checkout origin/patch/v1.18.0 -- {packages,plugins}/*/CHANGELOG.md`.
+ - [ ] A changeset with the message "Applied the fix from version `6.5.1` of this package, which is part of the `v1.18.1` release of Backstage."
- [ ] An entry in `.changeset/patched.json` that sets the current release version to `6.5.1`:
```json
diff --git a/microsite/blog/2022-01-25-backstage-homepage-templates.md b/microsite/blog/2022-01-25-backstage-homepage-templates.md
index 7ed5ee92e3..8ca8b7373e 100644
--- a/microsite/blog/2022-01-25-backstage-homepage-templates.md
+++ b/microsite/blog/2022-01-25-backstage-homepage-templates.md
@@ -33,7 +33,7 @@ _Example of the default homepage template in Backstage Storybook_
## How to get started
-To get started, you first need to set up your homepage plugin in the app if you have not already, then you can move on to composing your homepage. You can find our step-by-step documentation of how to do this under the [App Configuration - Customize the look-and-feel of your App documentation](https://backstage.io/docs/getting-started/app-custom-theme#custom-homepage). You can also access the [Backstage UI Kit in Figma](https://www.figma.com/file/nUaAw56hTgC0RIOYkuLSrB/Backstage-Design-System?node-id=2185%3A2978) to duplicate your own version and play around with a fitting homepage for your own organization.
+To get started, you first need to set up your homepage plugin in the app if you have not already, then you can move on to composing your homepage. You can find our step-by-step documentation of how to do this under the [App Configuration - Customize the look-and-feel of your App documentation](https://backstage.io/docs/getting-started/homepage). You can also access the [Backstage UI Kit in Figma](https://www.figma.com/file/nUaAw56hTgC0RIOYkuLSrB/Backstage-Design-System?node-id=2185%3A2978) to duplicate your own version and play around with a fitting homepage for your own organization.

_Example of the homepage components in the Backstage UI Kit in Figma_
diff --git a/microsite/data/plugins/airbrake.yaml b/microsite/data/plugins/airbrake.yaml
index 96de75c002..29c1f394d7 100644
--- a/microsite/data/plugins/airbrake.yaml
+++ b/microsite/data/plugins/airbrake.yaml
@@ -4,6 +4,6 @@ author: Simply Business
authorUrl: https://github.com/simplybusiness/
category: Monitoring
description: Access Airbrake error monitoring and other integrations from within Backstage
-documentation: https://github.com/backstage/backstage/blob/master/plugins/airbrake/README.md
+documentation: https://github.com/backstage/backstage/blob/master/plugins/airbrake
iconUrl: https://wp-assets.airbrake.io/wp-content/uploads/2020/10/05222904/Square-white-A-on-Orange.png
npmPackageName: '@backstage/plugin-airbrake'
diff --git a/microsite/sidebars.json b/microsite/sidebars.json
index cb7c0d5036..5369182013 100644
--- a/microsite/sidebars.json
+++ b/microsite/sidebars.json
@@ -22,7 +22,8 @@
"label": "App configuration",
"ids": [
"getting-started/configure-app-with-plugins",
- "getting-started/app-custom-theme"
+ "getting-started/app-custom-theme",
+ "getting-started/homepage"
]
},
"getting-started/keeping-backstage-updated",
diff --git a/microsite/yarn.lock b/microsite/yarn.lock
index 01226a9bf9..a9161f57fd 100644
--- a/microsite/yarn.lock
+++ b/microsite/yarn.lock
@@ -5215,9 +5215,9 @@ prettier@^2.5.1:
integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
prismjs@^1.22.0:
- version "1.25.0"
- resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756"
- integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==
+ version "1.27.0"
+ resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057"
+ integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==
process-nextick-args@~2.0.0:
version "2.0.1"
@@ -6499,9 +6499,9 @@ url-parse-lax@^3.0.0:
prepend-http "^2.0.0"
url-parse@^1.4.3:
- version "1.5.3"
- resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862"
- integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==
+ version "1.5.10"
+ resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
+ integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"
diff --git a/package.json b/package.json
index 242c64c8bb..e7cb42c1c6 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,7 @@
"**/@roadiehq/**/@backstage/plugin-catalog": "*",
"**/@roadiehq/**/@backstage/catalog-model": "*"
},
- "version": "0.67.0",
+ "version": "0.69.0",
"dependencies": {
"@manypkg/get-packages": "^1.1.3",
"@microsoft/api-documenter": "^7.15.0",
diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md
index 74313008cd..6fb6c46b76 100644
--- a/packages/app-defaults/CHANGELOG.md
+++ b/packages/app-defaults/CHANGELOG.md
@@ -1,5 +1,27 @@
# @backstage/app-defaults
+## 0.1.9
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/core-components@0.8.10
+ - @backstage/core-plugin-api@0.7.0
+ - @backstage/core-app-api@0.5.4
+ - @backstage/plugin-permission-react@0.3.2
+
+## 0.1.8
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/core-app-api@0.5.3
+ - @backstage/core-components@0.8.9
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/plugin-permission-react@0.3.1
+ - @backstage/theme@0.2.15
+
## 0.1.7
### Patch Changes
diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json
index c7cb87faa4..e65d8f53ac 100644
--- a/packages/app-defaults/package.json
+++ b/packages/app-defaults/package.json
@@ -1,13 +1,16 @@
{
"name": "@backstage/app-defaults",
"description": "Provides the default wiring of a Backstage App",
- "version": "0.1.7",
+ "version": "0.1.9",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "web-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,19 +24,20 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build --outputs types,esm",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/core-components": "^0.8.8",
- "@backstage/core-app-api": "^0.5.2",
- "@backstage/core-plugin-api": "^0.6.0",
- "@backstage/plugin-permission-react": "^0.3.0",
- "@backstage/theme": "^0.2.14",
+ "@backstage/core-components": "^0.8.10",
+ "@backstage/core-app-api": "^0.5.4",
+ "@backstage/core-plugin-api": "^0.7.0",
+ "@backstage/plugin-permission-react": "^0.3.2",
+ "@backstage/theme": "^0.2.15",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"react-router-dom": "6.0.0-beta.0"
@@ -42,8 +46,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
- "@backstage/test-utils": "^0.2.4",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/test-utils": "^0.2.6",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@types/jest": "^26.0.7",
diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md
index 1139bf2cbb..029b97ec30 100644
--- a/packages/app/CHANGELOG.md
+++ b/packages/app/CHANGELOG.md
@@ -1,5 +1,110 @@
# example-app
+## 0.2.66
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog@0.9.0
+ - @backstage/cli@0.14.1
+ - @backstage/core-components@0.8.10
+ - @backstage/plugin-api-docs@0.8.0
+ - @backstage/plugin-catalog-react@0.7.0
+ - @backstage/plugin-catalog-graph@0.2.12
+ - @backstage/plugin-jenkins@0.6.0
+ - @backstage/plugin-scaffolder@0.13.0
+ - @backstage/plugin-techdocs@0.14.0
+ - @backstage/plugin-airbrake@0.3.0
+ - @backstage/catalog-model@0.11.0
+ - @backstage/plugin-catalog-import@0.8.3
+ - @backstage/plugin-explore@0.3.31
+ - @backstage/core-plugin-api@0.7.0
+ - @backstage/plugin-circleci@0.3.0
+ - @backstage/plugin-cloudbuild@0.3.0
+ - @backstage/plugin-github-actions@0.5.0
+ - @backstage/plugin-kafka@0.3.0
+ - @backstage/plugin-kubernetes@0.6.0
+ - @backstage/plugin-lighthouse@0.3.0
+ - @backstage/plugin-org@0.5.0
+ - @backstage/plugin-rollbar@0.4.0
+ - @backstage/plugin-gocd@0.1.6
+ - @backstage/plugin-azure-devops@0.1.16
+ - @backstage/plugin-badges@0.2.24
+ - @backstage/plugin-code-coverage@0.1.27
+ - @backstage/plugin-home@0.4.16
+ - @backstage/plugin-newrelic-dashboard@0.1.8
+ - @backstage/plugin-pagerduty@0.3.27
+ - @backstage/plugin-search@0.7.1
+ - @backstage/plugin-sentry@0.3.38
+ - @backstage/plugin-tech-insights@0.1.10
+ - @backstage/plugin-todo@0.2.2
+ - @backstage/plugin-cost-insights@0.11.22
+ - @backstage/app-defaults@0.1.9
+ - @backstage/core-app-api@0.5.4
+ - @backstage/integration-react@0.1.23
+ - @backstage/plugin-apache-airflow@0.1.8
+ - @backstage/plugin-gcp-projects@0.3.19
+ - @backstage/plugin-graphiql@0.2.32
+ - @backstage/plugin-newrelic@0.3.18
+ - @backstage/plugin-permission-react@0.3.2
+ - @backstage/plugin-shortcuts@0.2.1
+ - @backstage/plugin-tech-radar@0.5.7
+ - @backstage/plugin-user-settings@0.3.21
+
+## 0.2.65
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/cli@0.14.0
+ - @backstage/core-app-api@0.5.3
+ - @backstage/core-components@0.8.9
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/integration-react@0.1.22
+ - @backstage/plugin-airbrake@0.2.0
+ - @backstage/plugin-apache-airflow@0.1.7
+ - @backstage/plugin-api-docs@0.7.3
+ - @backstage/plugin-azure-devops@0.1.15
+ - @backstage/plugin-badges@0.2.23
+ - @backstage/plugin-catalog@0.8.0
+ - @backstage/plugin-catalog-import@0.8.2
+ - @backstage/plugin-catalog-react@0.6.15
+ - @backstage/plugin-circleci@0.2.38
+ - @backstage/plugin-cloudbuild@0.2.36
+ - @backstage/plugin-code-coverage@0.1.26
+ - @backstage/plugin-cost-insights@0.11.21
+ - @backstage/plugin-explore@0.3.30
+ - @backstage/plugin-gcp-projects@0.3.18
+ - @backstage/plugin-github-actions@0.4.36
+ - @backstage/plugin-gocd@0.1.5
+ - @backstage/plugin-graphiql@0.2.31
+ - @backstage/plugin-home@0.4.15
+ - @backstage/plugin-jenkins@0.5.21
+ - @backstage/plugin-kafka@0.2.29
+ - @backstage/plugin-kubernetes@0.5.8
+ - @backstage/plugin-lighthouse@0.2.38
+ - @backstage/plugin-newrelic@0.3.17
+ - @backstage/plugin-newrelic-dashboard@0.1.7
+ - @backstage/plugin-org@0.4.3
+ - @backstage/plugin-pagerduty@0.3.26
+ - @backstage/plugin-permission-react@0.3.1
+ - @backstage/plugin-rollbar@0.3.27
+ - @backstage/plugin-scaffolder@0.12.3
+ - @backstage/plugin-search@0.7.0
+ - @backstage/plugin-sentry@0.3.37
+ - @backstage/plugin-shortcuts@0.2.0
+ - @backstage/plugin-tech-insights@0.1.9
+ - @backstage/plugin-tech-radar@0.5.6
+ - @backstage/plugin-techdocs@0.13.4
+ - @backstage/plugin-todo@0.2.1
+ - @backstage/plugin-user-settings@0.3.20
+ - @backstage/app-defaults@0.1.8
+ - @backstage/catalog-model@0.10.0
+ - @backstage/search-common@0.2.3
+ - @backstage/theme@0.2.15
+ - @backstage/plugin-catalog-common@0.1.3
+ - @backstage/plugin-catalog-graph@0.2.11
+
## 0.2.64
### Patch Changes
diff --git a/packages/app/package.json b/packages/app/package.json
index bdade7974a..25dcbbd945 100644
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -1,65 +1,68 @@
{
"name": "example-app",
- "version": "0.2.64",
+ "version": "0.2.66",
"private": true,
+ "backstage": {
+ "role": "frontend"
+ },
"bundled": true,
"dependencies": {
- "@backstage/app-defaults": "^0.1.7",
- "@backstage/catalog-model": "^0.9.10",
- "@backstage/cli": "^0.13.2",
- "@backstage/core-app-api": "^0.5.2",
- "@backstage/core-components": "^0.8.8",
- "@backstage/core-plugin-api": "^0.6.0",
- "@backstage/integration-react": "^0.1.21",
- "@backstage/plugin-airbrake": "^0.1.3",
- "@backstage/plugin-api-docs": "^0.7.2",
- "@backstage/plugin-azure-devops": "^0.1.14",
- "@backstage/plugin-apache-airflow": "^0.1.6",
- "@backstage/plugin-badges": "^0.2.22",
- "@backstage/plugin-catalog": "^0.7.12",
- "@backstage/plugin-catalog-common": "^0.1.2",
- "@backstage/plugin-catalog-graph": "^0.2.10",
- "@backstage/plugin-catalog-import": "^0.8.1",
- "@backstage/plugin-catalog-react": "^0.6.14",
- "@backstage/plugin-circleci": "^0.2.37",
- "@backstage/plugin-cloudbuild": "^0.2.35",
- "@backstage/plugin-code-coverage": "^0.1.25",
- "@backstage/plugin-cost-insights": "^0.11.20",
- "@backstage/plugin-explore": "^0.3.29",
- "@backstage/plugin-gcp-projects": "^0.3.17",
- "@backstage/plugin-github-actions": "^0.4.35",
- "@backstage/plugin-gocd": "^0.1.4",
- "@backstage/plugin-graphiql": "^0.2.30",
- "@backstage/plugin-home": "^0.4.14",
- "@backstage/plugin-jenkins": "^0.5.20",
- "@backstage/plugin-kafka": "^0.2.28",
- "@backstage/plugin-kubernetes": "^0.5.7",
- "@backstage/plugin-lighthouse": "^0.2.37",
- "@backstage/plugin-newrelic": "^0.3.16",
- "@backstage/plugin-newrelic-dashboard": "^0.1.6",
- "@backstage/plugin-org": "^0.4.2-next.0",
- "@backstage/plugin-pagerduty": "0.3.25",
- "@backstage/plugin-permission-react": "^0.3.0",
- "@backstage/plugin-rollbar": "^0.3.26",
- "@backstage/plugin-scaffolder": "^0.12.2",
- "@backstage/plugin-search": "^0.6.2",
- "@backstage/plugin-sentry": "^0.3.36",
- "@backstage/plugin-shortcuts": "^0.1.22",
- "@backstage/plugin-tech-radar": "^0.5.5",
- "@backstage/plugin-techdocs": "^0.13.3",
- "@backstage/plugin-todo": "^0.2.0",
- "@backstage/plugin-user-settings": "^0.3.19",
- "@backstage/search-common": "^0.2.2",
- "@backstage/plugin-tech-insights": "^0.1.8",
- "@backstage/theme": "^0.2.14",
+ "@backstage/app-defaults": "^0.1.9",
+ "@backstage/catalog-model": "^0.11.0",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/core-app-api": "^0.5.4",
+ "@backstage/core-components": "^0.8.10",
+ "@backstage/core-plugin-api": "^0.7.0",
+ "@backstage/integration-react": "^0.1.23",
+ "@backstage/plugin-airbrake": "^0.3.0",
+ "@backstage/plugin-api-docs": "^0.8.0",
+ "@backstage/plugin-azure-devops": "^0.1.16",
+ "@backstage/plugin-apache-airflow": "^0.1.8",
+ "@backstage/plugin-badges": "^0.2.24",
+ "@backstage/plugin-catalog": "^0.9.0",
+ "@backstage/plugin-catalog-common": "^0.1.4",
+ "@backstage/plugin-catalog-graph": "^0.2.12",
+ "@backstage/plugin-catalog-import": "^0.8.3",
+ "@backstage/plugin-catalog-react": "^0.7.0",
+ "@backstage/plugin-circleci": "^0.3.0",
+ "@backstage/plugin-cloudbuild": "^0.3.0",
+ "@backstage/plugin-code-coverage": "^0.1.27",
+ "@backstage/plugin-cost-insights": "^0.11.22",
+ "@backstage/plugin-explore": "^0.3.31",
+ "@backstage/plugin-gcp-projects": "^0.3.19",
+ "@backstage/plugin-github-actions": "^0.5.0",
+ "@backstage/plugin-gocd": "^0.1.6",
+ "@backstage/plugin-graphiql": "^0.2.32",
+ "@backstage/plugin-home": "^0.4.16",
+ "@backstage/plugin-jenkins": "^0.6.0",
+ "@backstage/plugin-kafka": "^0.3.0",
+ "@backstage/plugin-kubernetes": "^0.6.0",
+ "@backstage/plugin-lighthouse": "^0.3.0",
+ "@backstage/plugin-newrelic": "^0.3.18",
+ "@backstage/plugin-newrelic-dashboard": "^0.1.8",
+ "@backstage/plugin-org": "^0.5.0",
+ "@backstage/plugin-pagerduty": "0.3.27",
+ "@backstage/plugin-permission-react": "^0.3.2",
+ "@backstage/plugin-rollbar": "^0.4.0",
+ "@backstage/plugin-scaffolder": "^0.13.0",
+ "@backstage/plugin-search": "^0.7.1",
+ "@backstage/plugin-sentry": "^0.3.38",
+ "@backstage/plugin-shortcuts": "^0.2.1",
+ "@backstage/plugin-tech-radar": "^0.5.7",
+ "@backstage/plugin-techdocs": "^0.14.0",
+ "@backstage/plugin-todo": "^0.2.2",
+ "@backstage/plugin-user-settings": "^0.3.21",
+ "@backstage/search-common": "^0.2.4",
+ "@backstage/plugin-tech-insights": "^0.1.10",
+ "@backstage/theme": "^0.2.15",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
"@octokit/rest": "^18.5.3",
- "@roadiehq/backstage-plugin-github-insights": "^1.4.2",
- "@roadiehq/backstage-plugin-github-pull-requests": "^1.3.2",
- "@roadiehq/backstage-plugin-travis-ci": "^1.3.2",
- "@roadiehq/backstage-plugin-buildkite": "^1.3.4",
+ "@roadiehq/backstage-plugin-github-insights": "^1.5.0",
+ "@roadiehq/backstage-plugin-github-pull-requests": "^1.4.0",
+ "@roadiehq/backstage-plugin-travis-ci": "^1.3.6",
+ "@roadiehq/backstage-plugin-buildkite": "^1.3.8",
"history": "^5.0.0",
"prop-types": "^15.7.2",
"react": "^17.0.2",
@@ -71,8 +74,8 @@
"zen-observable": "^0.8.15"
},
"devDependencies": {
- "@backstage/plugin-permission-react": "^0.3.0",
- "@backstage/test-utils": "^0.2.4",
+ "@backstage/plugin-permission-react": "^0.3.2",
+ "@backstage/test-utils": "^0.2.6",
"@rjsf/core": "^3.2.1",
"@testing-library/cypress": "^8.0.2",
"@testing-library/jest-dom": "^5.10.1",
@@ -84,18 +87,18 @@
"@types/react-dom": "*",
"@types/zen-observable": "^0.8.0",
"cross-env": "^7.0.0",
- "cypress": "^7.3.0",
+ "cypress": "^9.5.0",
"eslint-plugin-cypress": "^2.10.3",
"start-server-and-test": "^1.10.11"
},
"scripts": {
- "start": "backstage-cli app:serve",
- "build": "backstage-cli app:build",
- "clean": "backstage-cli clean",
- "test": "backstage-cli test",
+ "start": "backstage-cli package start",
+ "build": "backstage-cli package build",
+ "clean": "backstage-cli package clean",
+ "test": "backstage-cli package test",
"test:e2e": "start-server-and-test start http://localhost:3000 cy:dev",
"test:e2e:ci": "start-server-and-test start http://localhost:3000 cy:run",
- "lint": "backstage-cli lint",
+ "lint": "backstage-cli package lint",
"cy:dev": "cypress open",
"cy:run": "cypress run"
},
diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx
index 345915189a..374d637b2e 100644
--- a/packages/app/src/App.tsx
+++ b/packages/app/src/App.tsx
@@ -65,7 +65,6 @@ import {
import { SearchPage } from '@backstage/plugin-search';
import { TechRadarPage } from '@backstage/plugin-tech-radar';
import {
- DefaultTechDocsHome,
TechDocsIndexPage,
techdocsPlugin,
TechDocsReaderPage,
@@ -169,9 +168,7 @@ const routes = (
/>
}
/>
- }>
-
-
+ } />
}
diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx
index 1c96e9325c..61407e2918 100644
--- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx
+++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx
@@ -13,14 +13,44 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+import React from 'react';
import type { FieldValidation } from '@rjsf/core';
import {
createScaffolderFieldExtension,
- TextValuePicker,
+ FieldExtensionComponentProps,
scaffolderPlugin,
} from '@backstage/plugin-scaffolder';
+import { TextField } from '@material-ui/core';
+
+const TextValuePicker = (props: FieldExtensionComponentProps) => {
+ const {
+ onChange,
+ required,
+ schema: { title, description },
+ rawErrors,
+ formData,
+ uiSchema: { 'ui:autofocus': autoFocus },
+ idSchema,
+ placeholder,
+ } = props;
+
+ return (
+ onChange(value)}
+ margin="normal"
+ error={rawErrors?.length > 0 && !formData}
+ inputProps={{ autoFocus }}
+ />
+ );
+};
+
export const LowerCaseValuePickerFieldExtension = scaffolderPlugin.provide(
createScaffolderFieldExtension({
name: 'LowerCaseValuePicker',
diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx
index d4e60244d7..65da72d91c 100644
--- a/packages/app/src/components/search/SearchPage.tsx
+++ b/packages/app/src/components/search/SearchPage.tsx
@@ -24,7 +24,7 @@ import {
SidebarPinStateContext,
} from '@backstage/core-components';
import { useApi } from '@backstage/core-plugin-api';
-import { CatalogResultListItem } from '@backstage/plugin-catalog';
+import { CatalogSearchResultListItem } from '@backstage/plugin-catalog';
import {
catalogApiRef,
CATALOG_FILTER_EXISTS,
@@ -38,7 +38,7 @@ import {
SearchType,
useSearch,
} from '@backstage/plugin-search';
-import { DocsResultListItem } from '@backstage/plugin-techdocs';
+import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
import { Grid, List, makeStyles, Paper, Theme } from '@material-ui/core';
import React, { useContext } from 'react';
@@ -136,14 +136,14 @@ const SearchPage = () => {
switch (type) {
case 'software-catalog':
return (
-
);
case 'techdocs':
return (
-
diff --git a/packages/app/src/components/techdocs/TechDocsPage.tsx b/packages/app/src/components/techdocs/TechDocsPage.tsx
index be11e30e61..4f49cf38e8 100644
--- a/packages/app/src/components/techdocs/TechDocsPage.tsx
+++ b/packages/app/src/components/techdocs/TechDocsPage.tsx
@@ -16,18 +16,18 @@
import { Content } from '@backstage/core-components';
import {
- TechDocsPageHeader,
- TechDocsPage,
+ TechDocsReaderPageHeader,
+ TechDocsReaderPage,
Reader,
} 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 2e80c62c92..ce5c2f0894 100644
--- a/packages/backend-common/CHANGELOG.md
+++ b/packages/backend-common/CHANGELOG.md
@@ -1,5 +1,48 @@
# @backstage/backend-common
+## 0.11.0
+
+### Minor Changes
+
+- 7d12e4cf32: feat(backend-common): add Redis backed cache store
+
+### Patch Changes
+
+- b2f8bb99d3: Make backend.auth.keys optional in config schema. Previously backend.auth was optional but keys was not, which meant that if another plugin introduced additional properties under backend.auth, it would implicitly make backend.auth.keys mandatory.
+- d64b8d3678: chore(deps): bump `minimatch` from 3.0.4 to 5.0.0
+- Updated dependencies
+ - @backstage/config-loader@0.9.6
+ - @backstage/integration@0.7.5
+
+## 0.10.9
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/cli-common@0.1.8
+ - @backstage/config@0.1.15
+ - @backstage/config-loader@0.9.5
+ - @backstage/errors@0.2.2
+ - @backstage/integration@0.7.4
+ - @backstage/types@0.1.3
+
+## 0.10.8
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- 0107c9aa08: chore(deps): bump `helmet` from 4.4.1 to 5.0.2
+- b590e9b58d: Updated `isDatabaseConflictError` to handle modern sqlite conflict errors
+- Updated dependencies
+ - @backstage/config-loader@0.9.4
+ - @backstage/errors@0.2.1
+ - @backstage/integration@0.7.3
+ - @backstage/cli-common@0.1.7
+ - @backstage/config@0.1.14
+ - @backstage/types@0.1.2
+
## 0.10.7
### Patch Changes
diff --git a/packages/backend-common/config.d.ts b/packages/backend-common/config.d.ts
index 16ca1698f6..57645d9fda 100644
--- a/packages/backend-common/config.d.ts
+++ b/packages/backend-common/config.d.ts
@@ -23,7 +23,7 @@ export interface Config {
/** Backend configuration for when request authentication is enabled */
auth?: {
/** Keys shared by all backends for signing and validating backend tokens. */
- keys: {
+ keys?: {
/**
* Secret for generating tokens. Should be a base64 string, recommended
* length is 24 bytes.
@@ -134,6 +134,14 @@ export interface Config {
| {
store: 'memory';
}
+ | {
+ store: 'redis';
+ /**
+ * A redis connection string in the form `user:pass@host:port`.
+ * @secret
+ */
+ connection: string;
+ }
| {
store: 'memcache';
/**
diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json
index 13a34a1d81..fd5ea443ab 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.10.7",
+ "version": "0.11.0",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -11,6 +11,9 @@
"types": "dist/index.d.ts",
"alphaTypes": "dist/index.alpha.d.ts"
},
+ "backstage": {
+ "role": "node-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -22,20 +25,21 @@
],
"license": "Apache-2.0",
"scripts": {
- "build": "backstage-cli build --experimental-type-build --outputs cjs,types",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build --experimental-type-build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/cli-common": "^0.1.6",
- "@backstage/config": "^0.1.13",
- "@backstage/config-loader": "^0.9.3",
- "@backstage/errors": "^0.2.0",
- "@backstage/integration": "^0.7.2",
- "@backstage/types": "^0.1.1",
+ "@backstage/cli-common": "^0.1.8",
+ "@backstage/config": "^0.1.15",
+ "@backstage/config-loader": "^0.9.6",
+ "@backstage/errors": "^0.2.2",
+ "@backstage/integration": "^0.7.5",
+ "@backstage/types": "^0.1.3",
"@google-cloud/storage": "^5.8.0",
"@manypkg/get-packages": "^1.1.3",
"@octokit/rest": "^18.5.3",
@@ -53,16 +57,17 @@
"express-promise-router": "^4.1.0",
"fs-extra": "9.1.0",
"git-url-parse": "^11.6.0",
- "helmet": "^4.0.0",
+ "helmet": "^5.0.2",
"isomorphic-git": "^1.8.0",
"jose": "^1.27.1",
"keyv": "^4.0.3",
"keyv-memcache": "^1.2.5",
+ "@keyv/redis": "^2.2.3",
"knex": "^1.0.2",
"lodash": "^4.17.21",
"logform": "^2.3.2",
"luxon": "^2.0.2",
- "minimatch": "^3.0.4",
+ "minimatch": "^5.0.0",
"minimist": "^1.2.5",
"morgan": "^1.10.0",
"node-abort-controller": "^3.0.1",
@@ -84,8 +89,8 @@
}
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
- "@backstage/test-utils": "^0.2.4",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/test-utils": "^0.2.6",
"@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 ce5b6f5999..660aa82bb0 100644
--- a/packages/backend-common/src/cache/CacheManager.test.ts
+++ b/packages/backend-common/src/cache/CacheManager.test.ts
@@ -18,6 +18,8 @@ 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';
import { NoStore } from './NoStore';
@@ -26,6 +28,8 @@ jest.createMockFromModule('keyv');
jest.mock('keyv');
jest.createMockFromModule('keyv-memcache');
jest.mock('keyv-memcache');
+jest.createMockFromModule('@keyv/redis');
+jest.mock('@keyv/redis');
jest.mock('./CacheClient', () => {
return {
DefaultCacheClient: jest.fn(),
@@ -190,6 +194,33 @@ describe('CacheManager', () => {
});
});
+ it('returns a Redis client when configured', () => {
+ const redisHostAndPort = '127.0.0.1:6379';
+ const expectedHost = `redis://${redisHostAndPort}`;
+ const manager = CacheManager.fromConfig(
+ new ConfigReader({
+ backend: {
+ cache: {
+ store: 'redis',
+ connection: redisHostAndPort,
+ },
+ },
+ }),
+ );
+ const expectedTtl = 3600;
+ manager.forPlugin('test').getClient({ defaultTtl: expectedTtl });
+
+ const cache = Keyv as unknown as jest.Mock;
+ const mockCacheCalls = cache.mock.calls.splice(-1);
+ expect(mockCacheCalls[0][0]).toMatchObject({
+ ttl: expectedTtl,
+ });
+ expect(mockCacheCalls[0][0].store).toBeInstanceOf(KeyvRedis);
+ const redis = KeyvRedis as jest.Mock;
+ const mockRedisCalls = redis.mock.calls.splice(-1);
+ expect(mockRedisCalls[0][0]).toEqual(expectedHost);
+ });
+
describe('connection errors', () => {
it('uses provided logger', () => {
// Set up and inject mock logger.
diff --git a/packages/backend-common/src/cache/CacheManager.ts b/packages/backend-common/src/cache/CacheManager.ts
index 66e9849e77..d63ac6d940 100644
--- a/packages/backend-common/src/cache/CacheManager.ts
+++ b/packages/backend-common/src/cache/CacheManager.ts
@@ -18,6 +18,8 @@ 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';
import { DefaultCacheClient, CacheClient } from './CacheClient';
@@ -37,6 +39,7 @@ export class CacheManager {
* that return Keyv instances appropriate to the store.
*/
private readonly storeFactories = {
+ redis: this.getRedisClient,
memcache: this.getMemcacheClient,
memory: this.getMemoryClient,
none: this.getNoneClient,
@@ -123,6 +126,17 @@ export class CacheManager {
return this.storeFactories[this.store].call(this, pluginId, ttl);
}
+ private getRedisClient(
+ pluginId: string,
+ defaultTtl: number | undefined,
+ ): Keyv {
+ return new Keyv({
+ namespace: pluginId,
+ ttl: defaultTtl,
+ store: new KeyvRedis(`redis://${this.connection}`),
+ });
+ }
+
private getMemcacheClient(
pluginId: string,
defaultTtl: number | undefined,
diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts
index d155287b34..105704159b 100644
--- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts
+++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts
@@ -19,7 +19,7 @@ import compression from 'compression';
import cors from 'cors';
import express, { Router, ErrorRequestHandler } from 'express';
import helmet from 'helmet';
-import { ContentSecurityPolicyOptions } from 'helmet/dist/middlewares/content-security-policy';
+import { ContentSecurityPolicyOptions } from 'helmet/dist/types/middlewares/content-security-policy';
import * as http from 'http';
import stoppable from 'stoppable';
import { Logger } from 'winston';
@@ -215,8 +215,17 @@ export class ServiceBuilderImpl implements ServiceBuilder {
httpsSettings: this.httpsSettings,
helmetOptions: {
contentSecurityPolicy: {
+ useDefaults: false,
directives: applyCspDirectives(this.cspOptions),
},
+ // These are all disabled in order to maintain backwards compatibility
+ // when bumping helmet v5. We can't enable these by default because
+ // there is no way for users to configure them.
+ // TODO(Rugvip): We should give control of this setup to consumers
+ crossOriginEmbedderPolicy: false,
+ crossOriginOpenerPolicy: false,
+ crossOriginResourcePolicy: false,
+ originAgentCluster: false,
},
};
}
@@ -232,6 +241,11 @@ export function applyCspDirectives(
// It should be replaced by any other solution that doesn't require unsafe-eval.
result['script-src'] = ["'self'", "'unsafe-eval'"];
+ // TODO(Rugvip): This is removed so that we maintained backwards compatibility
+ // when bumping to helmet v5, we could remove this as well as
+ // skip setting `useDefaults: false` in the future.
+ delete result['form-action'];
+
if (directives) {
for (const [key, value] of Object.entries(directives)) {
if (value === false) {
diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md
index d611ee8ac1..546d4a8187 100644
--- a/packages/backend-tasks/CHANGELOG.md
+++ b/packages/backend-tasks/CHANGELOG.md
@@ -1,5 +1,35 @@
# @backstage/backend-tasks
+## 0.1.9
+
+### Patch Changes
+
+- dc97845422: Only output janitor logs when actually timing out tasks
+- Updated dependencies
+ - @backstage/backend-common@0.11.0
+
+## 0.1.8
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/backend-common@0.10.9
+ - @backstage/config@0.1.15
+ - @backstage/errors@0.2.2
+ - @backstage/types@0.1.3
+
+## 0.1.7
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/backend-common@0.10.8
+ - @backstage/errors@0.2.1
+ - @backstage/config@0.1.14
+ - @backstage/types@0.1.2
+
## 0.1.6
### Patch Changes
diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json
index 364f1d1380..215fafe970 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.1.6",
+ "version": "0.1.9",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -10,6 +10,9 @@
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "node-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,18 +24,19 @@
],
"license": "Apache-2.0",
"scripts": {
- "build": "backstage-cli build --outputs cjs,types",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/backend-common": "^0.10.7",
- "@backstage/config": "^0.1.13",
- "@backstage/errors": "^0.2.0",
- "@backstage/types": "^0.1.1",
+ "@backstage/backend-common": "^0.11.0",
+ "@backstage/config": "^0.1.15",
+ "@backstage/errors": "^0.2.2",
+ "@backstage/types": "^0.1.3",
"@types/luxon": "^2.0.4",
"knex": "^1.0.2",
"lodash": "^4.17.21",
@@ -43,8 +47,8 @@
"zod": "^3.9.5"
},
"devDependencies": {
- "@backstage/backend-test-utils": "^0.1.17",
- "@backstage/cli": "^0.13.2",
+ "@backstage/backend-test-utils": "^0.1.19",
+ "@backstage/cli": "^0.14.1",
"jest": "^26.0.1",
"wait-for-expect": "^3.0.2"
},
diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts
index 8b90afff42..c77fe4e925 100644
--- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts
+++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts
@@ -62,19 +62,21 @@ export class PluginTaskSchedulerJanitor {
const dbNull = this.knex.raw('null');
- const tasksQuery = this.knex(DB_TASKS_TABLE)
+ const tasks = await this.knex(DB_TASKS_TABLE)
.where('current_run_expires_at', '<', this.knex.fn.now())
.update({
current_run_ticket: dbNull,
current_run_started_at: dbNull,
current_run_expires_at: dbNull,
- });
+ })
+ .returning(['id']);
- if (this.knex.client.config.client === 'sqlite3') {
- const tasks = await tasksQuery;
- this.logger.warn(`${tasks} tasks timed out and were lost`);
+ // sqlite ignores "returning", returns number of rows changed instead
+ if (typeof tasks === 'number') {
+ if (tasks > 0) {
+ this.logger.warn(`${tasks} tasks timed out and were lost`);
+ }
} else {
- const tasks = await tasksQuery.returning(['id']);
for (const { id } of tasks) {
this.logger.warn(`Task timed out and was lost: ${id}`);
}
diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md
index 55fb3c94cd..03f564074b 100644
--- a/packages/backend-test-utils/CHANGELOG.md
+++ b/packages/backend-test-utils/CHANGELOG.md
@@ -1,5 +1,23 @@
# @backstage/backend-test-utils
+## 0.1.19
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.11.0
+ - @backstage/cli@0.14.1
+
+## 0.1.18
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/cli@0.14.0
+ - @backstage/backend-common@0.10.8
+ - @backstage/config@0.1.14
+
## 0.1.17
### Patch Changes
diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json
index 8a9767b292..2cc3b8a07b 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.17",
+ "version": "0.1.19",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -10,6 +10,9 @@
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "node-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -22,17 +25,18 @@
],
"license": "Apache-2.0",
"scripts": {
- "build": "backstage-cli build --outputs cjs,types",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/backend-common": "^0.10.7",
- "@backstage/cli": "^0.13.2",
- "@backstage/config": "^0.1.13",
+ "@backstage/backend-common": "^0.11.0",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/config": "^0.1.15",
"@vscode/sqlite3": "^5.0.7",
"knex": "^1.0.2",
"mysql2": "^2.2.5",
@@ -41,7 +45,7 @@
"uuid": "^8.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
+ "@backstage/cli": "^0.14.1",
"jest": "^26.0.1"
},
"files": [
diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md
index d68ec80469..227b8ee231 100644
--- a/packages/backend/CHANGELOG.md
+++ b/packages/backend/CHANGELOG.md
@@ -1,5 +1,120 @@
# example-backend
+## 0.2.66
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.11.0
+ - @backstage/plugin-catalog-backend@0.22.0
+ - @backstage/plugin-scaffolder-backend@0.17.0
+ - @backstage/plugin-graphql-backend@0.1.17
+ - @backstage/plugin-auth-backend@0.11.0
+ - @backstage/plugin-kubernetes-backend@0.4.10
+ - @backstage/plugin-code-coverage-backend@0.1.25
+ - @backstage/plugin-jenkins-backend@0.1.16
+ - @backstage/plugin-tech-insights-backend@0.2.7
+ - @backstage/plugin-todo-backend@0.1.24
+ - @backstage/catalog-model@0.11.0
+ - @backstage/catalog-client@0.7.2
+ - @backstage/plugin-badges-backend@0.1.21
+ - @backstage/backend-tasks@0.1.9
+ - @backstage/plugin-scaffolder-backend-module-rails@0.3.2
+ - @backstage/plugin-techdocs-backend@0.14.0
+ - @backstage/plugin-permission-node@0.5.2
+ - @backstage/integration@0.7.5
+ - example-app@0.2.66
+ - @backstage/plugin-app-backend@0.3.27
+ - @backstage/plugin-auth-node@0.1.3
+ - @backstage/plugin-azure-devops-backend@0.3.6
+ - @backstage/plugin-kafka-backend@0.2.20
+ - @backstage/plugin-permission-backend@0.5.2
+ - @backstage/plugin-proxy-backend@0.2.21
+ - @backstage/plugin-rollbar-backend@0.1.24
+ - @backstage/plugin-search-backend@0.4.5
+ - @backstage/plugin-search-backend-module-pg@0.2.9
+ - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.11
+ - @backstage/plugin-tech-insights-node@0.2.5
+
+## 0.2.66
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.10.9
+ - @backstage/backend-tasks@0.1.8
+ - @backstage/catalog-client@0.7.1
+ - @backstage/catalog-model@0.10.1
+ - @backstage/config@0.1.15
+ - @backstage/integration@0.7.4
+ - @backstage/plugin-app-backend@0.3.26
+ - @backstage/plugin-auth-backend@0.10.2
+ - @backstage/plugin-auth-node@0.1.2
+ - @backstage/plugin-azure-devops-backend@0.3.5
+ - @backstage/plugin-badges-backend@0.1.20
+ - @backstage/plugin-catalog-backend@0.21.5
+ - @backstage/plugin-code-coverage-backend@0.1.24
+ - @backstage/plugin-graphql-backend@0.1.16
+ - @backstage/plugin-jenkins-backend@0.1.15
+ - @backstage/plugin-kafka-backend@0.2.19
+ - @backstage/plugin-kubernetes-backend@0.4.9
+ - @backstage/plugin-permission-backend@0.5.1
+ - @backstage/plugin-permission-common@0.5.1
+ - @backstage/plugin-permission-node@0.5.1
+ - @backstage/plugin-proxy-backend@0.2.20
+ - @backstage/plugin-rollbar-backend@0.1.23
+ - @backstage/plugin-scaffolder-backend@0.16.1
+ - @backstage/plugin-scaffolder-backend-module-rails@0.3.1
+ - @backstage/plugin-search-backend@0.4.4
+ - @backstage/plugin-search-backend-module-elasticsearch@0.0.10
+ - @backstage/plugin-search-backend-module-pg@0.2.8
+ - @backstage/plugin-search-backend-node@0.4.7
+ - @backstage/plugin-tech-insights-backend@0.2.6
+ - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.10
+ - @backstage/plugin-tech-insights-node@0.2.4
+ - @backstage/plugin-techdocs-backend@0.13.5
+ - @backstage/plugin-todo-backend@0.1.23
+
+## 0.2.65
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-techdocs-backend@0.13.4
+ - @backstage/plugin-catalog-backend@0.21.4
+ - @backstage/backend-common@0.10.8
+ - @backstage/catalog-client@0.7.0
+ - @backstage/integration@0.7.3
+ - @backstage/plugin-auth-backend@0.10.1
+ - @backstage/plugin-auth-node@0.1.1
+ - @backstage/plugin-permission-backend@0.5.0
+ - @backstage/plugin-permission-common@0.5.0
+ - @backstage/plugin-rollbar-backend@0.1.22
+ - @backstage/plugin-scaffolder-backend@0.16.0
+ - @backstage/backend-tasks@0.1.7
+ - @backstage/catalog-model@0.10.0
+ - @backstage/config@0.1.14
+ - @backstage/plugin-app-backend@0.3.25
+ - @backstage/plugin-azure-devops-backend@0.3.4
+ - @backstage/plugin-badges-backend@0.1.19
+ - @backstage/plugin-code-coverage-backend@0.1.23
+ - @backstage/plugin-graphql-backend@0.1.15
+ - @backstage/plugin-jenkins-backend@0.1.14
+ - @backstage/plugin-kafka-backend@0.2.18
+ - @backstage/plugin-kubernetes-backend@0.4.8
+ - @backstage/plugin-permission-node@0.5.0
+ - @backstage/plugin-proxy-backend@0.2.19
+ - @backstage/plugin-scaffolder-backend-module-rails@0.3.0
+ - @backstage/plugin-search-backend@0.4.3
+ - @backstage/plugin-search-backend-module-elasticsearch@0.0.9
+ - @backstage/plugin-search-backend-module-pg@0.2.7
+ - @backstage/plugin-search-backend-node@0.4.6
+ - @backstage/plugin-tech-insights-backend@0.2.5
+ - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.9
+ - @backstage/plugin-tech-insights-node@0.2.3
+ - @backstage/plugin-todo-backend@0.1.22
+ - example-app@0.2.65
+
## 0.2.64
### Patch Changes
diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile
index 31231a3a4a..dd35d4ddbc 100644
--- a/packages/backend/Dockerfile
+++ b/packages/backend/Dockerfile
@@ -9,7 +9,7 @@
#
# Once the commands have been run, you can build the image using `yarn build-image`
-FROM node:14-buster-slim
+FROM node:16-bullseye-slim
WORKDIR /app
@@ -19,6 +19,12 @@ WORKDIR /app
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 35b234aeda..cc960e3c24 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -1,10 +1,13 @@
{
"name": "example-backend",
- "version": "0.2.64",
+ "version": "0.2.66",
"main": "dist/index.cjs.js",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": true,
+ "backstage": {
+ "role": "backend"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -15,48 +18,48 @@
"backstage"
],
"scripts": {
- "build": "backstage-cli backend:bundle",
+ "build": "backstage-cli package build",
"build-image": "docker build ../.. -f Dockerfile --tag example-backend",
- "start": "backstage-cli backend:dev",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "clean": "backstage-cli clean",
+ "start": "backstage-cli package start",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "clean": "backstage-cli package clean",
"migrate:create": "knex migrate:make -x ts"
},
"dependencies": {
- "@backstage/backend-common": "^0.10.7",
- "@backstage/backend-tasks": "^0.1.6",
- "@backstage/catalog-client": "^0.6.0",
- "@backstage/catalog-model": "^0.9.10",
- "@backstage/config": "^0.1.13",
- "@backstage/integration": "^0.7.2",
- "@backstage/plugin-app-backend": "^0.3.24",
- "@backstage/plugin-auth-backend": "^0.10.0",
- "@backstage/plugin-auth-node": "^0.1.0",
- "@backstage/plugin-azure-devops-backend": "^0.3.3",
- "@backstage/plugin-badges-backend": "^0.1.18",
- "@backstage/plugin-catalog-backend": "^0.21.3",
- "@backstage/plugin-code-coverage-backend": "^0.1.22",
- "@backstage/plugin-graphql-backend": "^0.1.14",
- "@backstage/plugin-jenkins-backend": "^0.1.13",
- "@backstage/plugin-kubernetes-backend": "^0.4.7",
- "@backstage/plugin-kafka-backend": "^0.2.17",
- "@backstage/plugin-permission-backend": "^0.4.3",
- "@backstage/plugin-permission-common": "^0.4.0",
- "@backstage/plugin-permission-node": "^0.4.3",
- "@backstage/plugin-proxy-backend": "^0.2.18",
- "@backstage/plugin-rollbar-backend": "^0.1.21",
- "@backstage/plugin-scaffolder-backend": "^0.15.24",
- "@backstage/plugin-scaffolder-backend-module-rails": "^0.2.6",
- "@backstage/plugin-search-backend": "^0.4.2",
- "@backstage/plugin-search-backend-node": "^0.4.5",
- "@backstage/plugin-search-backend-module-elasticsearch": "^0.0.8",
- "@backstage/plugin-search-backend-module-pg": "^0.2.6",
- "@backstage/plugin-techdocs-backend": "^0.13.3",
- "@backstage/plugin-tech-insights-backend": "^0.2.4",
- "@backstage/plugin-tech-insights-node": "^0.2.2",
- "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.8",
- "@backstage/plugin-todo-backend": "^0.1.21",
+ "@backstage/backend-common": "^0.11.0",
+ "@backstage/backend-tasks": "^0.1.9",
+ "@backstage/catalog-client": "^0.7.2",
+ "@backstage/catalog-model": "^0.11.0",
+ "@backstage/config": "^0.1.15",
+ "@backstage/integration": "^0.7.5",
+ "@backstage/plugin-app-backend": "^0.3.27",
+ "@backstage/plugin-auth-backend": "^0.11.0",
+ "@backstage/plugin-auth-node": "^0.1.3",
+ "@backstage/plugin-azure-devops-backend": "^0.3.6",
+ "@backstage/plugin-badges-backend": "^0.1.21",
+ "@backstage/plugin-catalog-backend": "^0.22.0",
+ "@backstage/plugin-code-coverage-backend": "^0.1.25",
+ "@backstage/plugin-graphql-backend": "^0.1.17",
+ "@backstage/plugin-jenkins-backend": "^0.1.16",
+ "@backstage/plugin-kubernetes-backend": "^0.4.10",
+ "@backstage/plugin-kafka-backend": "^0.2.20",
+ "@backstage/plugin-permission-backend": "^0.5.2",
+ "@backstage/plugin-permission-common": "^0.5.1",
+ "@backstage/plugin-permission-node": "^0.5.2",
+ "@backstage/plugin-proxy-backend": "^0.2.21",
+ "@backstage/plugin-rollbar-backend": "^0.1.24",
+ "@backstage/plugin-scaffolder-backend": "^0.17.0",
+ "@backstage/plugin-scaffolder-backend-module-rails": "^0.3.2",
+ "@backstage/plugin-search-backend": "^0.4.5",
+ "@backstage/plugin-search-backend-node": "^0.4.7",
+ "@backstage/plugin-search-backend-module-elasticsearch": "^0.0.10",
+ "@backstage/plugin-search-backend-module-pg": "^0.2.9",
+ "@backstage/plugin-techdocs-backend": "^0.14.0",
+ "@backstage/plugin-tech-insights-backend": "^0.2.7",
+ "@backstage/plugin-tech-insights-node": "^0.2.5",
+ "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.11",
+ "@backstage/plugin-todo-backend": "^0.1.24",
"@gitbeaker/node": "^35.1.0",
"@octokit/rest": "^18.5.3",
"@vscode/sqlite3": "^5.0.7",
@@ -73,7 +76,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
+ "@backstage/cli": "^0.14.1",
"@types/dockerode": "^3.3.0",
"@types/express": "^4.17.6",
"@types/express-serve-static-core": "^4.17.5"
diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md
index 664e7a49ed..93f248ff0e 100644
--- a/packages/catalog-client/CHANGELOG.md
+++ b/packages/catalog-client/CHANGELOG.md
@@ -1,5 +1,67 @@
# @backstage/catalog-client
+## 0.7.2
+
+### Patch Changes
+
+- ed09ad8093: Updated usage of the `LocationSpec` type from `@backstage/catalog-model`, which is deprecated.
+- 46dee04eba: Deprecated `AddLocationRequest.presence`, as it is already being ignored.
+- 6e1cbc12a6: Added `CatalogApi.getEntityFacets`. Marking this as a breaking change since it
+ is a non-optional addition to the API and depends on the backend being in place.
+ If you are mocking this interface in your tests, you will need to add an extra
+ `getEntityFacets: jest.fn()` or similar to that interface.
+- Updated dependencies
+ - @backstage/catalog-model@0.11.0
+
+## 0.7.1
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/catalog-model@0.10.1
+ - @backstage/errors@0.2.2
+
+## 0.7.0
+
+### Minor Changes
+
+- 8eda0e7a9c: **BREAKING**: Removed the explicit `DiscoveryApi` and `FetchApi` export symbols,
+ which were unnecessary duplicates from the well known core ones.
+
+ The `CATALOG_FILTER_EXISTS` symbol's value has changed. However, this should not
+ affect any code in practice.
+
+- deaf6065db: Removed `CatalogApi.geLocationByEntity` and `CatalogApi.getOriginLocationByEntity`, and replaced them with `CatalogApi.getLocationByRef`.
+
+ If you were using one of the two old methods, you can update your code as follows:
+
+ ```diff
+ -const originLocation = catalogApi.getOriginLocationByEntity(entity);
+ +const originLocation = catalogApi.getLocationByRef(entity.metadata.annotations[ANNOTATION_ORIGIN_LOCATION]!);
+ -const location = catalogApi.getLocationByEntity(entity);
+ +const location = catalogApi.getLocationByRef(entity.metadata.annotations[ANNOTATION_LOCATION]!);
+ ```
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef`
+- 244d24ebc4: Export the `Location` type that was previously exported by the `@backstage/catalog-model` package.
+- 538ca90790: Deprecated the following types used by the catalog client, and created new
+ corresponding types to make them more consistent:
+
+ - `CatalogEntitiesRequest` -> `GetEntitiesRequest`
+ - `CatalogListResponse` was removed and generally replaced with `GetEntitiesResponse` (which does not use a type parameter argument)
+ - `CatalogEntityAncestorsRequest`-> `GetEntityAncestorsRequest`
+ - `CatalogEntityAncestorsResponse` -> `GetEntityAncestorsResponse`
+
+- 27eccab216: Replaces use of deprecated catalog-model constants.
+- Updated dependencies
+ - @backstage/errors@0.2.1
+ - @backstage/catalog-model@0.10.0
+
## 0.6.0
### Minor Changes
diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md
index 090a1dbcc4..c957859fec 100644
--- a/packages/catalog-client/api-report.md
+++ b/packages/catalog-client/api-report.md
@@ -5,7 +5,6 @@
```ts
import { Entity } from '@backstage/catalog-model';
import { EntityName } from '@backstage/catalog-model';
-import { LocationSpec } from '@backstage/catalog-model';
// @public
export type AddLocationRequest = {
@@ -43,16 +42,16 @@ export interface CatalogApi {
name: EntityName,
options?: CatalogRequestOptions,
): Promise;
- getLocationByEntity(
- entity: Entity,
+ getEntityFacets(
+ request: GetEntityFacetsRequest,
options?: CatalogRequestOptions,
- ): Promise;
+ ): Promise;
getLocationById(
id: string,
options?: CatalogRequestOptions,
): Promise;
- getOriginLocationByEntity(
- entity: Entity,
+ getLocationByRef(
+ locationRef: string,
options?: CatalogRequestOptions,
): Promise;
refreshEntity(
@@ -95,6 +94,11 @@ export class CatalogClient implements CatalogApi {
compoundName: EntityName,
options?: CatalogRequestOptions,
): Promise;
+ getEntityFacets(
+ request: GetEntityFacetsRequest,
+ options?: CatalogRequestOptions,
+ ): Promise;
+ // @deprecated (undocumented)
getLocationByEntity(
entity: Entity,
options?: CatalogRequestOptions,
@@ -103,6 +107,11 @@ export class CatalogClient implements CatalogApi {
id: string,
options?: CatalogRequestOptions,
): Promise;
+ getLocationByRef(
+ locationRef: string,
+ options?: CatalogRequestOptions,
+ ): Promise;
+ // @deprecated (undocumented)
getOriginLocationByEntity(
entity: Entity,
options?: CatalogRequestOptions,
@@ -178,9 +187,32 @@ export interface GetEntityAncestorsResponse {
rootEntityRef: string;
}
+// @public
+export interface GetEntityFacetsRequest {
+ facets: string[];
+ filter?:
+ | Record[]
+ | Record
+ | undefined;
+}
+
+// @public
+export interface GetEntityFacetsResponse {
+ facets: Record<
+ string,
+ Array<{
+ value: string;
+ count: number;
+ }>
+ >;
+}
+
// @public
type Location_2 = {
id: string;
-} & LocationSpec;
+ type: string;
+ target: string;
+ presence?: 'optional' | 'required';
+};
export { Location_2 as Location };
```
diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json
index 3a45a74680..ffcfbc16b7 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": "0.6.0",
+ "version": "0.7.2",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -12,6 +12,9 @@
"module": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "common-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -22,20 +25,20 @@
"backstage"
],
"scripts": {
- "build": "backstage-cli build",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean"
},
"dependencies": {
- "@backstage/catalog-model": "^0.9.10",
- "@backstage/errors": "^0.2.0",
+ "@backstage/catalog-model": "^0.11.0",
+ "@backstage/errors": "^0.2.2",
"cross-fetch": "^3.1.5"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
+ "@backstage/cli": "^0.14.1",
"@types/jest": "^26.0.7",
"msw": "^0.35.0"
},
diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts
index bcf8750658..bb3c9604b3 100644
--- a/packages/catalog-client/src/CatalogClient.ts
+++ b/packages/catalog-client/src/CatalogClient.ts
@@ -36,6 +36,8 @@ import {
GetEntityAncestorsRequest,
GetEntityAncestorsResponse,
Location,
+ GetEntityFacetsRequest,
+ GetEntityFacetsResponse,
} from './types/api';
import { DiscoveryApi } from './types/discovery';
import { FetchApi } from './types/fetch';
@@ -97,14 +99,13 @@ export class CatalogClient implements CatalogApi {
options?: CatalogRequestOptions,
): Promise {
const { filter = [], fields = [], offset, limit, after } = request ?? {};
- const filterItems = [filter].flat();
const params: string[] = [];
// filter param can occur multiple times, for example
// /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'
// the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters
// the "inner array" defined within a `filter` param corresponds to "allOf" filters
- for (const filterItem of filterItems) {
+ for (const filterItem of [filter].flat()) {
const filterParts: string[] = [];
for (const [key, value] of Object.entries(filterItem)) {
for (const v of [value].flat()) {
@@ -207,6 +208,47 @@ export class CatalogClient implements CatalogApi {
}
}
+ /**
+ * {@inheritdoc CatalogApi.getEntityFacets}
+ */
+ async getEntityFacets(
+ request: GetEntityFacetsRequest,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ const { filter = [], facets } = request;
+ const params: string[] = [];
+
+ // filter param can occur multiple times, for example
+ // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'
+ // the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters
+ // the "inner array" defined within a `filter` param corresponds to "allOf" filters
+ for (const filterItem of [filter].flat()) {
+ const filterParts: string[] = [];
+ for (const [key, value] of Object.entries(filterItem)) {
+ for (const v of [value].flat()) {
+ if (v === CATALOG_FILTER_EXISTS) {
+ filterParts.push(encodeURIComponent(key));
+ } else if (typeof v === 'string') {
+ filterParts.push(
+ `${encodeURIComponent(key)}=${encodeURIComponent(v)}`,
+ );
+ }
+ }
+ }
+
+ if (filterParts.length) {
+ params.push(`filter=${filterParts.join(',')}`);
+ }
+ }
+
+ for (const facet of facets) {
+ params.push(`facet=${encodeURIComponent(facet)}`);
+ }
+
+ const query = params.length ? `?${params.join('&')}` : '';
+ return await this.requestOptional('GET', `/entity-facets${query}`, options);
+ }
+
/**
* {@inheritdoc CatalogApi.addLocation}
*/
@@ -246,7 +288,7 @@ export class CatalogClient implements CatalogApi {
}
/**
- * {@inheritdoc CatalogApi.getOriginLocationByEntity}
+ * @deprecated please use getLocationByRef instead
*/
async getOriginLocationByEntity(
entity: Entity,
@@ -268,7 +310,7 @@ export class CatalogClient implements CatalogApi {
}
/**
- * {@inheritdoc CatalogApi.getLocationByEntity}
+ * @deprecated please use getLocationByRef instead
*/
async getLocationByEntity(
entity: Entity,
@@ -288,6 +330,23 @@ export class CatalogClient implements CatalogApi {
.find(l => locationCompound === stringifyLocationRef(l));
}
+ /**
+ * {@inheritdoc CatalogApi.getLocationByRef}
+ */
+ async getLocationByRef(
+ locationRef: string,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ const all: { data: Location }[] = await this.requestRequired(
+ 'GET',
+ '/locations',
+ options,
+ );
+ return all
+ .map(r => r.data)
+ .find(l => locationRef === stringifyLocationRef(l));
+ }
+
/**
* {@inheritdoc CatalogApi.removeLocationById}
*/
diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts
index bf5a7327c6..4a86ca41f3 100644
--- a/packages/catalog-client/src/types/api.ts
+++ b/packages/catalog-client/src/types/api.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { Entity, EntityName, LocationSpec } from '@backstage/catalog-model';
+import { Entity, EntityName } from '@backstage/catalog-model';
/**
* This symbol can be used in place of a value when passed to filters in e.g.
@@ -142,6 +142,90 @@ export interface GetEntityAncestorsResponse {
}>;
}
+/**
+ * The request type for {@link CatalogClient.getEntityFacets}.
+ *
+ * @public
+ */
+export interface GetEntityFacetsRequest {
+ /**
+ * If given, return only entities that match the given patterns.
+ *
+ * @remarks
+ *
+ * If multiple filter sets are given as an array, then there is effectively an
+ * OR between each filter set.
+ *
+ * Within one filter set, there is effectively an AND between the various
+ * keys.
+ *
+ * Within one key, if there are more than one value, then there is effectively
+ * an OR between them.
+ *
+ * Example: For an input of
+ *
+ * ```
+ * [
+ * { kind: ['API', 'Component'] },
+ * { 'metadata.name': 'a', 'metadata.namespace': 'b' }
+ * ]
+ * ```
+ *
+ * This effectively means
+ *
+ * ```
+ * (kind = EITHER 'API' OR 'Component')
+ * OR
+ * (metadata.name = 'a' AND metadata.namespace = 'b' )
+ * ```
+ *
+ * Each key is a dot separated path in each object.
+ *
+ * As a value you can also pass in the symbol `CATALOG_FILTER_EXISTS`
+ * (exported from this package), which means that you assert on the existence
+ * of that key, no matter what its value is.
+ */
+ filter?:
+ | Record[]
+ | Record
+ | undefined;
+ /**
+ * Dot separated paths for the facets to extract from each entity.
+ *
+ * @remarks
+ *
+ * Example: For an input of `['kind', 'metadata.annotations.backstage.io/orphan']`, then the
+ * response will be shaped like
+ *
+ * ```
+ * {
+ * "facets": {
+ * "kind": [
+ * { "key": "Component", "count": 22 },
+ * { "key": "API", "count": 13 }
+ * ],
+ * "metadata.annotations.backstage.io/orphan": [
+ * { "key": "true", "count": 2 }
+ * ]
+ * }
+ * }
+ * ```
+ */
+ facets: string[];
+}
+
+/**
+ * The response type for {@link CatalogClient.getEntityFacets}.
+ *
+ * @public
+ */
+export interface GetEntityFacetsResponse {
+ /**
+ * The computed facets, one entry per facet in the request.
+ */
+ facets: Record>;
+}
+
/**
* Options you can pass into a catalog request for additional information.
*
@@ -158,7 +242,11 @@ export interface CatalogRequestOptions {
*/
export type Location = {
id: string;
-} & LocationSpec;
+ type: string;
+ target: string;
+ /** @deprecated This field is is ignored */
+ presence?: 'optional' | 'required';
+};
/**
* The request type for {@link CatalogClient.addLocation}.
@@ -169,6 +257,7 @@ export type AddLocationRequest = {
type?: string;
target: string;
dryRun?: boolean;
+ /** @deprecated This field is is ignored */
presence?: 'optional' | 'required';
};
@@ -248,6 +337,17 @@ export interface CatalogApi {
options?: CatalogRequestOptions,
): Promise;
+ /**
+ * Gets a summary of field facets of entities in the catalog.
+ *
+ * @param request - Request parameters
+ * @param options - Additional options
+ */
+ getEntityFacets(
+ request: GetEntityFacetsRequest,
+ options?: CatalogRequestOptions,
+ ): Promise;
+
// Locations
/**
@@ -262,24 +362,13 @@ export interface CatalogApi {
): Promise;
/**
- * Gets origin location by Entity.
+ * Gets a registered location by its ref.
*
- * @param entity - An {@link catalog-model#Entity}.
+ * @param locationRef - A location ref, e.g. "url:https://github.com/..."
* @param options - Additional options
*/
- getOriginLocationByEntity(
- entity: Entity,
- options?: CatalogRequestOptions,
- ): Promise;
-
- /**
- * Gets Location by Entity.
- *
- * @param entity - An {@link catalog-model#Entity}.
- * @param options - Additional options
- */
- getLocationByEntity(
- entity: Entity,
+ getLocationByRef(
+ locationRef: string,
options?: CatalogRequestOptions,
): Promise;
diff --git a/packages/catalog-client/src/types/index.ts b/packages/catalog-client/src/types/index.ts
index 580bb7330d..39c8962b68 100644
--- a/packages/catalog-client/src/types/index.ts
+++ b/packages/catalog-client/src/types/index.ts
@@ -25,6 +25,8 @@ export type {
GetEntityAncestorsRequest,
GetEntityAncestorsResponse,
Location,
+ GetEntityFacetsRequest,
+ GetEntityFacetsResponse,
} from './api';
-export { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from './status';
export * from './deprecated';
+export { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from './status';
diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md
index 9dbf2f116b..cbb2e681bf 100644
--- a/packages/catalog-model/CHANGELOG.md
+++ b/packages/catalog-model/CHANGELOG.md
@@ -1,5 +1,86 @@
# @backstage/catalog-model
+## 0.11.0
+
+### Minor Changes
+
+- 919cf2f836: **BREAKING**: Added `EntityRelation.targetRef` (a string form entity ref), and
+ deprecated `EntityRelation.target` (a kind + namespace + name object). This
+ aligns the type with our goal of using string form entity refs more coherently.
+ There will be a period of time when both fields need to be present, which may in
+ particular affect your tests which now have to list both the string form and the
+ object form side by side.
+
+ ```diff
+ const mockEntity: Entity = {
+ kind: 'Component',
+ relations: [
+ {
+ type: RELATION_MEMBER_OF,
+ + targetRef: 'component:default/foo',
+ target: { kind: 'component', namespace: 'default', name: 'foo' }
+ }
+ ]
+ ```
+
+ The `target` field will be entirely removed from this type in a future release.
+
+- 7010349c9a: **BREAKING**: Removed `EntityRelationSpec` as it is only used during the catalog during the catalog processing.
+- 68f0871b76: **BREAKING**: Simplified the `parseEntityRef` function to _always_ either return
+ a complete `EntityName`, complete with both kind, namespace and name, or throw
+ an error if it for some reason did not have enough information to form that
+ result. This makes its usage and its type declaration vastly simpler.
+
+### Patch Changes
+
+- ed09ad8093: Deprecated the `LocationSpec` export, which should now be imported from `@backstage/plugin-catalog-backend` instead.
+- b5c02d10a6: Remove all usage of the deprecated `ENTITY_DEFAULT_NAMESPACE`
+- 67a7c02d26: **DEPRECATED**: The `EntityRef` type and `parseEntityName` function are now
+ deprecated, and will soon be removed. This is part of a larger movement toward
+ fixing the poorly named `EntityName` type which should instead have been named
+ `EntityRef`. Please remove any usage of these as soon as possible.
+- da44c47f43: Deprecated the `entity.metadata.generation` as the field has never been fully functioning.
+
+## 0.10.1
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/config@0.1.15
+ - @backstage/errors@0.2.2
+ - @backstage/types@0.1.3
+
+## 0.10.0
+
+### Minor Changes
+
+- e483dd6c72: **BREAKING**: Remove deprecated validation methods `analyzeLocationSchema`, `locationSchema` and `locationSpecSchema`.
+ This functionality was primarily used internally by the `catalog-backend`.
+- edbc03814a: **BREAKING**: Remove deprecated `serializeEntityRef` which is replaced by `stringifyEntityRef`.
+- e72d371296: **BREAKING**: Removed `TemplateEntityV1beta2` from the model and moved it to
+ `@backstage/plugin-scaffolder-common` where `TemplateEntityV1beta3` already
+ lived. It has also been marked as deprecated in the process - please consider
+ [migrating to `v1beta3` templates](https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3).
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- 216725b434: Deprecated `parseLocationReference` and `stringifyLocationReference`,
+ introducing `parseLocationRef` and `stringifyLocationRef` in their place.
+- 244d24ebc4: Deprecates the `Location` type export from this package. Imports of the `Location` type should now be done from the `@backstage/catalog-client` package instead.
+- 7aeb491394: Deprecated `ENTITY_DEFAULT_NAMESPACE` constant in favour of `DEFAULT_NAMESPACE`.
+- 0d03e42a89: Deprecated `compareEntityToRef` due to low usage and provided value.
+- e8c6f9d282: Deprecated the `EntityRefContext` type which had limited use.
+- 7f21538c9e: Deprecated `JSONSchema` export type.
+- 20f3244102: Deprecates the following exports which all have very limited and internal use. `ENTITY_META_GENERATED_FIELDS`, `entityHasChanges`, `generateEntityEtag`, `generateEntityUid`, `generateUpdatedEntity`, `ENTITY_META_GENERATED_FIELDS`.
+- 27eccab216: Deprecates `EDIT_URL_ANNOTATION`, `LOCATION_ANNOTATION`, `ORIGIN_LOCATION_ANNOTATION`, `SOURCE_LOCATION_ANNOTATION`, `VIEW_URL_ANNOTATION`
+ and replaces these constants all prefixed with ANNOTATION\_ `ANNOTATION_EDIT_URL`, `ANNOTATION_LOCATION`, `ANNOTATION_ORIGIN_LOCATION`, `ANNOTATION_SOURCE_LOCATION`, `ANNOTATION_VIEW_URL`
+- Updated dependencies
+ - @backstage/errors@0.2.1
+ - @backstage/config@0.1.14
+ - @backstage/types@0.1.2
+
## 0.9.10
### Patch Changes
diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md
index 10ef63388b..210d0187e2 100644
--- a/packages/catalog-model/api-report.md
+++ b/packages/catalog-model/api-report.md
@@ -69,7 +69,14 @@ export class CommonValidatorFunctions {
// @public @deprecated
export function compareEntityToRef(
entity: Entity,
- ref: EntityRef | EntityName,
+ ref:
+ | string
+ | {
+ kind?: string;
+ namespace?: string;
+ name: string;
+ }
+ | EntityName,
context?: {
defaultKind?: string;
defaultNamespace?: string;
@@ -212,7 +219,7 @@ export type EntityPolicy = {
enforce(entity: Entity): Promise;
};
-// @public
+// @public @deprecated
export type EntityRef =
| string
| {
@@ -231,13 +238,7 @@ export type EntityRefContext = {
export type EntityRelation = {
type: string;
target: EntityName;
-};
-
-// @public
-export type EntityRelationSpec = {
- source: EntityName;
- type: string;
- target: EntityName;
+ targetRef: string;
};
// @public
@@ -311,7 +312,7 @@ export { GroupEntityV1alpha1 };
// @public
export const groupEntityV1alpha1Validator: KindValidator;
-// @public
+// @public @deprecated
export type JSONSchema = JSONSchema7 & {
[key in string]?: JsonValue;
};
@@ -370,7 +371,7 @@ export { LocationEntityV1alpha1 };
// @public
export const locationEntityV1alpha1Validator: KindValidator;
-// @public
+// @public @deprecated
export type LocationSpec = {
type: string;
target: string;
@@ -391,9 +392,15 @@ export class NoForeignRootFieldsEntityPolicy implements EntityPolicy {
export const ORIGIN_LOCATION_ANNOTATION =
'backstage.io/managed-by-origin-location';
-// @public
+// @public @deprecated
export function parseEntityName(
- ref: EntityRef,
+ ref:
+ | string
+ | {
+ kind?: string;
+ namespace?: string;
+ name: string;
+ },
context?: {
defaultKind?: string;
defaultNamespace?: string;
@@ -402,37 +409,19 @@ export function parseEntityName(
// @public
export function parseEntityRef(
- ref: EntityRef,
+ ref:
+ | string
+ | {
+ kind?: string;
+ namespace?: string;
+ name: string;
+ },
context?: {
- defaultKind: string;
- defaultNamespace: string;
+ defaultKind?: string;
+ defaultNamespace?: string;
},
): EntityName;
-// @public
-export function parseEntityRef(
- ref: EntityRef,
- context?: {
- defaultKind: string;
- },
-): {
- kind: string;
- namespace?: string;
- name: string;
-};
-
-// @public
-export function parseEntityRef(
- ref: EntityRef,
- context?: {
- defaultNamespace: string;
- },
-): {
- kind?: string;
- namespace: string;
- name: string;
-};
-
// @public
export function parseLocationRef(ref: string): {
type: string;
@@ -558,33 +547,6 @@ export { SystemEntityV1alpha1 };
// @public
export const systemEntityV1alpha1Validator: KindValidator;
-// @public
-export interface TemplateEntityV1beta2 extends Entity {
- // (undocumented)
- apiVersion: 'backstage.io/v1beta2';
- // (undocumented)
- kind: 'Template';
- // (undocumented)
- spec: {
- type: string;
- parameters?: JsonObject | JsonObject[];
- steps: Array<{
- id?: string;
- name?: string;
- action: string;
- input?: JsonObject;
- if?: string | boolean;
- }>;
- output?: {
- [name: string]: string;
- };
- owner?: string;
- };
-}
-
-// @public
-export const templateEntityV1beta2Validator: KindValidator;
-
// @public
interface UserEntityV1alpha1 extends Entity {
// (undocumented)
diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json
index 62e577df4a..70ed0fbe4d 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": "0.9.10",
+ "version": "0.11.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -13,6 +13,9 @@
"types": "dist/index.d.ts",
"alphaTypes": "dist/index.alpha.d.ts"
},
+ "backstage": {
+ "role": "common-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -23,17 +26,17 @@
"backstage"
],
"scripts": {
- "build": "backstage-cli build --experimental-type-build",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build --experimental-type-build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean"
},
"dependencies": {
- "@backstage/config": "^0.1.13",
- "@backstage/errors": "^0.2.0",
- "@backstage/types": "^0.1.1",
+ "@backstage/config": "^0.1.15",
+ "@backstage/errors": "^0.2.2",
+ "@backstage/types": "^0.1.3",
"@types/json-schema": "^7.0.5",
"ajv": "^7.0.3",
"json-schema": "^0.4.0",
@@ -41,7 +44,7 @@
"uuid": "^8.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0",
+ "@backstage/cli": "^0.14.1",
"@types/jest": "^26.0.7",
"@types/lodash": "^4.14.151",
"yaml": "^1.9.2"
diff --git a/packages/catalog-model/src/entity/Entity.ts b/packages/catalog-model/src/entity/Entity.ts
index f56774025c..ef9b4352da 100644
--- a/packages/catalog-model/src/entity/Entity.ts
+++ b/packages/catalog-model/src/entity/Entity.ts
@@ -116,6 +116,7 @@ export type EntityMeta = JsonObject & {
* This field can not be set by the user at creation time, and the server
* will reject an attempt to do so. The field will be populated in read
* operations.
+ * @deprecated field is not supported.
*/
generation?: number;
@@ -197,30 +198,15 @@ export type EntityRelation = {
/**
* The target entity of this relation.
+ *
+ * @deprecated use targetRef instead
*/
target: EntityName;
-};
-
-/**
- * Holds the relation data for entities.
- *
- * @public
- */
-export type EntityRelationSpec = {
- /**
- * The source entity of this relation.
- */
- source: EntityName;
/**
- * The type of the relation.
+ * The entity ref of the target of this relation.
*/
- type: string;
-
- /**
- * The target entity of this relation.
- */
- target: EntityName;
+ targetRef: string;
};
/**
diff --git a/packages/catalog-model/src/entity/index.ts b/packages/catalog-model/src/entity/index.ts
index 938bdb2b9b..f619d0f39e 100644
--- a/packages/catalog-model/src/entity/index.ts
+++ b/packages/catalog-model/src/entity/index.ts
@@ -29,7 +29,6 @@ export type {
EntityLink,
EntityMeta,
EntityRelation,
- EntityRelationSpec,
} from './Entity';
export type { EntityEnvelope } from './EntityEnvelope';
export type {
diff --git a/packages/catalog-model/src/entity/policies/DefaultNamespaceEntityPolicy.test.ts b/packages/catalog-model/src/entity/policies/DefaultNamespaceEntityPolicy.test.ts
index 55188d84c8..b92abb0fc2 100644
--- a/packages/catalog-model/src/entity/policies/DefaultNamespaceEntityPolicy.test.ts
+++ b/packages/catalog-model/src/entity/policies/DefaultNamespaceEntityPolicy.test.ts
@@ -15,7 +15,7 @@
*/
import yaml from 'yaml';
-import { ENTITY_DEFAULT_NAMESPACE } from '../constants';
+import { DEFAULT_NAMESPACE } from '../constants';
import { DefaultNamespaceEntityPolicy } from './DefaultNamespaceEntityPolicy';
describe('DefaultNamespaceEntityPolicy', () => {
@@ -57,7 +57,7 @@ describe('DefaultNamespaceEntityPolicy', () => {
expect.objectContaining({
metadata: {
name: 'my-component-yay',
- namespace: ENTITY_DEFAULT_NAMESPACE,
+ namespace: DEFAULT_NAMESPACE,
},
}),
);
diff --git a/packages/catalog-model/src/entity/policies/DefaultNamespaceEntityPolicy.ts b/packages/catalog-model/src/entity/policies/DefaultNamespaceEntityPolicy.ts
index 9511dfb05f..5f6efc03dc 100644
--- a/packages/catalog-model/src/entity/policies/DefaultNamespaceEntityPolicy.ts
+++ b/packages/catalog-model/src/entity/policies/DefaultNamespaceEntityPolicy.ts
@@ -16,7 +16,7 @@
import lodash from 'lodash';
import { EntityPolicy } from './types';
-import { ENTITY_DEFAULT_NAMESPACE } from '../constants';
+import { DEFAULT_NAMESPACE } from '../constants';
import { Entity } from '../Entity';
/**
@@ -27,7 +27,7 @@ import { Entity } from '../Entity';
export class DefaultNamespaceEntityPolicy implements EntityPolicy {
private readonly namespace: string;
- constructor(namespace: string = ENTITY_DEFAULT_NAMESPACE) {
+ constructor(namespace: string = DEFAULT_NAMESPACE) {
this.namespace = namespace;
}
diff --git a/packages/catalog-model/src/entity/ref.test.ts b/packages/catalog-model/src/entity/ref.test.ts
index f80b588d55..b0c7068fae 100644
--- a/packages/catalog-model/src/entity/ref.test.ts
+++ b/packages/catalog-model/src/entity/ref.test.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { ENTITY_DEFAULT_NAMESPACE } from './constants';
+import { DEFAULT_NAMESPACE } from './constants';
import { Entity } from './Entity';
import { compareEntityToRef, parseEntityName, parseEntityRef } from './ref';
@@ -29,7 +29,7 @@ describe('ref', () => {
expect(() => parseEntityName('b/c')).toThrow(/kind/);
expect(parseEntityName('a:c')).toEqual({
kind: 'a',
- namespace: ENTITY_DEFAULT_NAMESPACE,
+ namespace: DEFAULT_NAMESPACE,
name: 'c',
});
expect(() => parseEntityName('c')).toThrow(/kind/);
@@ -118,7 +118,7 @@ describe('ref', () => {
).toEqual({ kind: 'a', namespace: 'y', name: 'c' });
expect(parseEntityName('a:c', { defaultKind: 'x' })).toEqual({
kind: 'a',
- namespace: ENTITY_DEFAULT_NAMESPACE,
+ namespace: DEFAULT_NAMESPACE,
name: 'c',
});
expect(
@@ -126,7 +126,7 @@ describe('ref', () => {
).toEqual({ kind: 'x', namespace: 'y', name: 'c' });
expect(parseEntityName('c', { defaultKind: 'x' })).toEqual({
kind: 'x',
- namespace: ENTITY_DEFAULT_NAMESPACE,
+ namespace: DEFAULT_NAMESPACE,
name: 'c',
});
});
@@ -152,7 +152,7 @@ describe('ref', () => {
).toEqual({ kind: 'a', namespace: 'y', name: 'c' });
expect(
parseEntityName({ kind: 'a', name: 'c' }, { defaultKind: 'x' }),
- ).toEqual({ kind: 'a', namespace: ENTITY_DEFAULT_NAMESPACE, name: 'c' });
+ ).toEqual({ kind: 'a', namespace: DEFAULT_NAMESPACE, name: 'c' });
expect(
parseEntityName(
{ name: 'c' },
@@ -161,7 +161,7 @@ describe('ref', () => {
).toEqual({ kind: 'x', namespace: 'y', name: 'c' });
expect(parseEntityName({ name: 'c' }, { defaultKind: 'x' })).toEqual({
kind: 'x',
- namespace: ENTITY_DEFAULT_NAMESPACE,
+ namespace: DEFAULT_NAMESPACE,
name: 'c',
});
// empty strings are errors, not defaults
@@ -187,19 +187,9 @@ describe('ref', () => {
namespace: 'b',
name: 'c',
});
- expect(parseEntityRef('b/c')).toEqual({
- kind: undefined,
- namespace: 'b',
- name: 'c',
- });
expect(parseEntityRef('a:c')).toEqual({
kind: 'a',
- namespace: undefined,
- name: 'c',
- });
- expect(parseEntityRef('c')).toEqual({
- kind: undefined,
- namespace: undefined,
+ namespace: 'default',
name: 'c',
});
});
diff --git a/packages/catalog-model/src/entity/ref.ts b/packages/catalog-model/src/entity/ref.ts
index 122fe0b31a..66974f5a01 100644
--- a/packages/catalog-model/src/entity/ref.ts
+++ b/packages/catalog-model/src/entity/ref.ts
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-import { EntityName, EntityRef } from '../types';
-import { ENTITY_DEFAULT_NAMESPACE } from './constants';
+import { DEFAULT_NAMESPACE } from './constants';
+import { EntityName } from '../types';
import { Entity } from './Entity';
function parseRefString(ref: string): {
@@ -48,7 +48,7 @@ function parseRefString(ref: string): {
export function getEntityName(entity: Entity): EntityName {
return {
kind: entity.kind,
- namespace: entity.metadata.namespace || ENTITY_DEFAULT_NAMESPACE,
+ namespace: entity.metadata.namespace || DEFAULT_NAMESPACE,
name: entity.metadata.name,
};
}
@@ -76,13 +76,14 @@ export type EntityRefContext = {
* otherwise specified as part of the options, and will throw an error if no
* kind was specified in the input reference and no default kind was given.
*
+ * @deprecated Please use parseEntityRef instead
* @public
* @param ref - The reference to parse
* @param context - The context of defaults that the parsing happens within
* @returns A complete entity name
*/
export function parseEntityName(
- ref: EntityRef,
+ ref: string | { kind?: string; namespace?: string; name: string },
context: {
/** The default kind, if none is given in the reference */
defaultKind?: string;
@@ -91,7 +92,7 @@ export function parseEntityName(
} = {},
): EntityName {
const { kind, namespace, name } = parseEntityRef(ref, {
- defaultNamespace: ENTITY_DEFAULT_NAMESPACE,
+ defaultNamespace: DEFAULT_NAMESPACE,
...context,
});
@@ -119,80 +120,52 @@ export function parseEntityName(
* @returns The compound form of the reference
*/
export function parseEntityRef(
- ref: EntityRef,
- context?: { defaultKind: string; defaultNamespace: string },
-): EntityName;
-/**
- * parseEntityRef with optional Kind.
- *
- * @public
- */
-export function parseEntityRef(
- ref: EntityRef,
- context?: { defaultKind: string },
-): {
- kind: string;
- namespace?: string;
- name: string;
-};
-/**
- * parseEntityRef with optional Namespace.
- *
- * @public
- */
-export function parseEntityRef(
- ref: EntityRef,
- context?: { defaultNamespace: string },
-): {
- kind?: string;
- namespace: string;
- name: string;
-};
-/**
- * parseEntityRef with optional Kind and Namespace.
- *
- * @public
- */
-export function parseEntityRef(
- ref: EntityRef,
- context: {
+ ref: string | { kind?: string; namespace?: string; name: string },
+ context?: {
/** The default kind, if none is given in the reference */
defaultKind?: string;
/** The default namespace, if none is given in the reference */
defaultNamespace?: string;
- } = {},
-): {
- kind?: string;
- namespace?: string;
- name: string;
-} {
+ },
+): EntityName {
if (!ref) {
throw new Error(`Entity reference must not be empty`);
}
+ const defaultKind = context?.defaultKind;
+ const defaultNamespace = context?.defaultNamespace || DEFAULT_NAMESPACE;
+
+ let kind: string | undefined;
+ let namespace: string | undefined;
+ let name: string | undefined;
+
if (typeof ref === 'string') {
const parsed = parseRefString(ref);
- return {
- kind: parsed.kind ?? context.defaultKind,
- namespace: parsed.namespace ?? context.defaultNamespace,
- name: parsed.name,
- };
+ kind = parsed.kind ?? defaultKind;
+ namespace = parsed.namespace ?? defaultNamespace;
+ name = parsed.name;
+ } else {
+ kind = ref.kind ?? defaultKind;
+ namespace = ref.namespace ?? defaultNamespace;
+ name = ref.name;
}
- const { kind, namespace, name } = ref;
- if (kind === '') {
- throw new Error('Entity reference kinds must not be empty');
- } else if (namespace === '') {
- throw new Error('Entity reference namespaces must not be empty');
+ if (!kind) {
+ const textual = JSON.stringify(ref);
+ throw new Error(
+ `Entity reference ${textual} had missing or empty kind (e.g. did not start with "component:" or similar)`,
+ );
+ } else if (!namespace) {
+ const textual = JSON.stringify(ref);
+ throw new Error(
+ `Entity reference ${textual} had missing or empty namespace`,
+ );
} else if (!name) {
- throw new Error('Entity references must contain a name');
+ const textual = JSON.stringify(ref);
+ throw new Error(`Entity reference ${textual} had missing or empty name`);
}
- return {
- kind: kind ?? context.defaultKind,
- namespace: namespace ?? context.defaultNamespace,
- name,
- };
+ return { kind, namespace, name };
}
/**
@@ -218,11 +191,11 @@ export function stringifyEntityRef(
if ('metadata' in ref) {
kind = ref.kind;
- namespace = ref.metadata.namespace ?? ENTITY_DEFAULT_NAMESPACE;
+ namespace = ref.metadata.namespace ?? DEFAULT_NAMESPACE;
name = ref.metadata.name;
} else {
kind = ref.kind;
- namespace = ref.namespace ?? ENTITY_DEFAULT_NAMESPACE;
+ namespace = ref.namespace ?? DEFAULT_NAMESPACE;
name = ref.name;
}
@@ -249,7 +222,10 @@ export function stringifyEntityRef(
*/
export function compareEntityToRef(
entity: Entity,
- ref: EntityRef | EntityName,
+ ref:
+ | string
+ | { kind?: string; namespace?: string; name: string }
+ | EntityName,
context?: {
/** The default kind, if none is given in the reference */
defaultKind?: string;
@@ -258,7 +234,7 @@ export function compareEntityToRef(
},
): boolean {
const entityKind = entity.kind;
- const entityNamespace = entity.metadata.namespace || ENTITY_DEFAULT_NAMESPACE;
+ const entityNamespace = entity.metadata.namespace || DEFAULT_NAMESPACE;
const entityName = entity.metadata.name;
let refKind: string | undefined;
@@ -268,12 +244,12 @@ export function compareEntityToRef(
const parsed = parseRefString(ref);
refKind = parsed.kind || context?.defaultKind;
refNamespace =
- parsed.namespace || context?.defaultNamespace || ENTITY_DEFAULT_NAMESPACE;
+ parsed.namespace || context?.defaultNamespace || DEFAULT_NAMESPACE;
refName = parsed.name;
} else {
refKind = ref.kind || context?.defaultKind;
refNamespace =
- ref.namespace || context?.defaultNamespace || ENTITY_DEFAULT_NAMESPACE;
+ ref.namespace || context?.defaultNamespace || DEFAULT_NAMESPACE;
refName = ref.name;
}
diff --git a/packages/catalog-model/src/kinds/index.ts b/packages/catalog-model/src/kinds/index.ts
index be9f7a0d6a..7211c25a8d 100644
--- a/packages/catalog-model/src/kinds/index.ts
+++ b/packages/catalog-model/src/kinds/index.ts
@@ -50,8 +50,6 @@ export type {
SystemEntityV1alpha1 as SystemEntity,
SystemEntityV1alpha1,
} from './SystemEntityV1alpha1';
-export { templateEntityV1beta2Validator } from './TemplateEntityV1beta2';
-export type { TemplateEntityV1beta2 } from './TemplateEntityV1beta2';
export type { KindValidator } from './types';
export { userEntityV1alpha1Validator } from './UserEntityV1alpha1';
export type {
diff --git a/packages/catalog-model/src/location/helpers.ts b/packages/catalog-model/src/location/helpers.ts
index d308c00449..7c73908157 100644
--- a/packages/catalog-model/src/location/helpers.ts
+++ b/packages/catalog-model/src/location/helpers.ts
@@ -21,9 +21,6 @@ import { ANNOTATION_LOCATION } from './annotation';
/**
* Parses a string form location reference.
*
- * Note that the return type is not `LocationSpec`, because we do not want to
- * conflate the string form with the additional properties of that type.
- *
* @public
* @param ref - A string-form location reference, e.g. `'url:https://host'`
* @returns A location reference, e.g. `{ type: 'url', target: 'https://host' }`
@@ -36,11 +33,6 @@ export function parseLocationReference(ref: string) {
/**
* Parses a string form location reference.
*
- * @remarks
- *
- * Note that the return type is not `LocationSpec`, because we do not want to
- * conflate the string form with the additional properties of that type.
- *
* @public
* @param ref - A string-form location ref, e.g. `'url:https://host'`
* @returns A location ref, e.g. `{ type: 'url', target: 'https://host' }`
@@ -83,11 +75,6 @@ export function parseLocationRef(ref: string): {
/**
* Turns a location reference into its string form.
*
- * @remarks
- *
- * Note that the input type is not `LocationSpec`, because we do not want to
- * conflate the string form with the additional properties of that type.
- *
* @public
* @param ref - A location reference, e.g. `{ type: 'url', target: 'https://host' }`
* @returns A string-form location reference, e.g. `'url:https://host'`
@@ -103,11 +90,6 @@ export function stringifyLocationReference(ref: {
/**
* Turns a location ref into its string form.
*
- * @remarks
- *
- * Note that the input type is not `LocationSpec`, because we do not want to
- * conflate the string form with the additional properties of that type.
- *
* @public
* @param ref - A location ref, e.g. `{ type: 'url', target: 'https://host' }`
* @returns A string-form location ref, e.g. `'url:https://host'`
diff --git a/packages/catalog-model/src/location/types.ts b/packages/catalog-model/src/location/types.ts
index 2ed8fd717b..9b87e4919d 100644
--- a/packages/catalog-model/src/location/types.ts
+++ b/packages/catalog-model/src/location/types.ts
@@ -24,6 +24,7 @@
* default value: 'required'.
*
* @public
+ * @deprecated Import from `@backstage/plugin-catalog-backend` instead.
*/
export type LocationSpec = {
type: string;
diff --git a/packages/catalog-model/src/schema/EntityMeta.schema.json b/packages/catalog-model/src/schema/EntityMeta.schema.json
index c834bfb113..7b2b9d3f82 100644
--- a/packages/catalog-model/src/schema/EntityMeta.schema.json
+++ b/packages/catalog-model/src/schema/EntityMeta.schema.json
@@ -38,7 +38,8 @@
"type": "integer",
"description": "A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations.",
"examples": [1],
- "minimum": 1
+ "minimum": 1,
+ "deprecated": true
},
"name": {
"type": "string",
diff --git a/packages/catalog-model/src/types.ts b/packages/catalog-model/src/types.ts
index 1a0fab267c..13550968be 100644
--- a/packages/catalog-model/src/types.ts
+++ b/packages/catalog-model/src/types.ts
@@ -21,6 +21,7 @@ import { JSONSchema7 } from 'json-schema';
* JSONSchema extendable by arbitrary JSON attributes
*
* @public
+ * @deprecated use JSONSchema7 from the json-schema package instead.
*/
export type JSONSchema = JSONSchema7 & { [key in string]?: JsonValue };
@@ -39,6 +40,7 @@ export type EntityName = {
* A reference by name to an entity, either as a compact string representation,
* or as a compound reference structure.
*
+ * @deprecated Please use string directly, or EntityName (depending on what you actually need)
* @remarks
*
* The string representation is on the form `[:][/]`.
diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md
index e588c02edf..c890e44b29 100644
--- a/packages/cli-common/CHANGELOG.md
+++ b/packages/cli-common/CHANGELOG.md
@@ -1,5 +1,17 @@
# @backstage/cli-common
+## 0.1.8
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+
+## 0.1.7
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+
## 0.1.6
### Patch Changes
diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json
index cdb4b01b6d..3b05e93603 100644
--- a/packages/cli-common/package.json
+++ b/packages/cli-common/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/cli-common",
"description": "Common functionality used by cli, backend, and create-app",
- "version": "0.1.6",
+ "version": "0.1.8",
"private": false,
"main": "src/index.ts",
"types": "src/index.ts",
@@ -10,6 +10,9 @@
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "node-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,12 +24,13 @@
],
"license": "Apache-2.0",
"scripts": {
- "build": "backstage-cli build --outputs cjs,types",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"devDependencies": {
"@types/jest": "^26.0.7",
diff --git a/packages/cli/.snyk b/packages/cli/.snyk
index 3ad43bd3de..0a32a6ac12 100644
--- a/packages/cli/.snyk
+++ b/packages/cli/.snyk
@@ -3,80 +3,65 @@ version: v1.22.1
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
ignore:
SNYK-JS-ANSIHTML-1296849:
- - 'webpack-dev-server > ansi-html':
+ - webpack-dev-server > ansi-html:
reason: Developer tools are not a valid target for ReDoS attacks
expires: 2022-03-06T17:18:55.019Z
created: 2021-09-06T17:18:55.027Z
-
SNYK-JS-ANSIREGEX-1583908:
- '*':
reason: Developer tools are not a valid target for ReDoS attacks
expires: 2022-03-06T17:18:55.019Z
created: 2021-09-06T17:18:55.027Z
-
SNYK-JS-CSSWHAT-1298035:
- '*':
reason: Developer tools are not a valid target for ReDoS attacks
expires: 2022-03-06T17:18:55.019Z
created: 2021-09-06T17:18:55.027Z
-
SNYK-JS-BROWSERSLIST-1090194:
- '*':
reason: Developer tools are not a valid target for ReDoS attacks
expires: 2022-03-06T17:18:55.019Z
created: 2021-09-06T17:18:55.027Z
-
SNYK-JS-ISSVG-1243891:
- '*':
reason: Developer tools are not a valid target for ReDoS attacks
expires: 2022-03-06T17:18:55.019Z
created: 2021-09-06T17:18:55.027Z
-
SNYK-JS-ISSVG-1085627:
- '*':
reason: Developer tools are not a valid target for ReDoS attacks
expires: 2022-03-06T17:18:55.019Z
created: 2021-09-06T17:18:55.027Z
-
SNYK-JS-POSTCSS-1255640:
- '*':
reason: Developer tools are not a valid target for ReDoS attacks
expires: 2022-03-06T17:18:55.019Z
created: 2021-09-06T17:18:55.027Z
-
SNYK-JS-POSTCSS-1090595:
- '*':
reason: Developer tools are not a valid target for ReDoS attacks
expires: 2022-03-06T17:18:55.019Z
created: 2021-09-06T17:18:55.027Z
-
SNYK-JS-WS-1296835:
- '*':
reason: Developer tools are not a valid target for ReDoS attacks
expires: 2022-03-06T17:18:55.019Z
created: 2021-09-06T17:18:55.027Z
-
- SNYK-JS-IMMER-1540542:
- - '*':
- reason: Prototype pollution is not an effective attack against a CLI as it already executes arbitrary code
- expires: 2022-03-06T17:18:55.019Z
- created: 2021-09-06T17:18:55.027Z
-
- SNYK-JS-SETVALUE-1540541:
- - '*':
- reason: Prototype pollution is not an effective attack against a CLI as it already executes arbitrary code
- expires: 2022-03-06T17:18:55.019Z
- created: 2021-09-06T17:18:55.027Z
-
'snyk:lic:npm:rollup-plugin-dts:LGPL-3.0':
- '*':
- reason: Backstage itself does not redistribute this dependency in minified form
+ reason: This is a development dependency only and is therefore acceptable
expires: 2031-09-06T17:18:55.027Z
created: 2021-09-06T17:18:55.027Z
-
'snyk:lic:npm:axe-core:MPL-2.0':
- '*':
- reason: Backstage itself does not redistribute this dependency in minified form
+ reason: This is a development dependency only and is therefore acceptable
expires: 2031-09-06T17:18:55.027Z
created: 2021-09-06T17:18:55.027Z
+ SNYK-JS-UNSETVALUE-2400660:
+ - '*':
+ reason: >-
+ The pollution in this vulnerability does not allow injection of
+ arbitrary values and is therefore a negligible risk for a CLI.
+ expires: 2022-08-17T21:54:43.658Z
+ created: 2022-02-15T21:54:43.668Z
patch: {}
diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md
index 37bea1e016..46b67615c4 100644
--- a/packages/cli/CHANGELOG.md
+++ b/packages/cli/CHANGELOG.md
@@ -1,5 +1,61 @@
# @backstage/cli
+## 0.14.1
+
+### Patch Changes
+
+- 5cc7f48400: Fixed a bug in the built-in Jest configuration that prevented it from identifying packages that had migrated to using the new package scripts to run tests.
+- 49ae6c9573: chore(deps-dev): bump `@types/rollup-plugin-postcss` from 2.0.1 to 3.1.4
+- d64b8d3678: chore(deps): bump `minimatch` from 3.0.4 to 5.0.0
+- d2e9d2a34f: chore(deps): bump `@hot-loader/react-dom` from 16.13.0 to 17.0.2
+- c2f3a548cf: Fix building of backends with `repo build --all`, where it would previously only work if the build was executed within the backend package.
+- 3d7ed5377a: Ignore setupTests and the file inside ./dev folder recursively. Eslint
+ can not resolve relative paths as we defined in the rule import/no-extraneous-dependencies, and it does not apply this rule.
+
+ A downside to use a recursive definition would be to checking all `dev` folders, which might not be wanted. Ensure you don't use
+ the `dev` folder out of scope (must be used for dev. env. only)
+
+- Updated dependencies
+ - @backstage/config-loader@0.9.6
+
+## 0.14.0
+
+### Minor Changes
+
+- 1fc0cd3896: Bumped Webpack and Rollup `svgr` dependencies and updated the AST template for `.icon.svg` modules. This means that SVG icon imports are now using SVGO v2.
+
+### Patch Changes
+
+- 0b74c72987: Added a new experimental and hidden `backstage-cli repo lint` command that can be used to lint all packages in the project, similar to `lerna run lint`.
+- 532dae9c4c: The `versions:bump --release next` command is updated to compare the `main` and `next` release manifests and prefer the latest.
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- 22862486de: The `versions:bump` command now filters out `npm_` environment configuration when running `yarn install`. This has the effect of allowing it to consider local configuration files within the repository, which is the behavior that one would expect.
+- 22862486de: The `versions:bump` command now also considers the root `package.json` when searching for updates. It has also received updates to its output, including a link the [Backstage upgrade helper](https://backstage.github.io/upgrade-helper) and silenced `yarn install` output.
+- 7410e12268: Several changes were made to the new experimental package roles system. Unless you have been experimenting with using this new system, these changes have no affect on your project.
+
+ Renamed the `backstage-cli migrate package-role` command to `backstage-cli migrate package-roles`.
+
+ Updated the package role definitions by renaming `app` to `frontend`, `plugin-frontend` to `frontend-plugin`, `plugin-frontend-module` to `frontend-plugin-module`, `plugin-backend` to `backend-plugin`, and `plugin-backend-module` to `backend-plugin-module`
+
+ The `backstage-cli migrate package-scripts` received several tweaks to make it more accurate. It now tries to maintain existing script arguments, like `--config` parameters for `build` and `start` scripts.
+
+ The `script` command category has been renamed to `package`.
+
+ The `backstage-cli package build` command set an incorrect target directory for `app` and `backend` packages, which has been fixed.
+
+ The `backend:bundle` and `repo build` command for the `backend` role was previously ignoring building of bundled packages that had migrated to use package roles and the standard build script, this has now been fixed.
+
+- c6bbafb516: Updated the default [sucrase](https://github.com/alangpierce/sucrase)-based Jest transform to include source maps if the environment variable `ENABLE_SOURCE_MAPS` is non-empty. This can be used to better support editor test debugging integrations.
+- 7410e12268: The `test` command now automatically adds `--passWithNoTests` to the Jest invocation. To revert this behavior, pass `--passWithNoTests=false` or `--no-passWithNoTests`.
+- Updated dependencies
+ - @backstage/config-loader@0.9.4
+ - @backstage/errors@0.2.1
+ - @backstage/release-manifests@0.0.2
+ - @backstage/cli-common@0.1.7
+ - @backstage/config@0.1.14
+ - @backstage/types@0.1.2
+
## 0.13.2
### Patch Changes
diff --git a/packages/cli/config/eslint.js b/packages/cli/config/eslint.js
index 06f22933e8..5555dad451 100644
--- a/packages/cli/config/eslint.js
+++ b/packages/cli/config/eslint.js
@@ -55,8 +55,8 @@ module.exports = {
devDependencies: [
'**/*.test.*',
'**/*.stories.*',
- 'src/setupTests.*',
- 'dev/**',
+ '**/src/setupTests.*',
+ '**/dev/**',
],
optionalDependencies: true,
peerDependencies: true,
diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js
index 91cdd3c41b..d5b85b9748 100644
--- a/packages/cli/config/jest.js
+++ b/packages/cli/config/jest.js
@@ -175,7 +175,10 @@ async function getRootConfig() {
// script to determine whether a given package should be tested
const packageData = await fs.readJson(packagePath);
const testScript = packageData.scripts && packageData.scripts.test;
- if (testScript && testScript.includes('backstage-cli test')) {
+ const isSupportedTestScript =
+ testScript?.includes('backstage-cli test') ||
+ testScript?.includes('backstage-cli package test');
+ if (testScript && isSupportedTestScript) {
return await getProjectConfig(projectPath, packageData.name);
}
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 589ac58646..b17d517ba1 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,11 +1,14 @@
{
"name": "@backstage/cli",
"description": "CLI for developing Backstage plugins and apps",
- "version": "0.13.2",
+ "version": "0.14.1",
"private": false,
"publishConfig": {
"access": "public"
},
+ "backstage": {
+ "role": "cli"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -18,23 +21,23 @@
"license": "Apache-2.0",
"main": "dist/index.cjs.js",
"scripts": {
- "build": "backstage-cli build --outputs cjs",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "clean": "backstage-cli clean",
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "clean": "backstage-cli package clean",
"start": "nodemon --"
},
"bin": {
"backstage-cli": "bin/backstage-cli"
},
"dependencies": {
- "@backstage/cli-common": "^0.1.6",
- "@backstage/config": "^0.1.13",
- "@backstage/config-loader": "^0.9.3",
- "@backstage/errors": "^0.2.0",
- "@backstage/release-manifests": "^0.0.1",
- "@backstage/types": "^0.1.1",
- "@hot-loader/react-dom": "^16.13.0",
+ "@backstage/cli-common": "^0.1.8",
+ "@backstage/config": "^0.1.15",
+ "@backstage/config-loader": "^0.9.6",
+ "@backstage/errors": "^0.2.2",
+ "@backstage/release-manifests": "^0.0.2",
+ "@backstage/types": "^0.1.3",
+ "@hot-loader/react-dom": "^17.0.2",
"@manypkg/get-packages": "^1.1.3",
"@octokit/request": "^5.4.12",
"@rollup/plugin-commonjs": "^21.0.1",
@@ -48,8 +51,8 @@
"@sucrase/webpack-loader": "^2.0.0",
"@svgr/plugin-jsx": "6.2.x",
"@svgr/plugin-svgo": "6.2.x",
- "@svgr/rollup": "5.5.x",
- "@svgr/webpack": "5.5.x",
+ "@svgr/rollup": "6.2.x",
+ "@svgr/webpack": "6.2.x",
"@types/webpack-env": "^1.15.2",
"@typescript-eslint/eslint-plugin": "^5.9.0",
"@typescript-eslint/parser": "^5.9.0",
@@ -85,7 +88,7 @@
"json-schema": "^0.4.0",
"jest-transform-yaml": "^1.0.0",
"lodash": "^4.17.21",
- "minimatch": "3.0.4",
+ "minimatch": "5.0.0",
"mini-css-extract-plugin": "^2.4.2",
"npm-packlist": "^3.0.0",
"node-libs-browser": "^2.2.1",
@@ -118,14 +121,14 @@
"zod": "^3.11.6"
},
"devDependencies": {
- "@backstage/backend-common": "^0.10.7",
- "@backstage/config": "^0.1.13",
- "@backstage/core-components": "^0.8.8",
- "@backstage/core-plugin-api": "^0.6.0",
- "@backstage/core-app-api": "^0.5.2",
- "@backstage/dev-utils": "^0.2.21",
- "@backstage/test-utils": "^0.2.4",
- "@backstage/theme": "^0.2.14",
+ "@backstage/backend-common": "^0.11.0",
+ "@backstage/config": "^0.1.15",
+ "@backstage/core-components": "^0.8.10",
+ "@backstage/core-plugin-api": "^0.7.0",
+ "@backstage/core-app-api": "^0.5.4",
+ "@backstage/dev-utils": "^0.2.23",
+ "@backstage/test-utils": "^0.2.6",
+ "@backstage/theme": "^0.2.15",
"@types/diff": "^5.0.0",
"@types/express": "^4.17.6",
"@types/fs-extra": "^9.0.1",
@@ -137,7 +140,8 @@
"@types/npm-packlist": "^1.1.2",
"@types/recursive-readdir": "^2.2.0",
"@types/rollup-plugin-peer-deps-external": "^2.2.0",
- "@types/rollup-plugin-postcss": "^2.0.0",
+ "@types/rollup-plugin-postcss": "^3.1.4",
+ "@types/svgo": "^2.6.2",
"@types/tar": "^6.1.1",
"@types/terser-webpack-plugin": "^5.0.4",
"@types/yarnpkg__lockfile": "^1.1.4",
diff --git a/packages/cli/src/commands/build/buildBackend.ts b/packages/cli/src/commands/build/buildBackend.ts
index e32b7956db..d7c4f72dbe 100644
--- a/packages/cli/src/commands/build/buildBackend.ts
+++ b/packages/cli/src/commands/build/buildBackend.ts
@@ -35,7 +35,10 @@ export async function buildBackend(options: BuildBackendOptions) {
const pkg = await fs.readJson(resolvePath(targetDir, 'package.json'));
// We build the target package without generating type declarations.
- await buildPackage({ outputs: new Set([Output.cjs]) });
+ await buildPackage({
+ targetDir: options.targetDir,
+ outputs: new Set([Output.cjs]),
+ });
const tmpDir = await fs.mkdtemp(resolvePath(os.tmpdir(), 'backstage-bundle'));
try {
@@ -49,19 +52,20 @@ export async function buildBackend(options: BuildBackendOptions) {
// We built the target backend package using the regular build process, but the result of
// that has now been packed into the dist workspace, so clean up the dist dir.
- await fs.remove(targetDir);
- await fs.mkdir(targetDir);
+ const distDir = resolvePath(targetDir, 'dist');
+ await fs.remove(distDir);
+ await fs.mkdir(distDir);
// Move out skeleton.tar.gz before we create the main bundle, no point having that included up twice.
await fs.move(
resolvePath(tmpDir, SKELETON_FILE),
- resolvePath(targetDir, SKELETON_FILE),
+ resolvePath(distDir, SKELETON_FILE),
);
// Create main bundle.tar.gz, with some tweaks to make it more likely hit Docker build cache.
await tar.create(
{
- file: resolvePath(targetDir, BUNDLE_FILE),
+ file: resolvePath(distDir, BUNDLE_FILE),
cwd: tmpDir,
portable: true,
noMtime: true,
diff --git a/packages/cli/src/commands/build/buildApp.ts b/packages/cli/src/commands/build/buildFrontend.ts
similarity index 95%
rename from packages/cli/src/commands/build/buildApp.ts
rename to packages/cli/src/commands/build/buildFrontend.ts
index b0959b2d6a..6d7ca2e6a9 100644
--- a/packages/cli/src/commands/build/buildApp.ts
+++ b/packages/cli/src/commands/build/buildFrontend.ts
@@ -26,7 +26,7 @@ interface BuildAppOptions {
configPaths: string[];
}
-export async function buildApp(options: BuildAppOptions) {
+export async function buildFrontend(options: BuildAppOptions) {
const { targetDir, writeStats, configPaths } = options;
const { name } = await fs.readJson(resolvePath(targetDir, 'package.json'));
await buildBundle({
diff --git a/packages/cli/src/commands/build/command.ts b/packages/cli/src/commands/build/command.ts
index 1189883b12..5c8065dbb4 100644
--- a/packages/cli/src/commands/build/command.ts
+++ b/packages/cli/src/commands/build/command.ts
@@ -18,22 +18,22 @@ import { Command } from 'commander';
import { buildPackage, Output } from '../../lib/builder';
import { findRoleFromCommand, getRoleInfo } from '../../lib/role';
import { paths } from '../../lib/paths';
-import { buildApp } from './buildApp';
+import { buildFrontend } from './buildFrontend';
import { buildBackend } from './buildBackend';
export async function command(cmd: Command): Promise {
const role = await findRoleFromCommand(cmd);
- if (role === 'app') {
- return buildApp({
- targetDir: paths.resolveTarget('dist'),
+ if (role === 'frontend') {
+ return buildFrontend({
+ targetDir: paths.targetDir,
configPaths: cmd.config as string[],
writeStats: Boolean(cmd.stats),
});
}
if (role === 'backend') {
return buildBackend({
- targetDir: paths.resolveTarget('dist'),
+ targetDir: paths.targetDir,
skipBuildDependencies: Boolean(cmd.skipBuildDependencies),
});
}
diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts
index 6f534d3e62..d3baa37b3f 100644
--- a/packages/cli/src/commands/index.ts
+++ b/packages/cli/src/commands/index.ts
@@ -61,14 +61,17 @@ export function registerRepoCommand(program: CommanderStatic) {
export function registerScriptCommand(program: CommanderStatic) {
const command = program
- .command('script [command]', { hidden: true })
- .description('Lifecycle scripts for Backstage packages [EXPERIMENTAL]');
+ .command('package [command]', { hidden: true })
+ .description('Lifecycle scripts for individual packages [EXPERIMENTAL]');
command
.command('start')
.description('Start a package for local development')
.option(...configOption)
- .option('--role ', 'Run the command with an explicit package role')
+ .option(
+ '--role ',
+ 'Run the command with an explicit package role [EXPERIMENTAL]',
+ )
.option('--check', 'Enable type checking and linting if available')
.option('--inspect', 'Enable debugger in Node.js environments')
.option(
@@ -80,6 +83,10 @@ export function registerScriptCommand(program: CommanderStatic) {
command
.command('build')
.description('Build a package for production deployment or publishing')
+ .option(
+ '--role ',
+ 'Run the command with an explicit package role [EXPERIMENTAL]',
+ )
.option(
'--minify',
'Minify the generated code. Does not apply to app or backend packages.',
@@ -104,7 +111,7 @@ export function registerScriptCommand(program: CommanderStatic) {
)
.action(lazy(() => import('./build').then(m => m.command)));
- program
+ command
.command('lint')
.option(
'--format ',
@@ -115,7 +122,7 @@ export function registerScriptCommand(program: CommanderStatic) {
.description('Lint a package')
.action(lazy(() => import('./lint').then(m => m.default)));
- program
+ command
.command('test')
.allowUnknownOption(true) // Allows the command to run, but we still need to parse raw args
.helpOption(', --backstage-cli-help') // Let Jest handle help
@@ -144,7 +151,7 @@ export function registerMigrateCommand(program: CommanderStatic) {
.description('Migration utilities [EXPERIMENTAL]');
command
- .command('package-role')
+ .command('package-roles')
.description(`Add package role field to packages that don't have it`)
.action(lazy(() => import('./migrate/packageRole').then(m => m.default)));
@@ -157,7 +164,7 @@ export function registerMigrateCommand(program: CommanderStatic) {
}
export function registerCommands(program: CommanderStatic) {
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('app:build')
.description('Build an app for a production release')
@@ -165,7 +172,7 @@ export function registerCommands(program: CommanderStatic) {
.option(...configOption)
.action(lazy(() => import('./app/build').then(m => m.default)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('app:serve')
.description('Serve an app for local development')
@@ -173,7 +180,7 @@ export function registerCommands(program: CommanderStatic) {
.option(...configOption)
.action(lazy(() => import('./app/serve').then(m => m.default)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('backend:build')
.description('Build a backend plugin')
@@ -181,7 +188,7 @@ export function registerCommands(program: CommanderStatic) {
.option('--experimental-type-build', 'Enable experimental type build')
.action(lazy(() => import('./backend/build').then(m => m.default)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('backend:bundle')
.description('Bundle the backend into a deployment archive')
@@ -191,7 +198,7 @@ export function registerCommands(program: CommanderStatic) {
)
.action(lazy(() => import('./backend/bundle').then(m => m.default)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('backend:dev')
.description('Start local development server with HMR for the backend')
@@ -240,7 +247,7 @@ export function registerCommands(program: CommanderStatic) {
lazy(() => import('./create-plugin/createPlugin').then(m => m.default)),
);
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('plugin:build')
.description('Build a plugin')
@@ -248,7 +255,7 @@ export function registerCommands(program: CommanderStatic) {
.option('--experimental-type-build', 'Enable experimental type build')
.action(lazy(() => import('./plugin/build').then(m => m.default)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('plugin:serve')
.description('Serves the dev/ folder of a plugin')
@@ -263,7 +270,7 @@ export function registerCommands(program: CommanderStatic) {
.description('Diff an existing plugin with the creation template')
.action(lazy(() => import('./plugin/diff').then(m => m.default)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('build')
.description('Build a package for publishing')
@@ -272,7 +279,7 @@ export function registerCommands(program: CommanderStatic) {
.option('--experimental-type-build', 'Enable experimental type build')
.action(lazy(() => import('./oldBuild').then(m => m.default)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('lint')
.option(
@@ -284,7 +291,7 @@ export function registerCommands(program: CommanderStatic) {
.description('Lint a package')
.action(lazy(() => import('./lint').then(m => m.default)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('test')
.allowUnknownOption(true) // Allows the command to run, but we still need to parse raw args
@@ -370,19 +377,19 @@ export function registerCommands(program: CommanderStatic) {
.description('Check Backstage package versioning')
.action(lazy(() => import('./versions/lint').then(m => m.default)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('prepack')
.description('Prepares a package for packaging before publishing')
.action(lazy(() => import('./pack').then(m => m.pre)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('postpack')
.description('Restores the changes made by the prepack command')
.action(lazy(() => import('./pack').then(m => m.post)));
- // TODO(Rugvip): Deprecate in favor of script variant
+ // TODO(Rugvip): Deprecate in favor of package variant
program
.command('clean')
.description('Delete cache directories')
diff --git a/packages/cli/src/commands/migrate/packageScripts.ts b/packages/cli/src/commands/migrate/packageScripts.ts
index a3fdd20018..c7dab9466b 100644
--- a/packages/cli/src/commands/migrate/packageScripts.ts
+++ b/packages/cli/src/commands/migrate/packageScripts.ts
@@ -19,6 +19,8 @@ import { resolve as resolvePath } from 'path';
import { PackageGraph } from '../../lib/monorepo';
import { getRoleFromPackage, getRoleInfo, PackageRole } from '../../lib/role';
+const configArgPattern = /--config[=\s][^\s$]+/;
+
const noStartRoles: PackageRole[] = ['cli', 'common-library'];
export async function command() {
@@ -33,17 +35,52 @@ export async function command() {
const roleInfo = getRoleInfo(role);
const hasStart = !noStartRoles.includes(role);
- const isBundled = roleInfo.output.includes('bundle');
+ const needsPack = !(roleInfo.output.includes('bundle') || role === 'cli');
+ const scripts = packageJson.scripts ?? {};
+
+ const startCmd = ['start'];
+ if (scripts.start?.includes('--check')) {
+ startCmd.push('--check');
+ }
+ if (scripts.start?.includes('--config')) {
+ startCmd.push(...(scripts.start.match(configArgPattern) ?? []));
+ }
+
+ const buildCmd = ['build'];
+ if (scripts.build?.includes('--minify')) {
+ buildCmd.push('--minify');
+ }
+ if (scripts.build?.includes('--experimental-type-build')) {
+ buildCmd.push('--experimental-type-build');
+ }
+ if (scripts.build?.includes('--config')) {
+ buildCmd.push(...(scripts.build.match(configArgPattern) ?? []));
+ }
+
+ // For test scripts we keep all existing flags except for --passWithNoTests, since that's now default
+ const testCmd = ['test'];
+ if (scripts.test?.startsWith('backstage-cli test')) {
+ const args = scripts.test
+ .slice('backstage-cli test'.length)
+ .split(' ')
+ .filter(Boolean);
+ if (args.includes('--passWithNoTests')) {
+ args.splice(args.indexOf('--passWithNoTests'), 1);
+ }
+ testCmd.push(...args);
+ }
const expectedScripts = {
- ...(hasStart && { start: 'backstage-cli script start' }),
- build: 'backstage-cli script build',
- lint: 'backstage-cli script lint',
- test: 'backstage-cli script test',
- clean: 'backstage-cli script clean',
- ...(!isBundled && {
- postpack: 'backstage-cli script postpack',
- prepack: 'backstage-cli script prepack',
+ ...(hasStart && {
+ start: `backstage-cli package ${startCmd.join(' ')}`,
+ }),
+ build: `backstage-cli package ${buildCmd.join(' ')}`,
+ lint: 'backstage-cli package lint',
+ test: `backstage-cli package ${testCmd.join(' ')}`,
+ clean: 'backstage-cli package clean',
+ ...(needsPack && {
+ postpack: 'backstage-cli package postpack',
+ prepack: 'backstage-cli package prepack',
}),
};
@@ -52,7 +89,12 @@ export async function command() {
(packageJson.scripts = packageJson.scripts || {});
for (const [name, value] of Object.entries(expectedScripts)) {
- if (currentScripts[name] !== value) {
+ const currentScript = currentScripts[name];
+
+ const isMissing = !currentScript;
+ const isDifferent = currentScript !== value;
+ const isBackstageScript = currentScript?.includes('backstage-cli');
+ if (isMissing || (isDifferent && isBackstageScript)) {
changed = true;
currentScripts[name] = value;
}
diff --git a/packages/cli/src/commands/repo/build.ts b/packages/cli/src/commands/repo/build.ts
index 9c32386304..ceb468ebfa 100644
--- a/packages/cli/src/commands/repo/build.ts
+++ b/packages/cli/src/commands/repo/build.ts
@@ -23,7 +23,7 @@ import { ExtendedPackage } from '../../lib/monorepo/PackageGraph';
import { runParallelWorkers } from '../../lib/parallel';
import { paths } from '../../lib/paths';
import { detectRoleFromPackage } from '../../lib/role';
-import { buildApp } from '../build/buildApp';
+import { buildFrontend } from '../build/buildFrontend';
import { buildBackend } from '../build/buildBackend';
function createScriptOptionsParser(anyCmd: Command, commandPath: string[]) {
@@ -43,7 +43,9 @@ function createScriptOptionsParser(anyCmd: Command, commandPath: string[]) {
}
if (!targetCmd) {
- throw new Error(`Could not find script command '${commandPath.join(' ')}'`);
+ throw new Error(
+ `Could not find package command '${commandPath.join(' ')}'`,
+ );
}
const cmd = targetCmd;
@@ -80,7 +82,7 @@ export async function command(cmd: Command): Promise {
const apps = new Array();
const backends = new Array();
- const parseBuildScript = createScriptOptionsParser(cmd, ['script', 'build']);
+ const parseBuildScript = createScriptOptionsParser(cmd, ['package', 'build']);
const options = packages.flatMap(pkg => {
const role =
@@ -90,7 +92,7 @@ export async function command(cmd: Command): Promise {
return [];
}
- if (role === 'app') {
+ if (role === 'frontend') {
apps.push(pkg);
return [];
} else if (role === 'backend') {
@@ -137,7 +139,7 @@ export async function command(cmd: Command): Promise {
);
return;
}
- await buildApp({
+ await buildFrontend({
targetDir: pkg.dir,
configPaths: (buildOptions.config as string[]) ?? [],
writeStats: Boolean(buildOptions.stats),
diff --git a/packages/cli/src/commands/start/command.ts b/packages/cli/src/commands/start/command.ts
index 6615d5fd46..7a11028800 100644
--- a/packages/cli/src/commands/start/command.ts
+++ b/packages/cli/src/commands/start/command.ts
@@ -31,19 +31,19 @@ export async function command(cmd: Command): Promise {
switch (role) {
case 'backend':
- case 'plugin-backend':
- case 'plugin-backend-module':
+ case 'backend-plugin':
+ case 'backend-plugin-module':
case 'node-library':
return startBackend(options);
- case 'app':
+ case 'frontend':
return startFrontend({
...options,
entry: 'src/index',
verifyVersions: true,
});
case 'web-library':
- case 'plugin-frontend':
- case 'plugin-frontend-module':
+ case 'frontend-plugin':
+ case 'frontend-plugin-module':
return startFrontend({ entry: 'dev/index', ...options });
default:
throw new Error(
diff --git a/packages/cli/src/commands/testCommand.ts b/packages/cli/src/commands/testCommand.ts
index 24a4e06f9e..7165b20925 100644
--- a/packages/cli/src/commands/testCommand.ts
+++ b/packages/cli/src/commands/testCommand.ts
@@ -29,7 +29,11 @@ function includesAnyOf(hayStack: string[], ...needles: string[]) {
export default async (cmd: Command) => {
// all args are forwarded to jest
- const rawArgs = cmd.parent.rawArgs as string[];
+ let parent = cmd;
+ while (parent.parent) {
+ parent = parent.parent;
+ }
+ const rawArgs = parent.rawArgs as string[];
const args = rawArgs.slice(rawArgs.indexOf('test') + 1);
// Only include our config if caller isn't passing their own config
@@ -37,6 +41,10 @@ export default async (cmd: Command) => {
args.push('--config', paths.resolveOwn('config/jest.js'));
}
+ if (!includesAnyOf(args, '--no-passWithNoTests', '--passWithNoTests=false')) {
+ args.push('--passWithNoTests');
+ }
+
// Run in watch mode unless in CI, coverage mode, or running all tests
if (
!process.env.CI &&
diff --git a/packages/cli/src/lib/diff/handlers.ts b/packages/cli/src/lib/diff/handlers.ts
index 5bd90e3d22..55e9cddd3d 100644
--- a/packages/cli/src/lib/diff/handlers.ts
+++ b/packages/cli/src/lib/diff/handlers.ts
@@ -173,6 +173,14 @@ class PackageJsonHandler {
return;
}
+ // Skip diffing package scripts that have been migrated to the new commands
+ const hasNewScript = Object.values(targetScripts).some(script =>
+ String(script).includes('backstage-cli package '),
+ );
+ if (hasNewScript) {
+ return;
+ }
+
for (const key of Object.keys(pkgScripts)) {
await this.syncField(key, pkgScripts, targetScripts, 'scripts');
}
diff --git a/packages/cli/src/lib/monorepo/PackageGraph.ts b/packages/cli/src/lib/monorepo/PackageGraph.ts
index a1f77299df..4bbb9eac67 100644
--- a/packages/cli/src/lib/monorepo/PackageGraph.ts
+++ b/packages/cli/src/lib/monorepo/PackageGraph.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { relative as relativePath, posix as posixPath } from 'path';
+import path from 'path';
import { getPackages, Package } from '@manypkg/get-packages';
import { paths } from '../paths';
import { PackageRole } from '../role';
@@ -166,8 +166,11 @@ export class PackageGraph extends Map {
const dirMap = new Map(
Array.from(this.values()).map(pkg => [
- posixPath.normalize(relativePath(paths.targetRoot, pkg.dir)) +
- posixPath.sep,
+ // relative from root, convert to posix, and add a / at the end
+ path
+ .relative(paths.targetRoot, pkg.dir)
+ .split(path.sep)
+ .join(path.posix.sep) + path.posix.sep,
pkg,
]),
);
diff --git a/packages/cli/src/lib/packager/createDistWorkspace.ts b/packages/cli/src/lib/packager/createDistWorkspace.ts
index 15ccda30c2..bce6c5c14c 100644
--- a/packages/cli/src/lib/packager/createDistWorkspace.ts
+++ b/packages/cli/src/lib/packager/createDistWorkspace.ts
@@ -38,6 +38,7 @@ import {
Output,
} from '../builder';
import { copyPackageDist } from './copyPackageDist';
+import { getRoleInfo } from '../role';
// These packages aren't safe to pack in parallel since the CLI depends on them
const UNSAFE_PACKAGES = [
@@ -131,7 +132,9 @@ export async function createDistWorkspace(
}
const role = pkg.packageJson.backstage?.role;
if (!role) {
- console.warn(`Ignored ${pkg.packageJson.name} because it has no role`);
+ console.warn(
+ `Building ${pkg.packageJson.name} separately because it has no role`,
+ );
customBuild.push(pkg.packageJson.name);
continue;
}
@@ -142,9 +145,17 @@ export async function createDistWorkspace(
continue;
}
- if (!buildScript.startsWith('backstage-cli script build')) {
+ if (!buildScript.startsWith('backstage-cli package build')) {
console.warn(
- `Ignored ${pkg.packageJson.name} because it has a custom build script, '${buildScript}'`,
+ `Building ${pkg.packageJson.name} separately because it has a custom build script, '${buildScript}'`,
+ );
+ customBuild.push(pkg.packageJson.name);
+ continue;
+ }
+
+ if (getRoleInfo(role).output.includes('bundle')) {
+ console.warn(
+ `Building ${pkg.packageJson.name} separately because it is a bundled package`,
);
customBuild.push(pkg.packageJson.name);
continue;
@@ -216,7 +227,7 @@ export async function createDistWorkspace(
const FAST_PACK_SCRIPTS = [
undefined,
'backstage-cli prepack',
- 'backstage-cli script prepack',
+ 'backstage-cli package prepack',
];
async function moveToDistWorkspace(
diff --git a/packages/cli/src/lib/role/packageRoles.test.ts b/packages/cli/src/lib/role/packageRoles.test.ts
index f6c9fb418a..759be462d2 100644
--- a/packages/cli/src/lib/role/packageRoles.test.ts
+++ b/packages/cli/src/lib/role/packageRoles.test.ts
@@ -31,8 +31,8 @@ describe('getRoleInfo', () => {
output: ['types', 'esm'],
});
- expect(getRoleInfo('app')).toEqual({
- role: 'app',
+ expect(getRoleInfo('frontend')).toEqual({
+ role: 'frontend',
platform: 'web',
output: ['bundle'],
});
@@ -56,10 +56,10 @@ describe('getRoleFromPackage', () => {
expect(
getRoleFromPackage({
backstage: {
- role: 'app',
+ role: 'frontend',
},
}),
- ).toEqual('app');
+ ).toEqual('frontend');
expect(() =>
getRoleFromPackage({
@@ -135,7 +135,7 @@ describe('detectRoleFromPackage', () => {
'cy:run': 'cypress run',
},
}),
- ).toEqual('app');
+ ).toEqual('frontend');
});
it('detects the role of example-backend', () => {
@@ -180,7 +180,7 @@ describe('detectRoleFromPackage', () => {
clean: 'backstage-cli clean',
},
}),
- ).toEqual('plugin-frontend');
+ ).toEqual('frontend-plugin');
});
it('detects the role of @backstage/plugin-catalog-backend', () => {
@@ -204,7 +204,7 @@ describe('detectRoleFromPackage', () => {
clean: 'backstage-cli clean',
},
}),
- ).toEqual('plugin-backend');
+ ).toEqual('backend-plugin');
});
it('detects the role of @backstage/plugin-catalog-react', () => {
@@ -274,7 +274,7 @@ describe('detectRoleFromPackage', () => {
clean: 'backstage-cli clean',
},
}),
- ).toEqual('plugin-backend-module');
+ ).toEqual('backend-plugin-module');
});
it('detects the role of @backstage/plugin-permission-node', () => {
@@ -323,6 +323,6 @@ describe('detectRoleFromPackage', () => {
clean: 'backstage-cli clean',
},
}),
- ).toEqual('plugin-frontend-module');
+ ).toEqual('frontend-plugin-module');
});
});
diff --git a/packages/cli/src/lib/role/packageRoles.ts b/packages/cli/src/lib/role/packageRoles.ts
index 7c855ee0fd..a33a7d715a 100644
--- a/packages/cli/src/lib/role/packageRoles.ts
+++ b/packages/cli/src/lib/role/packageRoles.ts
@@ -22,7 +22,7 @@ import { PackageRole, PackageRoleInfo } from './types';
const packageRoleInfos: PackageRoleInfo[] = [
{
- role: 'app',
+ role: 'frontend',
platform: 'web',
output: ['bundle'],
},
@@ -52,22 +52,22 @@ const packageRoleInfos: PackageRoleInfo[] = [
output: ['types', 'esm', 'cjs'],
},
{
- role: 'plugin-frontend',
+ role: 'frontend-plugin',
platform: 'web',
output: ['types', 'esm'],
},
{
- role: 'plugin-frontend-module',
+ role: 'frontend-plugin-module',
platform: 'web',
output: ['types', 'esm'],
},
{
- role: 'plugin-backend',
+ role: 'backend-plugin',
platform: 'node',
output: ['types', 'cjs'],
},
{
- role: 'plugin-backend-module',
+ role: 'backend-plugin-module',
platform: 'node',
output: ['types', 'cjs'],
},
@@ -147,22 +147,22 @@ export function detectRoleFromPackage(
const pkg = detectionSchema.parse(pkgJson);
if (pkg.scripts?.start?.includes('app:serve')) {
- return 'app';
+ return 'frontend';
}
if (pkg.scripts?.build?.includes('backend:bundle')) {
return 'backend';
}
if (pkg.name?.includes('plugin-') && pkg.name?.includes('-backend-module-')) {
- return 'plugin-backend-module';
+ return 'backend-plugin-module';
}
if (pkg.name?.includes('plugin-') && pkg.name?.includes('-module-')) {
- return 'plugin-frontend-module';
+ return 'frontend-plugin-module';
}
if (pkg.scripts?.start?.includes('plugin:serve')) {
- return 'plugin-frontend';
+ return 'frontend-plugin';
}
if (pkg.scripts?.start?.includes('backend:dev')) {
- return 'plugin-backend';
+ return 'backend-plugin';
}
const mainEntry = pkg.publishConfig?.main || pkg.main;
diff --git a/packages/cli/src/lib/role/types.ts b/packages/cli/src/lib/role/types.ts
index 6a89f7bdaf..a3961544f4 100644
--- a/packages/cli/src/lib/role/types.ts
+++ b/packages/cli/src/lib/role/types.ts
@@ -15,16 +15,16 @@
*/
export type PackageRole =
- | 'app'
+ | 'frontend'
| 'backend'
| 'cli'
| 'web-library'
| 'node-library'
| 'common-library'
- | 'plugin-frontend'
- | 'plugin-frontend-module'
- | 'plugin-backend'
- | 'plugin-backend-module';
+ | 'frontend-plugin'
+ | 'frontend-plugin-module'
+ | 'backend-plugin'
+ | 'backend-plugin-module';
export type PackagePlatform = 'node' | 'web' | 'common';
export type PackageOutputType = 'bundle' | 'types' | 'esm' | 'cjs';
diff --git a/packages/cli/src/lib/svgrTemplate.ts b/packages/cli/src/lib/svgrTemplate.ts
index ca2a8c38fa..6af1b95e71 100644
--- a/packages/cli/src/lib/svgrTemplate.ts
+++ b/packages/cli/src/lib/svgrTemplate.ts
@@ -20,28 +20,23 @@
* them with .icon.svg
*/
export function svgrTemplate(
- { template }: any,
- _opts: any,
- { imports, interfaces, componentName, jsx }: any,
+ { imports, interfaces, componentName, props, jsx }: any,
+ { tpl }: any,
) {
- const iconName = {
- ...componentName,
- name: `${componentName.name.replace(/icon$/, '')}Icon`,
- };
+ const name = `${componentName.replace(/icon$/, '')}Icon`;
const defaultExport = {
type: 'ExportDefaultDeclaration',
- declaration: iconName,
+ declaration: { type: 'Identifier', name },
};
- const typeScriptTemplate = template.smart({ plugins: ['typescript'] });
- return typeScriptTemplate.ast`
+ return tpl`
${imports}
import SvgIcon from '@material-ui/core/SvgIcon';
${interfaces}
-const ${iconName} = props => React.createElement(SvgIcon, props, ${jsx.children});
+const ${name} = (${props}) => React.createElement(SvgIcon, ${props}, ${jsx.children});
${defaultExport}`;
}
diff --git a/packages/codemods/.snyk b/packages/codemods/.snyk
new file mode 100644
index 0000000000..7926925d71
--- /dev/null
+++ b/packages/codemods/.snyk
@@ -0,0 +1,12 @@
+# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
+version: v1.22.1
+# ignores vulnerabilities until expiry date; change duration by modifying expiry date
+ignore:
+ SNYK-JS-UNSETVALUE-2400660:
+ - '*':
+ reason: >-
+ The pollution in this vulnerability does not allow injection of
+ arbitrary values and is therefore a negligible risk for a CLI.
+ expires: 2022-08-17T21:54:43.658Z
+ created: 2022-02-15T21:54:43.668Z
+patch: {}
diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md
index c7283f5d8c..603fa1075e 100644
--- a/packages/codemods/CHANGELOG.md
+++ b/packages/codemods/CHANGELOG.md
@@ -1,5 +1,23 @@
# @backstage/codemods
+## 0.1.35
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/cli-common@0.1.8
+
+## 0.1.34
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/core-app-api@0.5.3
+ - @backstage/core-components@0.8.9
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/cli-common@0.1.7
+
## 0.1.33
### Patch Changes
diff --git a/packages/codemods/package.json b/packages/codemods/package.json
index dc1fe6a537..c4d2eedb4d 100644
--- a/packages/codemods/package.json
+++ b/packages/codemods/package.json
@@ -1,12 +1,15 @@
{
"name": "@backstage/codemods",
"description": "A collection of codemods for Backstage projects",
- "version": "0.1.33",
+ "version": "0.1.34",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js"
},
+ "backstage": {
+ "role": "cli"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -20,18 +23,18 @@
"main": "src/index.ts",
"scripts": {
"start": "nodemon --",
- "build": "backstage-cli build --outputs cjs",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
"prepack": "backstage-cli prepack",
"postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "clean": "backstage-cli package clean"
},
"bin": {
"backstage-codemods": "bin/backstage-codemods"
},
"dependencies": {
- "@backstage/cli-common": "0.1.6",
+ "@backstage/cli-common": "^0.1.8",
"@backstage/core-app-api": "*",
"@backstage/core-components": "*",
"@backstage/core-plugin-api": "*",
diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md
index cf953948da..d9bd7be8ba 100644
--- a/packages/config-loader/CHANGELOG.md
+++ b/packages/config-loader/CHANGELOG.md
@@ -1,5 +1,34 @@
# @backstage/config-loader
+## 0.9.6
+
+### Patch Changes
+
+- c3a1300f79: Include any files included in configuration via $include or $file directives when watching for configuration changes.
+
+## 0.9.5
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/cli-common@0.1.8
+ - @backstage/config@0.1.15
+ - @backstage/errors@0.2.2
+ - @backstage/types@0.1.3
+
+## 0.9.4
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/errors@0.2.1
+ - @backstage/cli-common@0.1.7
+ - @backstage/config@0.1.14
+ - @backstage/types@0.1.2
+
## 0.9.3
### Patch Changes
diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json
index b374a02fbf..d9c9b551b4 100644
--- a/packages/config-loader/package.json
+++ b/packages/config-loader/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/config-loader",
"description": "Config loading functionality used by Backstage backend, and CLI",
- "version": "0.9.3",
+ "version": "0.9.6",
"private": false,
"publishConfig": {
"access": "public",
@@ -9,6 +9,9 @@
"module": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "node-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -22,18 +25,19 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/cli-common": "^0.1.6",
- "@backstage/config": "^0.1.13",
- "@backstage/errors": "^0.2.0",
- "@backstage/types": "^0.1.1",
+ "@backstage/cli-common": "^0.1.8",
+ "@backstage/config": "^0.1.15",
+ "@backstage/errors": "^0.2.2",
+ "@backstage/types": "^0.1.3",
"@types/json-schema": "^7.0.6",
"ajv": "^7.0.3",
"chokidar": "^3.5.2",
diff --git a/packages/config-loader/src/loader.test.ts b/packages/config-loader/src/loader.test.ts
index 9faeda64ea..058f59aef1 100644
--- a/packages/config-loader/src/loader.test.ts
+++ b/packages/config-loader/src/loader.test.ts
@@ -333,6 +333,66 @@ describe('loadConfig', () => {
stopSignal.resolve();
});
+ it('watches included files', async () => {
+ const onChange = defer();
+ const stopSignal = defer();
+
+ await expect(
+ loadConfig({
+ configRoot: '/root',
+ configTargets: [{ path: '/root/app-config.development.yaml' }],
+ watch: {
+ onChange: onChange.resolve,
+ stopSignal: stopSignal.promise,
+ },
+ }),
+ ).resolves.toEqual({
+ appConfigs: [
+ {
+ context: 'app-config.development.yaml',
+ data: {
+ app: {
+ sessionKey: 'development-key',
+ },
+ backend: {
+ foo: {
+ bar: 'token is-secret',
+ },
+ },
+ other: {
+ secret: 'abc123',
+ },
+ },
+ },
+ ],
+ });
+
+ // session-key is indirectly included in app-config.development.yaml
+ // via included.yaml
+ await fs.writeFile('/root/secrets/session-key.txt', 'abc234');
+
+ await expect(onChange.promise).resolves.toEqual([
+ {
+ context: 'app-config.development.yaml',
+ data: {
+ app: {
+ sessionKey: 'development-key',
+ },
+ backend: {
+ foo: {
+ bar: 'token is-secret',
+ },
+ },
+ other: {
+ secret: 'abc234',
+ },
+ },
+ },
+ ]);
+
+ stopSignal.resolve();
+ });
+
it('watches remote config urls', async () => {
server.use(initialLoaderHandler);
diff --git a/packages/config-loader/src/loader.ts b/packages/config-loader/src/loader.ts
index 03a6805da0..9a3287e285 100644
--- a/packages/config-loader/src/loader.ts
+++ b/packages/config-loader/src/loader.ts
@@ -140,7 +140,8 @@ export async function loadConfig(
const env = envFunc ?? (async (name: string) => process.env[name]);
const loadConfigFiles = async () => {
- const configs = [];
+ const fileConfigs = [];
+ const loadedPaths = new Set();
for (const configPath of configPaths) {
if (!isAbsolute(configPath)) {
@@ -148,8 +149,15 @@ export async function loadConfig(
}
const dir = dirname(configPath);
- const readFile = (path: string) =>
- fs.readFile(resolvePath(dir, path), 'utf8');
+ const readFile = (path: string) => {
+ const fullPath = resolvePath(dir, path);
+ // if we read a file when building configuration,
+ // we should include that file when watching for
+ // changes, too.
+ loadedPaths.add(fullPath);
+
+ return fs.readFile(fullPath, 'utf8');
+ };
const input = yaml.parse(await readFile(configPath));
const substitutionTransform = createSubstitutionTransform(env);
@@ -158,10 +166,10 @@ export async function loadConfig(
substitutionTransform,
]);
- configs.push({ data, context: basename(configPath) });
+ fileConfigs.push({ data, context: basename(configPath) });
}
- return configs;
+ return { fileConfigs, loadedPaths };
};
const loadRemoteConfigFiles = async () => {
@@ -199,8 +207,9 @@ export async function loadConfig(
};
let fileConfigs: AppConfig[];
+ let loadedPaths: Set;
try {
- fileConfigs = await loadConfigFiles();
+ ({ fileConfigs, loadedPaths } = await loadConfigFiles());
} catch (error) {
throw new ForwardedError('Failed to read static configuration file', error);
}
@@ -220,14 +229,24 @@ export async function loadConfig(
const envConfigs = await readEnvConfig(process.env);
const watchConfigFile = (watchProp: LoadConfigOptionsWatch) => {
- const watcher = chokidar.watch(configPaths, {
+ let watchedFiles = Array.from(loadedPaths);
+
+ const watcher = chokidar.watch(watchedFiles, {
usePolling: process.env.NODE_ENV === 'test',
});
let currentSerializedConfig = JSON.stringify(fileConfigs);
watcher.on('change', async () => {
try {
- const newConfigs = await loadConfigFiles();
+ const { fileConfigs: newConfigs, loadedPaths: newLoadedPaths } =
+ await loadConfigFiles();
+
+ // Replace watches to handle any added or removed
+ // $include or $file expressions.
+ watcher.unwatch(watchedFiles);
+ watchedFiles = Array.from(newLoadedPaths);
+ watcher.add(watchedFiles);
+
const newSerializedConfig = JSON.stringify(newConfigs);
if (currentSerializedConfig === newSerializedConfig) {
diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md
index 2d3e90d1b7..2af4d3763b 100644
--- a/packages/config/CHANGELOG.md
+++ b/packages/config/CHANGELOG.md
@@ -1,5 +1,21 @@
# @backstage/config
+## 0.1.15
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/types@0.1.3
+
+## 0.1.14
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/types@0.1.2
+
## 0.1.13
### Patch Changes
diff --git a/packages/config/package.json b/packages/config/package.json
index 02c63af2b5..63edfe0360 100644
--- a/packages/config/package.json
+++ b/packages/config/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/config",
"description": "Config API used by Backstage core, backend, and CLI",
- "version": "0.1.13",
+ "version": "0.1.15",
"private": false,
"publishConfig": {
"access": "public",
@@ -9,6 +9,9 @@
"module": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "common-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -22,19 +25,19 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean"
},
"dependencies": {
- "@backstage/types": "^0.1.1",
+ "@backstage/types": "^0.1.3",
"lodash": "^4.17.21"
},
"devDependencies": {
- "@backstage/test-utils": "^0.2.4-next.0",
+ "@backstage/test-utils": "^0.2.5",
"@types/jest": "^26.0.7",
"@types/node": "^14.14.32"
},
diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md
index cc115a7da2..f40ea23f73 100644
--- a/packages/core-app-api/CHANGELOG.md
+++ b/packages/core-app-api/CHANGELOG.md
@@ -1,5 +1,24 @@
# @backstage/core-app-api
+## 0.5.4
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/core-plugin-api@0.7.0
+
+## 0.5.3
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/config@0.1.14
+ - @backstage/types@0.1.2
+ - @backstage/version-bridge@0.1.2
+
## 0.5.2
### Patch Changes
diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json
index 04e87b5d0c..6f74bf95d6 100644
--- a/packages/core-app-api/package.json
+++ b/packages/core-app-api/package.json
@@ -1,13 +1,16 @@
{
"name": "@backstage/core-app-api",
"description": "Core app API used by Backstage apps",
- "version": "0.5.2",
+ "version": "0.5.4",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "web-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,18 +24,19 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build --outputs types,esm",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/config": "^0.1.13",
- "@backstage/core-plugin-api": "^0.6.0",
- "@backstage/types": "^0.1.1",
- "@backstage/version-bridge": "^0.1.1",
+ "@backstage/config": "^0.1.15",
+ "@backstage/core-plugin-api": "^0.7.0",
+ "@backstage/types": "^0.1.3",
+ "@backstage/version-bridge": "^0.1.2",
"@types/prop-types": "^15.7.3",
"prop-types": "^15.7.2",
"react-router-dom": "6.0.0-beta.0",
@@ -45,8 +49,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0",
- "@backstage/test-utils": "^0.2.4",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/test-utils": "^0.2.6",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/react-hooks": "^7.0.2",
diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md
index fe51935ab0..5d8211d303 100644
--- a/packages/core-components/CHANGELOG.md
+++ b/packages/core-components/CHANGELOG.md
@@ -1,5 +1,28 @@
# @backstage/core-components
+## 0.8.10
+
+### Patch Changes
+
+- d91d22bb19: When clicking on a log line the URL will be updated from `/task/uid` to
+ `/task/uid/#line-1`. This URL are also sharable, meaning that the UI will
+ highlight the log line in the hash of the URL.
+- Updated dependencies
+ - @backstage/core-plugin-api@0.7.0
+
+## 0.8.9
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- 126074a04b: Port supported react-use functions to react-hookz.
+- Updated dependencies
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/errors@0.2.1
+ - @backstage/config@0.1.14
+ - @backstage/theme@0.2.15
+
## 0.8.8
### Patch Changes
diff --git a/packages/core-components/package.json b/packages/core-components/package.json
index ecb910c50b..d8d8328f9b 100644
--- a/packages/core-components/package.json
+++ b/packages/core-components/package.json
@@ -1,13 +1,16 @@
{
"name": "@backstage/core-components",
"description": "Core components used by Backstage plugins and apps",
- "version": "0.8.8",
+ "version": "0.8.10",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "web-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,18 +24,19 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build --outputs types,esm",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/config": "^0.1.13",
- "@backstage/core-plugin-api": "^0.6.0",
- "@backstage/errors": "^0.2.0",
- "@backstage/theme": "^0.2.14",
+ "@backstage/config": "^0.1.15",
+ "@backstage/core-plugin-api": "^0.7.0",
+ "@backstage/errors": "^0.2.2",
+ "@backstage/theme": "^0.2.15",
"@material-table/core": "^3.1.0",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
@@ -60,7 +64,8 @@
"react-sparklines": "^1.7.0",
"react-syntax-highlighter": "^15.4.5",
"react-text-truncate": "^0.17.0",
- "react-use": "^17.2.4",
+ "react-use": "^17.3.2",
+ "@react-hookz/web": "^12.3.0",
"react-virtualized-auto-sizer": "^1.0.6",
"react-window": "^1.8.6",
"remark-gfm": "^3.0.1",
@@ -73,9 +78,9 @@
"react-dom": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
- "@backstage/core-app-api": "^0.5.2",
- "@backstage/cli": "^0.13.2",
- "@backstage/test-utils": "^0.2.4",
+ "@backstage/core-app-api": "^0.5.4",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/test-utils": "^0.2.6",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/react-hooks": "^7.0.2",
diff --git a/packages/core-components/src/components/LogViewer/RealLogViewer.tsx b/packages/core-components/src/components/LogViewer/RealLogViewer.tsx
index cd30e96c92..ac66d7cdf5 100644
--- a/packages/core-components/src/components/LogViewer/RealLogViewer.tsx
+++ b/packages/core-components/src/components/LogViewer/RealLogViewer.tsx
@@ -15,6 +15,7 @@
*/
import React, { useEffect, useMemo, useRef } from 'react';
+import { useLocation } from 'react-router-dom';
import IconButton from '@material-ui/core/IconButton';
import CopyIcon from '@material-ui/icons/FileCopy';
import AutoSizer from 'react-virtualized-auto-sizer';
@@ -42,6 +43,7 @@ export function RealLogViewer(props: RealLogViewerProps) {
const search = useLogViewerSearch(lines);
const selection = useLogViewerSelection(lines);
+ const location = useLocation();
useEffect(() => {
if (search.resultLine !== undefined && listRef.current) {
@@ -49,11 +51,18 @@ export function RealLogViewer(props: RealLogViewerProps) {
}
}, [search.resultLine]);
+ useEffect(() => {
+ if (location.hash) {
+ // #line-6 -> 6
+ const line = parseInt(location.hash.replace(/\D/g, ''), 10);
+ selection.setSelection(line, false);
+ }
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
+
const handleSelectLine = (
line: number,
event: { shiftKey: boolean; preventDefault: () => void },
) => {
- event.preventDefault();
selection.setSelection(line, event.shiftKey);
};
diff --git a/packages/core-components/src/components/LogViewer/useLogViewerSearch.tsx b/packages/core-components/src/components/LogViewer/useLogViewerSearch.tsx
index 7f0069bc44..14f71984f4 100644
--- a/packages/core-components/src/components/LogViewer/useLogViewerSearch.tsx
+++ b/packages/core-components/src/components/LogViewer/useLogViewerSearch.tsx
@@ -15,7 +15,7 @@
*/
import { useMemo, useState } from 'react';
-import useToggle from 'react-use/lib/useToggle';
+import { useToggle } from '@react-hookz/web';
import { AnsiLine } from './AnsiProcessor';
export function applySearchFilter(lines: AnsiLine[], searchText: string) {
diff --git a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx
index 69952d487a..da489725e4 100644
--- a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx
+++ b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx
@@ -18,7 +18,7 @@ import { makeStyles } from '@material-ui/core/styles';
import Tooltip, { TooltipProps } from '@material-ui/core/Tooltip';
import React, { useState } from 'react';
import TextTruncate, { TextTruncateProps } from 'react-text-truncate';
-import useMountedState from 'react-use/lib/useMountedState';
+import { useIsMounted } from '@react-hookz/web';
type Props = {
text: TextTruncateProps['text'];
@@ -41,7 +41,7 @@ const useStyles = makeStyles(
export function OverflowTooltip(props: Props) {
const [hover, setHover] = useState(false);
- const isMounted = useMountedState();
+ const isMounted = useIsMounted();
const classes = useStyles();
const handleToggled = (truncated: boolean) => {
diff --git a/packages/core-components/src/hooks/useQueryParamState.ts b/packages/core-components/src/hooks/useQueryParamState.ts
index 72ccafd99f..16cd9e18c8 100644
--- a/packages/core-components/src/hooks/useQueryParamState.ts
+++ b/packages/core-components/src/hooks/useQueryParamState.ts
@@ -18,7 +18,7 @@ import { isEqual } from 'lodash';
import qs from 'qs';
import { useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
-import useDebounce from 'react-use/lib/useDebounce';
+import { useDebouncedEffect } from '@react-hookz/web';
function stringify(queryParams: any): string {
// Even though these setting don't look nice (e.g. escaped brackets), we should keep
@@ -75,7 +75,7 @@ export function useQueryParamState(
);
}, [searchParamsString, setQueryParamState, stateName]);
- useDebounce(
+ useDebouncedEffect(
() => {
const queryString = joinQueryString(
searchParamsString,
@@ -87,8 +87,8 @@ export function useQueryParamState(
setSearchParams(queryString, { replace: true });
}
},
- debounceTime,
[setSearchParams, queryParamState, searchParamsString, stateName],
+ debounceTime,
);
return [queryParamState, setQueryParamState];
diff --git a/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.tsx b/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.tsx
index adcd6ced8f..13a61d259f 100644
--- a/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.tsx
+++ b/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.tsx
@@ -20,7 +20,7 @@ import {
useApi,
} from '@backstage/core-plugin-api';
import React from 'react';
-import useAsync from 'react-use/lib/useAsync';
+import { useAsync, useMountEffect } from '@react-hookz/web';
import { ErrorPanel } from '../../components/ErrorPanel';
import { Progress } from '../../components/Progress';
import { ProxiedSignInIdentity } from './ProxiedSignInIdentity';
@@ -56,7 +56,7 @@ export type ProxiedSignInPageProps = SignInPageProps & {
export const ProxiedSignInPage = (props: ProxiedSignInPageProps) => {
const discoveryApi = useApi(discoveryApiRef);
- const { loading, error } = useAsync(async () => {
+ const [{ status, error }, { execute }] = useAsync(async () => {
const identity = new ProxiedSignInIdentity({
provider: props.provider,
discoveryApi,
@@ -65,9 +65,11 @@ export const ProxiedSignInPage = (props: ProxiedSignInPageProps) => {
await identity.start();
props.onSignInSuccess(identity);
- }, []);
+ });
- if (loading) {
+ useMountEffect(execute);
+
+ if (status === 'loading') {
return ;
} else if (error) {
return (
diff --git a/packages/core-components/src/layout/Sidebar/Bar.test.tsx b/packages/core-components/src/layout/Sidebar/Bar.test.tsx
index 89133997f9..fc42e7a94e 100644
--- a/packages/core-components/src/layout/Sidebar/Bar.test.tsx
+++ b/packages/core-components/src/layout/Sidebar/Bar.test.tsx
@@ -46,6 +46,11 @@ async function renderScalableSidebar() {
{}} text="Catalog">
+
@@ -112,5 +121,22 @@ describe('Sidebar', () => {
'/dropdownitemlink',
);
});
+
+ it('Submenu item renders an external link when `to` value is provided', async () => {
+ userEvent.hover(screen.getByTestId('item-with-submenu'));
+ expect(screen.getByText('External Link').closest('a')).toHaveAttribute(
+ 'href',
+ 'https://backstage.io/',
+ );
+ });
+
+ it('Dropdown item in submenu renders an external link when `to` value is provided', async () => {
+ userEvent.hover(screen.getByTestId('item-with-submenu'));
+ userEvent.click(screen.getByText('Misc'));
+ expect(screen.getByText('dropdown item 3').closest('a')).toHaveAttribute(
+ 'href',
+ 'https://backstage.io/',
+ );
+ });
});
});
diff --git a/packages/core-components/src/layout/Sidebar/Intro.tsx b/packages/core-components/src/layout/Sidebar/Intro.tsx
index 7b2c5fa4d7..1fcc54188f 100644
--- a/packages/core-components/src/layout/Sidebar/Intro.tsx
+++ b/packages/core-components/src/layout/Sidebar/Intro.tsx
@@ -21,7 +21,7 @@ import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import CloseIcon from '@material-ui/icons/Close';
import React, { useContext, useState } from 'react';
-import useLocalStorage from 'react-use/lib/useLocalStorage';
+import { useLocalStorageValue } from '@react-hookz/web';
import {
sidebarConfig,
SidebarContext,
@@ -155,7 +155,7 @@ export function SidebarIntro(_props: {}) {
recentlyViewedItemsDismissed: false,
};
const [dismissedIntro, setDismissedIntro] =
- useLocalStorage(SIDEBAR_INTRO_LOCAL_STORAGE);
+ useLocalStorageValue(SIDEBAR_INTRO_LOCAL_STORAGE);
const { starredItemsDismissed, recentlyViewedItemsDismissed } =
dismissedIntro ?? {};
diff --git a/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx b/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx
index 1ede5f887e..d204728bcf 100644
--- a/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx
+++ b/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx
@@ -14,15 +14,10 @@
* limitations under the License.
*/
import React, { useContext, useState } from 'react';
-import {
- NavLink,
- resolvePath,
- useLocation,
- useResolvedPath,
-} from 'react-router-dom';
+import { resolvePath, useLocation, useResolvedPath } from 'react-router-dom';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
-import Link from '@material-ui/core/Link';
+import { Link } from '../../components/Link';
import { IconComponent } from '@backstage/core-plugin-api';
import classnames from 'classnames';
import { BackstageTheme } from '@backstage/theme';
@@ -163,7 +158,6 @@ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => {
{dropdownItems.map((object, key) => (
{
return (
login({ checkExisting: true }));
+ useMountEffect(() => login({ checkExisting: true }));
return showLoginPage ? (
diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md
index 21668577a1..bba39bf2cf 100644
--- a/packages/core-plugin-api/CHANGELOG.md
+++ b/packages/core-plugin-api/CHANGELOG.md
@@ -1,5 +1,23 @@
# @backstage/core-plugin-api
+## 0.7.0
+
+### Minor Changes
+
+- 33cd215b11: **BREAKING**: Removed deprecated `AnyAnalyticsContext` type which is replaced by `AnalyticsContextValue`
+
+## 0.6.1
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- 2714145cf5: Removes unused react-use dependency.
+- Updated dependencies
+ - @backstage/config@0.1.14
+ - @backstage/types@0.1.2
+ - @backstage/version-bridge@0.1.2
+
## 0.6.0
### Minor Changes
diff --git a/packages/core-plugin-api/api-report.md b/packages/core-plugin-api/api-report.md
index 5ac07e195c..1647d1c2cb 100644
--- a/packages/core-plugin-api/api-report.md
+++ b/packages/core-plugin-api/api-report.md
@@ -76,11 +76,6 @@ export type AnalyticsTracker = {
) => void;
};
-// @public @deprecated
-export type AnyAnalyticsContext = {
- [param in string]: string | boolean | number | undefined;
-};
-
// @public
export type AnyApiFactory = ApiFactory<
unknown,
diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json
index c9f110b432..4e9198557b 100644
--- a/packages/core-plugin-api/package.json
+++ b/packages/core-plugin-api/package.json
@@ -1,13 +1,16 @@
{
"name": "@backstage/core-plugin-api",
"description": "Core API used by Backstage plugins",
- "version": "0.6.0",
+ "version": "0.7.0",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "web-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,21 +24,21 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build --outputs types,esm",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/config": "^0.1.13",
- "@backstage/types": "^0.1.1",
- "@backstage/version-bridge": "^0.1.1",
+ "@backstage/config": "^0.1.15",
+ "@backstage/types": "^0.1.3",
+ "@backstage/version-bridge": "^0.1.2",
"history": "^5.0.0",
"prop-types": "^15.7.2",
"react-router-dom": "6.0.0-beta.0",
- "react-use": "^17.2.4",
"zen-observable": "^0.8.15"
},
"peerDependencies": {
@@ -43,9 +46,9 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0",
- "@backstage/core-app-api": "^0.5.2-next.0",
- "@backstage/test-utils": "^0.2.4-next.0",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/core-app-api": "^0.5.4",
+ "@backstage/test-utils": "^0.2.6",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/react-hooks": "^7.0.2",
diff --git a/packages/core-plugin-api/src/analytics/index.ts b/packages/core-plugin-api/src/analytics/index.ts
index 942df56ef8..651e8e105e 100644
--- a/packages/core-plugin-api/src/analytics/index.ts
+++ b/packages/core-plugin-api/src/analytics/index.ts
@@ -15,9 +15,5 @@
*/
export { AnalyticsContext } from './AnalyticsContext';
-export type {
- AnalyticsContextValue,
- AnyAnalyticsContext,
- CommonAnalyticsContext,
-} from './types';
+export type { AnalyticsContextValue, CommonAnalyticsContext } from './types';
export { useAnalytics } from './useAnalytics';
diff --git a/packages/core-plugin-api/src/analytics/types.ts b/packages/core-plugin-api/src/analytics/types.ts
index 431e453a61..1a60572082 100644
--- a/packages/core-plugin-api/src/analytics/types.ts
+++ b/packages/core-plugin-api/src/analytics/types.ts
@@ -36,16 +36,6 @@ export type CommonAnalyticsContext = {
extension: string;
};
-/**
- * Allows arbitrary scalar values as context attributes too.
- *
- * @public
- * @deprecated Will be removed, use `AnalyticsContextValue` instead
- */
-export type AnyAnalyticsContext = {
- [param in string]: string | boolean | number | undefined;
-};
-
/**
* Analytics context envelope.
*
diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md
index 886d873740..52dad1bfc9 100644
--- a/packages/create-app/CHANGELOG.md
+++ b/packages/create-app/CHANGELOG.md
@@ -1,5 +1,82 @@
# @backstage/create-app
+## 0.4.21
+
+### Patch Changes
+
+- a686702dbe: Update the template to reflect the renaming of `CatalogResultListItem` to `CatalogSearchResultListItem` from `@backstage/plugin-catalog`.
+
+ To apply this change to an existing app, make the following change to `packages/app/src/components/search/SearchPage.tsx`:
+
+ ```diff
+ -import { CatalogResultListItem } from '@backstage/plugin-catalog';
+ +import { CatalogSearchResultListItem } from '@backstage/plugin-catalog';
+ ```
+
+ ```diff
+ case 'software-catalog':
+ return (
+ -
+ ```
+
+- f39c1e6036: To reflect the updated `knex` and `@vscode/sqlite3` dependencies introduced with [v0.4.19](https://github.com/backstage/backstage/blob/master/packages/create-app/CHANGELOG.md#0419), we update our example `Dockerfile`, adding `@vscode/sqlite3` build dependencies to the image. Further on, we updated it to the `node:16-bullseye-slim` base image.
+
+ To apply this update to an existing app, make the following change to `packages/backend/Dockerfile`:
+
+ ```diff
+ -FROM node:14-buster-slim
+ +FROM node:16-bullseye-slim
+ ```
+
+ and, _only if you are using sqlite3 in your app_:
+
+ ```diff
+ 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)"
+ ```
+
+ If you are using a multi-stage Docker build for your app, please refer to the [updated examples](https://github.com/backstage/backstage/blob/master/docs/deployment/docker.md#multi-stage-build) in the documentation.
+
+## 0.4.20
+
+### Patch Changes
+
+- e725bb812f: Remove SearchContextProvider from ``
+
+ The `SidebarSearchModal` exported from `plugin-search` internally renders `SearchContextProvider`, so it can be removed from `Root.tsx`:
+
+ ```diff
+ -import {
+ - SidebarSearchModal,
+ - SearchContextProvider,
+ -} from '@backstage/plugin-search';
+ +import { SidebarSearchModal } from '@backstage/plugin-search';
+
+ ... omitted ...
+
+ } to="/search">
+ -
+ -
+ -
+ +
+
+ ```
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/cli-common@0.1.7
+
## 0.4.19
### Patch Changes
diff --git a/packages/create-app/package.json b/packages/create-app/package.json
index 4ab263abfd..a240e95cac 100644
--- a/packages/create-app/package.json
+++ b/packages/create-app/package.json
@@ -1,11 +1,14 @@
{
"name": "@backstage/create-app",
"description": "A CLI that helps you create your own Backstage app",
- "version": "0.4.19",
+ "version": "0.4.21",
"private": false,
"publishConfig": {
"access": "public"
},
+ "backstage": {
+ "role": "cli"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,16 +24,16 @@
"backstage-create-app": "bin/backstage-create-app"
},
"scripts": {
- "build": "backstage-cli build --outputs cjs",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "clean": "backstage-cli clean",
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "clean": "backstage-cli package clean",
"prepack": "node scripts/prepack.js",
"postpack": "node scripts/postpack.js",
"start": "nodemon --"
},
"dependencies": {
- "@backstage/cli-common": "^0.1.6",
+ "@backstage/cli-common": "^0.1.8",
"chalk": "^4.0.0",
"commander": "^6.1.0",
"fs-extra": "9.1.0",
diff --git a/packages/create-app/templates/default-app/packages/app/src/App.tsx b/packages/create-app/templates/default-app/packages/app/src/App.tsx
index 9b6518620d..6f00993273 100644
--- a/packages/create-app/templates/default-app/packages/app/src/App.tsx
+++ b/packages/create-app/templates/default-app/packages/app/src/App.tsx
@@ -15,7 +15,6 @@ import { orgPlugin } from '@backstage/plugin-org';
import { SearchPage } from '@backstage/plugin-search';
import { TechRadarPage } from '@backstage/plugin-tech-radar';
import {
- DefaultTechDocsHome,
TechDocsIndexPage,
techdocsPlugin,
TechDocsReaderPage,
@@ -65,9 +64,7 @@ const routes = (
>
{entityPage}
- }>
-
-
+ } />
}
diff --git a/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx
index a88e7250e9..cd4603ecd3 100644
--- a/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx
+++ b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx
@@ -1,12 +1,12 @@
import React from 'react';
import { makeStyles, Theme, Grid, List, Paper } from '@material-ui/core';
-import { CatalogResultListItem } from '@backstage/plugin-catalog';
+import { CatalogSearchResultListItem } from '@backstage/plugin-catalog';
import {
catalogApiRef,
CATALOG_FILTER_EXISTS,
} from '@backstage/plugin-catalog-react';
-import { DocsResultListItem } from '@backstage/plugin-techdocs';
+import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
import {
SearchBar,
@@ -116,14 +116,14 @@ const SearchPage = () => {
switch (type) {
case 'software-catalog':
return (
-
);
case 'techdocs':
return (
-
diff --git a/packages/create-app/templates/default-app/packages/backend/Dockerfile b/packages/create-app/templates/default-app/packages/backend/Dockerfile
index 31231a3a4a..dd35d4ddbc 100644
--- a/packages/create-app/templates/default-app/packages/backend/Dockerfile
+++ b/packages/create-app/templates/default-app/packages/backend/Dockerfile
@@ -9,7 +9,7 @@
#
# Once the commands have been run, you can build the image using `yarn build-image`
-FROM node:14-buster-slim
+FROM node:16-bullseye-slim
WORKDIR /app
@@ -19,6 +19,12 @@ WORKDIR /app
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/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md
index 8061f5fb98..4d2354297e 100644
--- a/packages/dev-utils/CHANGELOG.md
+++ b/packages/dev-utils/CHANGELOG.md
@@ -1,5 +1,35 @@
# @backstage/dev-utils
+## 0.2.23
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/core-components@0.8.10
+ - @backstage/plugin-catalog-react@0.7.0
+ - @backstage/catalog-model@0.11.0
+ - @backstage/core-plugin-api@0.7.0
+ - @backstage/app-defaults@0.1.9
+ - @backstage/core-app-api@0.5.4
+ - @backstage/integration-react@0.1.23
+ - @backstage/test-utils@0.2.6
+
+## 0.2.22
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/core-app-api@0.5.3
+ - @backstage/core-components@0.8.9
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/integration-react@0.1.22
+ - @backstage/test-utils@0.2.5
+ - @backstage/plugin-catalog-react@0.6.15
+ - @backstage/app-defaults@0.1.8
+ - @backstage/catalog-model@0.10.0
+ - @backstage/theme@0.2.15
+
## 0.2.21
### Patch Changes
diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json
index 9d55d17592..5c29c7dd0f 100644
--- a/packages/dev-utils/package.json
+++ b/packages/dev-utils/package.json
@@ -1,13 +1,16 @@
{
"name": "@backstage/dev-utils",
"description": "Utilities for developing Backstage plugins.",
- "version": "0.2.21",
+ "version": "0.2.23",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "web-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,23 +24,24 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build --outputs types,esm",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/app-defaults": "^0.1.7",
- "@backstage/core-app-api": "^0.5.2",
- "@backstage/core-components": "^0.8.8",
- "@backstage/core-plugin-api": "^0.6.0",
- "@backstage/catalog-model": "^0.9.10",
- "@backstage/integration-react": "^0.1.21",
- "@backstage/plugin-catalog-react": "^0.6.14",
- "@backstage/test-utils": "^0.2.4",
- "@backstage/theme": "^0.2.14",
+ "@backstage/app-defaults": "^0.1.9",
+ "@backstage/core-app-api": "^0.5.4",
+ "@backstage/core-components": "^0.8.10",
+ "@backstage/core-plugin-api": "^0.7.0",
+ "@backstage/catalog-model": "^0.11.0",
+ "@backstage/integration-react": "^0.1.23",
+ "@backstage/plugin-catalog-react": "^0.7.0",
+ "@backstage/test-utils": "^0.2.6",
+ "@backstage/theme": "^0.2.15",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@testing-library/jest-dom": "^5.10.1",
@@ -55,7 +59,7 @@
"react-dom": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
+ "@backstage/cli": "^0.14.1",
"@types/jest": "^26.0.7",
"@types/node": "^14.14.32"
},
diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json
index bbf55fac17..b17b0c14ce 100644
--- a/packages/e2e-test/package.json
+++ b/packages/e2e-test/package.json
@@ -3,6 +3,9 @@
"description": "E2E test for verifying Backstage packages",
"version": "0.2.0",
"private": true,
+ "backstage": {
+ "role": "cli"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -16,16 +19,18 @@
"main": "src/index.ts",
"scripts": {
"start": "nodemon --",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "test:e2e": "yarn start"
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "test:e2e": "yarn start",
+ "build": "backstage-cli package build",
+ "clean": "backstage-cli package clean"
},
"bin": {
"e2e-test": "bin/e2e-test"
},
"devDependencies": {
- "@backstage/cli-common": "^0.1.1",
- "@backstage/errors": "^0.2.0",
+ "@backstage/cli-common": "^0.1.8",
+ "@backstage/errors": "^0.2.2",
"@types/fs-extra": "^9.0.1",
"@types/node": "^14.14.32",
"@types/puppeteer": "^5.4.4",
diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md
index 110863d347..0c9295532a 100644
--- a/packages/errors/CHANGELOG.md
+++ b/packages/errors/CHANGELOG.md
@@ -1,5 +1,22 @@
# @backstage/errors
+## 0.2.2
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/types@0.1.3
+
+## 0.2.1
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/types@0.1.2
+
## 0.2.0
### Minor Changes
diff --git a/packages/errors/package.json b/packages/errors/package.json
index f97adef8e1..b1c90f0371 100644
--- a/packages/errors/package.json
+++ b/packages/errors/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/errors",
"description": "Common utilities for error handling within Backstage",
- "version": "0.2.0",
+ "version": "0.2.2",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -12,6 +12,9 @@
"module": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "common-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -22,20 +25,20 @@
"backstage"
],
"scripts": {
- "build": "backstage-cli build",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean"
},
"dependencies": {
- "@backstage/types": "^0.1.1",
+ "@backstage/types": "^0.1.3",
"cross-fetch": "^3.1.5",
"serialize-error": "^8.0.1"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0",
+ "@backstage/cli": "^0.14.0",
"@types/jest": "^26.0.7"
},
"files": [
diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md
index ec0457dc1e..1b8f22bcfc 100644
--- a/packages/integration-react/CHANGELOG.md
+++ b/packages/integration-react/CHANGELOG.md
@@ -1,5 +1,28 @@
# @backstage/integration-react
+## 0.1.23
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/core-components@0.8.10
+ - @backstage/core-plugin-api@0.7.0
+ - @backstage/integration@0.7.5
+
+## 0.1.22
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- f0e2f7a56a: Updated the `ScmAuth` error message for missing provider configurations to link to `ScmAuthApi` setup documentation.
+- Updated dependencies
+ - @backstage/core-components@0.8.9
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/integration@0.7.3
+ - @backstage/config@0.1.14
+ - @backstage/theme@0.2.15
+
## 0.1.21
### Patch Changes
diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json
index 8413442b3d..27e4492e65 100644
--- a/packages/integration-react/package.json
+++ b/packages/integration-react/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/integration-react",
"description": "Frontend package for managing integrations towards external systems",
- "version": "0.1.21",
+ "version": "0.1.23",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -11,21 +11,24 @@
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "web-library"
+ },
"scripts": {
- "build": "backstage-cli plugin:build",
- "start": "backstage-cli plugin:serve",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "start": "backstage-cli package start",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean"
},
"dependencies": {
- "@backstage/config": "^0.1.13",
- "@backstage/core-components": "^0.8.8",
- "@backstage/core-plugin-api": "^0.6.0",
- "@backstage/integration": "^0.7.2",
- "@backstage/theme": "^0.2.14",
+ "@backstage/config": "^0.1.15",
+ "@backstage/core-components": "^0.8.10",
+ "@backstage/core-plugin-api": "^0.7.0",
+ "@backstage/integration": "^0.7.5",
+ "@backstage/theme": "^0.2.15",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
@@ -35,9 +38,9 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
- "@backstage/dev-utils": "^0.2.21",
- "@backstage/test-utils": "^0.2.4",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/dev-utils": "^0.2.23",
+ "@backstage/test-utils": "^0.2.6",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^13.1.8",
diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md
index f8f53e959b..af764c3b69 100644
--- a/packages/integration/CHANGELOG.md
+++ b/packages/integration/CHANGELOG.md
@@ -1,5 +1,28 @@
# @backstage/integration
+## 0.7.5
+
+### Patch Changes
+
+- 4e1384884f: Fixed bug in integration package where Self Hosted GitLab instances with custom ports weren't supported (because of the lack of an option to add the port in the integration configs. Now users can add the port directly in the host)
+
+## 0.7.4
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/config@0.1.15
+
+## 0.7.3
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/config@0.1.14
+
## 0.7.2
### Patch Changes
@@ -212,7 +235,7 @@
- 0fd4ea443: Updates the `GithubCredentialsProvider` to return the token type, it can either be `token` or `app` depending on the authentication method.
- Update the `GithubOrgReaderProcessor` NOT to query for email addresses if GitHub Apps is used for authentication, this is due to inconsistencies in the GitHub API when using server to server communications and installation tokens. https://github.community/t/api-v4-unable-to-retrieve-email-resource-not-accessible-by-integration/13831/4 for more info.
+ Update the `GithubOrgReaderProcessor` NOT to query for email addresses if GitHub Apps is used for authentication, this is due to inconsistencies in the GitHub API when using server to server communications and installation tokens. See [this community discussion](https://github.community/t/api-v4-unable-to-retrieve-email-resource-not-accessible-by-integration/13831/4) for more info.
**Removes** deprecated GithubOrgReaderProcessor provider configuration(`catalog.processors.githubOrg`). If you're using the deprecated config section make sure to migrate to [integrations](https://backstage.io/docs/integrations/github/locations) instead.
diff --git a/packages/integration/package.json b/packages/integration/package.json
index d6d0edd77a..bf7c167bfa 100644
--- a/packages/integration/package.json
+++ b/packages/integration/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/integration",
"description": "Helpers for managing integrations towards external systems",
- "version": "0.7.2",
+ "version": "0.7.5",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -12,6 +12,9 @@
"module": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "common-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -22,15 +25,15 @@
"backstage"
],
"scripts": {
- "build": "backstage-cli build",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean"
},
"dependencies": {
- "@backstage/config": "^0.1.13",
+ "@backstage/config": "^0.1.15",
"cross-fetch": "^3.1.5",
"git-url-parse": "^11.6.0",
"@octokit/rest": "^18.5.3",
@@ -39,9 +42,9 @@
"lodash": "^4.17.21"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0",
- "@backstage/config-loader": "^0.9.3",
- "@backstage/test-utils": "^0.2.4-next.0",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/config-loader": "^0.9.6",
+ "@backstage/test-utils": "^0.2.6",
"@types/jest": "^26.0.7",
"@types/luxon": "^2.0.4",
"msw": "^0.35.0"
diff --git a/packages/integration/src/bitbucket/BitbucketIntegration.test.ts b/packages/integration/src/bitbucket/BitbucketIntegration.test.ts
index 81b9be4e25..6bbe1be27b 100644
--- a/packages/integration/src/bitbucket/BitbucketIntegration.test.ts
+++ b/packages/integration/src/bitbucket/BitbucketIntegration.test.ts
@@ -45,8 +45,10 @@ describe('BitbucketIntegration', () => {
expect(integration.title).toBe('h.com');
});
- it('resolves url line number correctly', () => {
- const integration = new BitbucketIntegration({ host: 'h.com' } as any);
+ it('resolves url line number correctly for Bitbucket Cloud', () => {
+ const integration = new BitbucketIntegration({
+ host: 'bitbucket.org',
+ } as any);
expect(
integration.resolveUrl({
@@ -55,10 +57,22 @@ describe('BitbucketIntegration', () => {
lineNumber: 14,
}),
).toBe(
- 'https://bitbucket.org/my-owner/my-project/src/master/a.yaml#a.yaml-14',
+ 'https://bitbucket.org/my-owner/my-project/src/master/a.yaml#lines-14',
);
});
+ it('resolves url line number correctly for Bitbucket Server', () => {
+ const integration = new BitbucketIntegration({ host: 'h.com' } as any);
+
+ expect(
+ integration.resolveUrl({
+ url: './a.yaml',
+ base: 'https://bitbucket.org/my-owner/my-project/src/master/README.md',
+ lineNumber: 14,
+ }),
+ ).toBe('https://bitbucket.org/my-owner/my-project/src/master/a.yaml#14');
+ });
+
it('resolve edit URL', () => {
const integration = new BitbucketIntegration({ host: 'h.com' } as any);
diff --git a/packages/integration/src/bitbucket/BitbucketIntegration.ts b/packages/integration/src/bitbucket/BitbucketIntegration.ts
index 6c21d716b7..0162463e3c 100644
--- a/packages/integration/src/bitbucket/BitbucketIntegration.ts
+++ b/packages/integration/src/bitbucket/BitbucketIntegration.ts
@@ -60,17 +60,21 @@ export class BitbucketIntegration implements ScmIntegration {
lineNumber?: number;
}): string {
const resolved = defaultScmResolveUrl(options);
-
- // Bitbucket line numbers use the syntax #example.txt-42, rather than #L42
- if (options.lineNumber) {
- const url = new URL(resolved);
-
- const filename = url.pathname.split('/').slice(-1)[0];
- url.hash = `${filename}-${options.lineNumber}`;
- return url.toString();
+ if (!options.lineNumber) {
+ return resolved;
}
- return resolved;
+ const url = new URL(resolved);
+
+ if (this.integrationConfig.host === 'bitbucket.org') {
+ // Bitbucket Cloud uses the syntax #lines-{start}[:{end}][,...]
+ url.hash = `lines-${options.lineNumber}`;
+ } else {
+ // Bitbucket Server uses the syntax #{start}[-{end}][,...]
+ url.hash = `${options.lineNumber}`;
+ }
+
+ return url.toString();
}
resolveEditUrl(url: string): string {
diff --git a/packages/integration/src/gitlab/config.ts b/packages/integration/src/gitlab/config.ts
index f74b849c74..71b4cd868f 100644
--- a/packages/integration/src/gitlab/config.ts
+++ b/packages/integration/src/gitlab/config.ts
@@ -82,11 +82,7 @@ export function readGitLabIntegrationConfig(
baseUrl = `https://${host}`;
}
- if (host.includes(':')) {
- throw new Error(
- `Invalid GitLab integration config, host '${host}' should just be the host name (e.g. "github.com"), not a URL`,
- );
- } else if (!isValidHost(host)) {
+ if (!isValidHost(host)) {
throw new Error(
`Invalid GitLab integration config, '${host}' is not a valid host`,
);
diff --git a/packages/integration/src/gitlab/core.ts b/packages/integration/src/gitlab/core.ts
index c5b0713340..b379d3d129 100644
--- a/packages/integration/src/gitlab/core.ts
+++ b/packages/integration/src/gitlab/core.ts
@@ -138,7 +138,7 @@ export async function getProjectId(
// Convert
// to: https://gitlab.com/api/v4/projects/groupA%2Fteams%2FsubgroupA%2FteamA%2Frepo
const repoIDLookup = new URL(
- `${url.protocol + url.hostname}/api/v4/projects/${encodeURIComponent(
+ `${url.origin}/api/v4/projects/${encodeURIComponent(
repo.replace(/^\//, ''),
)}`,
);
diff --git a/packages/release-manifests/CHANGELOG.md b/packages/release-manifests/CHANGELOG.md
index 61e6c45992..61113e1c76 100644
--- a/packages/release-manifests/CHANGELOG.md
+++ b/packages/release-manifests/CHANGELOG.md
@@ -1,5 +1,12 @@
# @backstage/release-manifests
+## 0.0.2
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+
## 0.0.1
### Patch Changes
diff --git a/packages/release-manifests/package.json b/packages/release-manifests/package.json
index 8ddbb73bca..7ec69a35e9 100644
--- a/packages/release-manifests/package.json
+++ b/packages/release-manifests/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/release-manifests",
"description": "Helper library for receiving release manifests",
- "version": "0.0.1",
+ "version": "0.0.2",
"private": false,
"main": "src/index.ts",
"types": "src/index.ts",
@@ -11,6 +11,9 @@
"module": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "common-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -22,18 +25,18 @@
],
"license": "Apache-2.0",
"scripts": {
- "build": "backstage-cli build",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean"
},
"dependencies": {
"cross-fetch": "^3.1.5"
},
"devDependencies": {
- "@backstage/test-utils": "^0.2.3",
+ "@backstage/test-utils": "^0.2.5",
"msw": "^0.35.0",
"@types/jest": "^26.0.7",
"@types/node": "^14.14.32"
diff --git a/packages/search-common/CHANGELOG.md b/packages/search-common/CHANGELOG.md
index 4460374646..71f2952d90 100644
--- a/packages/search-common/CHANGELOG.md
+++ b/packages/search-common/CHANGELOG.md
@@ -1,5 +1,23 @@
# @backstage/search-common
+## 0.2.4
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/types@0.1.3
+ - @backstage/plugin-permission-common@0.5.1
+
+## 0.2.3
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/plugin-permission-common@0.5.0
+ - @backstage/types@0.1.2
+
## 0.2.2
### Patch Changes
diff --git a/packages/search-common/package.json b/packages/search-common/package.json
index 10b03ab663..ef56017405 100644
--- a/packages/search-common/package.json
+++ b/packages/search-common/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/search-common",
"description": "Common functionalities for Search, to be shared between various search-enabled plugins",
- "version": "0.2.2",
+ "version": "0.2.4",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -10,6 +10,9 @@
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "common-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -25,22 +28,22 @@
"dist"
],
"scripts": {
- "build": "backstage-cli build --outputs cjs,types",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean"
},
"bugs": {
"url": "https://github.com/backstage/backstage/issues"
},
"dependencies": {
- "@backstage/types": "^0.1.1",
- "@backstage/plugin-permission-common": "^0.4.0-next.0"
+ "@backstage/types": "^0.1.3",
+ "@backstage/plugin-permission-common": "^0.5.1"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0"
+ "@backstage/cli": "^0.14.0"
},
"jest": {
"roots": [
diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md
index 38726ce10e..1302d1ca9d 100644
--- a/packages/techdocs-cli-embedded-app/CHANGELOG.md
+++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md
@@ -1,5 +1,39 @@
# techdocs-cli-embedded-app
+## 0.2.65
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/plugin-catalog@0.9.0
+ - @backstage/cli@0.14.1
+ - @backstage/core-components@0.8.10
+ - @backstage/plugin-techdocs@0.14.0
+ - @backstage/catalog-model@0.11.0
+ - @backstage/core-plugin-api@0.7.0
+ - @backstage/app-defaults@0.1.9
+ - @backstage/core-app-api@0.5.4
+ - @backstage/integration-react@0.1.23
+ - @backstage/test-utils@0.2.6
+
+## 0.2.64
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/cli@0.14.0
+ - @backstage/core-app-api@0.5.3
+ - @backstage/core-components@0.8.9
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/integration-react@0.1.22
+ - @backstage/test-utils@0.2.5
+ - @backstage/plugin-catalog@0.8.0
+ - @backstage/plugin-techdocs@0.13.4
+ - @backstage/app-defaults@0.1.8
+ - @backstage/catalog-model@0.10.0
+ - @backstage/config@0.1.14
+ - @backstage/theme@0.2.15
+
## 0.2.63
### Patch Changes
diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json
index 975bfef43b..6719701378 100644
--- a/packages/techdocs-cli-embedded-app/package.json
+++ b/packages/techdocs-cli-embedded-app/package.json
@@ -1,21 +1,24 @@
{
"name": "techdocs-cli-embedded-app",
- "version": "0.2.63",
+ "version": "0.2.65",
"private": true,
+ "backstage": {
+ "role": "frontend"
+ },
"bundled": true,
"dependencies": {
- "@backstage/app-defaults": "^0.1.7",
- "@backstage/catalog-model": "^0.9.10",
- "@backstage/cli": "^0.13.2",
- "@backstage/config": "^0.1.13",
- "@backstage/core-app-api": "^0.5.2",
- "@backstage/core-components": "^0.8.8",
- "@backstage/core-plugin-api": "^0.6.0",
- "@backstage/integration-react": "^0.1.21",
- "@backstage/plugin-catalog": "^0.7.12",
- "@backstage/plugin-techdocs": "^0.13.3",
- "@backstage/test-utils": "^0.2.4",
- "@backstage/theme": "^0.2.14",
+ "@backstage/app-defaults": "^0.1.9",
+ "@backstage/catalog-model": "^0.11.0",
+ "@backstage/cli": "^0.14.1",
+ "@backstage/config": "^0.1.15",
+ "@backstage/core-app-api": "^0.5.4",
+ "@backstage/core-components": "^0.8.10",
+ "@backstage/core-plugin-api": "^0.7.0",
+ "@backstage/integration-react": "^0.1.23",
+ "@backstage/plugin-catalog": "^0.9.0",
+ "@backstage/plugin-techdocs": "^0.14.0",
+ "@backstage/test-utils": "^0.2.6",
+ "@backstage/theme": "^0.2.15",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"history": "^5.0.0",
@@ -26,7 +29,7 @@
"react-use": "^17.2.4"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
+ "@backstage/cli": "^0.14.1",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^13.1.8",
@@ -34,16 +37,16 @@
"@types/node": "^14.14.32",
"@types/react-dom": "*",
"cross-env": "^7.0.0",
- "cypress": "^7.3.0",
+ "cypress": "^9.5.0",
"eslint-plugin-cypress": "^2.10.3",
"start-server-and-test": "^1.10.11"
},
"scripts": {
- "start": "backstage-cli app:serve --config ./app-config.yaml",
- "build": "backstage-cli app:build --config ./app-config.yaml",
- "clean": "backstage-cli clean",
- "test": "backstage-cli test",
- "lint": "backstage-cli lint",
+ "start": "backstage-cli package start --config ./app-config.yaml",
+ "build": "backstage-cli package build --config ./app-config.yaml",
+ "clean": "backstage-cli package clean",
+ "test": "backstage-cli package test",
+ "lint": "backstage-cli package lint",
"test:e2e": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:dev",
"test:e2e:ci": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:run",
"cy:dev": "cypress open",
diff --git a/packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx b/packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx
index 65e75a488a..249394fdc4 100644
--- a/packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx
+++ b/packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx
@@ -14,18 +14,20 @@
* limitations under the License.
*/
-import React, { useContext, PropsWithChildren } from 'react';
+import React, { PropsWithChildren, useContext } from 'react';
+
import { Link, makeStyles } from '@material-ui/core';
import LibraryBooks from '@material-ui/icons/LibraryBooks';
import LogoFull from './LogoFull';
import LogoIcon from './LogoIcon';
+
import {
Sidebar,
+ SidebarItem,
SidebarPage,
sidebarConfig,
- SidebarContext,
- SidebarItem,
SidebarDivider,
+ SidebarContext,
} from '@backstage/core-components';
import { NavLink } from 'react-router-dom';
@@ -70,7 +72,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
{/* Global nav, not org-specific */}
{/* End global nav */}
diff --git a/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx b/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx
index b90a49fb22..d9a518c165 100644
--- a/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx
+++ b/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx
@@ -14,7 +14,22 @@
* limitations under the License.
*/
-import React from 'react';
+import React, {
+ FC,
+ createContext,
+ useContext,
+ useState,
+ useCallback,
+} from 'react';
+
+import { Theme, makeStyles } from '@material-ui/core';
+
+import { ThemeProvider, Box, Tooltip, IconButton } from '@material-ui/core';
+import LightIcon from '@material-ui/icons/Brightness7';
+import DarkIcon from '@material-ui/icons/Brightness4';
+
+import { lightTheme, darkTheme } from '@backstage/theme';
+import { EntityName } from '@backstage/catalog-model';
import { Content } from '@backstage/core-components';
@@ -24,6 +39,106 @@ import {
TechDocsPageHeader,
} from '@backstage/plugin-techdocs';
+const useStyles = makeStyles((theme: Theme) => ({
+ headerIcon: {
+ color: theme.palette.common.white,
+ width: '32px',
+ height: '32px',
+ },
+ content: {
+ backgroundColor: theme.palette.background.default,
+ },
+ contentToolbar: {
+ display: 'flex',
+ justifyContent: 'flex-end',
+ padding: 0,
+ },
+}));
+
+enum Themes {
+ LIGHT = 'light',
+ DARK = 'dark',
+}
+
+type TechDocsThemeValue = {
+ theme: Themes;
+ toggleTheme: () => void;
+};
+
+const TechDocsThemeContext = createContext({
+ theme: Themes.LIGHT,
+ toggleTheme: () => {},
+});
+
+const TechdocsThemeProvider: FC = ({ children }) => {
+ const [theme, setTheme] = useState(Themes.LIGHT);
+
+ const toggleTheme = useCallback(() => {
+ setTheme(prevTheme =>
+ prevTheme === Themes.LIGHT ? Themes.DARK : Themes.LIGHT,
+ );
+ }, [setTheme]);
+
+ const value = { theme, toggleTheme };
+
+ const themes = {
+ [Themes.LIGHT]: lightTheme,
+ [Themes.DARK]: darkTheme,
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+const useTechDocsTheme = () => useContext(TechDocsThemeContext);
+
+const TechDocsThemeToggle = () => {
+ const classes = useStyles();
+ const { theme, toggleTheme } = useTechDocsTheme();
+
+ const themes = {
+ [Themes.LIGHT]: {
+ icon: DarkIcon,
+ title: 'Dark theme',
+ },
+ [Themes.DARK]: {
+ icon: LightIcon,
+ title: 'Light theme',
+ },
+ };
+
+ const { title, icon: Icon } = themes[theme];
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+const TechDocsPageContent = ({
+ onReady,
+ entityRef,
+}: {
+ entityRef: EntityName;
+ onReady: () => void;
+}) => {
+ const classes = useStyles();
+
+ return (
+
+
+
+ );
+};
+
const DefaultTechDocsPage = () => {
const techDocsMetadata = {
site_name: 'Live preview environment',
@@ -35,20 +150,20 @@ const DefaultTechDocsPage = () => {
{({ entityRef, onReady }) => (
<>
-
-
-
+ techDocsMetadata={techDocsMetadata}
+ >
+
+
+
>
)}
);
};
-export const techDocsPage = ;
+export const techDocsPage = (
+
+
+
+);
diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md
index 98015f766a..bc23499662 100644
--- a/packages/techdocs-cli/CHANGELOG.md
+++ b/packages/techdocs-cli/CHANGELOG.md
@@ -1,5 +1,31 @@
# @techdocs/cli
+## 0.8.15
+
+### Patch Changes
+
+- ed78516480: chore(deps-dev): bump `cypress` from 7.3.0 to 9.5.0
+- 209fd128e6: Updated usage of `github:` location types in docs to use `url:` instead.
+- 61ff215e08: - Adds `cypress` and `cypress-plugin-snapshots` as dependencies for integration and visual regression tests.
+ - Updates README documentation with instructions for how to run tests.
+ - Clarifies output text for prepack script.
+- Updated dependencies
+ - @backstage/backend-common@0.11.0
+ - @backstage/catalog-model@0.11.0
+ - @backstage/techdocs-common@0.11.10
+
+## 0.8.14
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/backend-common@0.10.8
+ - @backstage/catalog-model@0.10.0
+ - @backstage/cli-common@0.1.7
+ - @backstage/config@0.1.14
+ - @backstage/techdocs-common@0.11.8
+
## 0.8.13
### Patch Changes
diff --git a/packages/techdocs-cli/README.md b/packages/techdocs-cli/README.md
index 3ac423cb38..ae296d2c26 100644
--- a/packages/techdocs-cli/README.md
+++ b/packages/techdocs-cli/README.md
@@ -17,7 +17,7 @@ bundle into the `packages/techdocs-cli/dist` which is then published with the
```sh
# From the root of this repository run
# NOTE: This will build the techdocs-cli-embedded-app and copy the output into the cli dist directory
-yarn build --scope @techdocs/cli
+yarn workspace @techdocs/cli build
# Now execute the binary
packages/techdocs-cli/bin/techdocs-cli
@@ -40,8 +40,25 @@ yarn start
yarn techdocs-cli:dev [...options]
```
+### Using an example docs project
+
+For the purpose of local development, we have created an example documentation project. You are of course also free to create your own local test site - all it takes is a `docs/index.md` and an `mkdocs.yml` in a directory.
+
+```sh
+
+cd packages/techdocs-cli/src/example-docs
+
+# To get a view of your docs in Backstage, use:
+techdocs-cli serve
+
+# To view the raw mkdocs site (without Backstage), use:
+techdocs-cli serve:mkdocs
+```
+
### Testing
+#### E2E tests
+
Running unit tests requires mkdocs to be installed locally:
```sh
@@ -51,18 +68,37 @@ pip install mkdocs-techdocs-core
Then run `yarn test`.
-### Use an example docs project
+#### Cypress (Integration and Visual regression) tests
-We have created an [example documentation project](https://github.com/backstage/techdocs-container/tree/main/mock-docs) and it's shipped with [techdocs-container](https://github.com/backstage/techdocs-container) repository, for the purpose of local development. But you are free to create your own local test site. All it takes is a `docs/index.md` and `mkdocs.yml` in a directory.
+Running cypress tests requires you to run the CLI locally against our example docs.
+
+Run the local version of techdocs-cli against the example docs:
```sh
-git clone https://github.com/backstage/techdocs-container.git
+# From the root of this repository run
+# NOTE: This will build the techdocs-cli-embedded-app and copy the output into the cli dist directory
+yarn build --scope @techdocs/cli
-cd techdocs-container/mock-docs
+# Navigate to the example project
+cd packages/techdocs-cli/src/example-docs
-# To get a view of your docs in Backstage, use:
-techdocs-cli serve
-
-# To view the raw mkdocs site (without Backstage), use:
-techdocs-cli serve:mkdocs
+# Now execute the techdocs-cli serve command
+../../bin/techdocs-cli serve
```
+
+In another shell, run the cypress tests:
+
+```sh
+# From the root of the project, navigate to the techdocs-cli package
+cd packages/techdocs-cli
+
+# Run tests
+yarn test:cypress
+```
+
+This will launch a cypress app where you can run the two different tests:
+
+- `backstage_serve` - will run against the backstage server
+- `mkdocs_serve` - will run test against the mkdocs server
+
+> If its the first time you run Cypress, it will run a "Verifying Cypress can run" step. This step can result in a "Cypress verification timed out" error. If that is the case, let the verification step run and then run the command again and it should succeed.
diff --git a/packages/techdocs-cli/cypress.json b/packages/techdocs-cli/cypress.json
new file mode 100644
index 0000000000..b6f3b96019
--- /dev/null
+++ b/packages/techdocs-cli/cypress.json
@@ -0,0 +1,17 @@
+{
+ "env": {
+ "mkDocsBaseUrl": "http://localhost:8000",
+ "backstageBaseUrl": "http://localhost:3000",
+ "cypress-plugin-snapshots": {
+ "autoCleanUp": false,
+ "imageConfig": {
+ "resizeDevicePixelRatio": true,
+ "threshold": 0.01
+ }
+ }
+ },
+ "viewportWidth": 1920,
+ "viewportHeight": 1080,
+ "includeShadowDom": true,
+ "ignoreTestFiles": ["**/__snapshots__/*", "**/__image_snapshots__/*"]
+}
diff --git a/packages/techdocs-cli/cypress/.eslintrc.json b/packages/techdocs-cli/cypress/.eslintrc.json
new file mode 100644
index 0000000000..2481ac5715
--- /dev/null
+++ b/packages/techdocs-cli/cypress/.eslintrc.json
@@ -0,0 +1,21 @@
+{
+ "plugins": ["cypress"],
+ "extends": ["plugin:cypress/recommended"],
+ "rules": {
+ "jest/expect-expect": [
+ "error",
+ {
+ "assertFunctionNames": ["expect", "cy.contains", "cy.document"]
+ }
+ ],
+ "import/no-extraneous-dependencies": [
+ "error",
+ {
+ "devDependencies": true,
+ "optionalDependencies": true,
+ "peerDependencies": true,
+ "bundledDependencies": true
+ }
+ ]
+ }
+}
diff --git a/packages/techdocs-cli/cypress/fixtures/example.json b/packages/techdocs-cli/cypress/fixtures/example.json
new file mode 100644
index 0000000000..02e4254378
--- /dev/null
+++ b/packages/techdocs-cli/cypress/fixtures/example.json
@@ -0,0 +1,5 @@
+{
+ "name": "Using fixtures to represent data",
+ "email": "hello@cypress.io",
+ "body": "Fixtures are a great way to mock data for responses to routes"
+}
diff --git a/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png b/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png
new file mode 100644
index 0000000000..99fc1ea483
Binary files /dev/null and b/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png differ
diff --git a/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png b/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png
new file mode 100644
index 0000000000..e6c63d5d57
Binary files /dev/null and b/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png differ
diff --git a/packages/techdocs-cli/cypress/integration/backstage_serve.js b/packages/techdocs-cli/cypress/integration/backstage_serve.js
new file mode 100644
index 0000000000..15fc03f8f4
--- /dev/null
+++ b/packages/techdocs-cli/cypress/integration/backstage_serve.js
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+///
+describe('TechDocs Live Preview - Backstage Serve', () => {
+ it('successfully serves documentation', () => {
+ cy.visit(`${Cypress.env('backstageBaseUrl')}/docs/default/component/local`);
+ cy.contains('hello mock docs');
+ });
+
+ it('successfully navigates to sub page of documentation', () => {
+ cy.contains('SubDocs').click();
+ cy.contains('Home 2').click();
+ cy.contains(
+ 'This is an md file in another docs folder using the MkDocs Monorepo Plugin',
+ );
+ });
+
+ it('successfully renders all Backstage main elements', () => {
+ cy.contains('header', 'Live preview environment');
+ cy.get('[data-testid="sidebar-root"]')
+ .children()
+ .should('have.length.gt', 0);
+ });
+
+ it('successfully renders all extracted MkDocs main elements', () => {
+ // as it gets replaced by Backstage header
+ cy.get('.md-header').should('have.length', 0);
+ cy.get('.md-main').should('have.length', 1);
+ cy.contains(
+ '.md-main',
+ 'This is an md file in another docs folder using the MkDocs Monorepo Plugin',
+ );
+ cy.get('.md-sidebar.md-sidebar--primary').should('have.length', 1);
+ cy.get('.md-sidebar.md-sidebar--primary').should('have.length', 1);
+ cy.get('.md-footer').should('have.length', 1);
+ });
+
+ it('toMatchImageSnapshot - Backstage TechDocs Page', () => {
+ cy.visit(
+ `${Cypress.env('backstageBaseUrl')}/docs/default/component/local`,
+ ).then(() => {
+ cy.document().toMatchImageSnapshot();
+ });
+ });
+});
diff --git a/packages/techdocs-cli/cypress/integration/mkdocs_serve.js b/packages/techdocs-cli/cypress/integration/mkdocs_serve.js
new file mode 100644
index 0000000000..1ace7298ce
--- /dev/null
+++ b/packages/techdocs-cli/cypress/integration/mkdocs_serve.js
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+///
+describe('TechDocs Live Preview - MkDocs Serve', () => {
+ it('successfully serves documentation', () => {
+ cy.visit(Cypress.env('mkDocsBaseUrl'));
+ cy.contains('hello mock docs');
+ });
+
+ it('successfully navigates to sub page of documentation', () => {
+ cy.contains('SubDocs').click();
+ cy.contains('Home 2').click();
+ cy.contains(
+ 'This is an md file in another docs folder using the MkDocs Monorepo Plugin',
+ );
+ });
+
+ it('successfully renders all main elements', () => {
+ cy.get('.md-header').should('have.length', 1);
+ cy.get('.md-main').should('have.length', 1);
+ cy.contains(
+ '.md-main',
+ 'This is an md file in another docs folder using the MkDocs Monorepo Plugin',
+ );
+ cy.get('.md-sidebar.md-sidebar--primary').should('have.length', 1);
+ cy.get('.md-sidebar.md-sidebar--primary').should('have.length', 1);
+ cy.get('.md-footer').should('have.length', 1);
+ });
+
+ it('toMatchImageSnapshot - MkDocs Page', () => {
+ cy.visit(Cypress.env('mkDocsBaseUrl')).then(() => {
+ cy.document().toMatchImageSnapshot();
+ });
+ });
+});
diff --git a/packages/techdocs-cli/cypress/plugins/index.js b/packages/techdocs-cli/cypress/plugins/index.js
new file mode 100644
index 0000000000..92faabb6ad
--- /dev/null
+++ b/packages/techdocs-cli/cypress/plugins/index.js
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+// ***********************************************************
+// This example plugins/index.js can be used to load plugins
+//
+// You can change the location of this file or turn off loading
+// the plugins file with the 'pluginsFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/plugins-guide
+// ***********************************************************
+
+// This function is called when a project is opened or re-opened (e.g. due to
+// the project's config changing)
+
+const { initPlugin } = require('cypress-plugin-snapshots/plugin');
+
+/**
+ * @type {Cypress.PluginConfig}
+ */
+// eslint-disable-next-line no-unused-vars
+module.exports = (on, config) => {
+ // `on` is used to hook into various events Cypress emits
+ // `config` is the resolved Cypress config
+ initPlugin(on, config);
+ return config;
+};
diff --git a/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage Header #0.png b/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage Header #0.png
new file mode 100644
index 0000000000..867e8ddd81
Binary files /dev/null and b/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage Header #0.png differ
diff --git a/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0 (1).png b/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0 (1).png
new file mode 100644
index 0000000000..3f1078345d
Binary files /dev/null and b/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0 (1).png differ
diff --git a/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0 (2).png b/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0 (2).png
new file mode 100644
index 0000000000..c576be51c5
Binary files /dev/null and b/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0 (2).png differ
diff --git a/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png b/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png
new file mode 100644
index 0000000000..3f1078345d
Binary files /dev/null and b/packages/techdocs-cli/cypress/screenshots/backstage_serve.js/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png differ
diff --git a/packages/techdocs-cli/cypress/support/commands.js b/packages/techdocs-cli/cypress/support/commands.js
new file mode 100644
index 0000000000..a8d6a5fdb7
--- /dev/null
+++ b/packages/techdocs-cli/cypress/support/commands.js
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+// This example commands.js shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+//
+//
+// -- This is a parent command --
+// Cypress.Commands.add('login', (email, password) => { ... })
+//
+//
+// -- This is a child command --
+// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
+//
+//
+// -- This is a dual command --
+// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
+//
+//
+// -- This will overwrite an existing command --
+// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
diff --git a/packages/techdocs-cli/cypress/support/index.js b/packages/techdocs-cli/cypress/support/index.js
new file mode 100644
index 0000000000..a1a5b10ea4
--- /dev/null
+++ b/packages/techdocs-cli/cypress/support/index.js
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+// This example support/index.js is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import './commands';
+import 'cypress-plugin-snapshots/commands';
+
+// Alternatively you can use CommonJS syntax:
+// require('./commands')
diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json
index 19514b63d2..929564e01c 100644
--- a/packages/techdocs-cli/package.json
+++ b/packages/techdocs-cli/package.json
@@ -1,11 +1,14 @@
{
"name": "@techdocs/cli",
"description": "Utility CLI for managing TechDocs sites in Backstage.",
- "version": "0.8.13",
+ "version": "0.8.15",
"private": false,
"publishConfig": {
"access": "public"
},
+ "backstage": {
+ "role": "cli"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,19 +24,20 @@
"types": "",
"scripts": {
"start": "nodemon --",
- "build": "backstage-cli build --outputs cjs",
- "clean": "backstage-cli clean",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test --testPathIgnorePatterns=src/e2e.test.ts",
+ "build": "backstage-cli package build",
+ "clean": "backstage-cli package clean",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test --testPathIgnorePatterns=src/e2e.test.ts",
"test:e2e": "backstage-cli test src/e2e.test.ts",
"test:e2e:ci": "backstage-cli test --watchAll=false --ci src/e2e.test.ts",
+ "test:cypress": "cypress open",
"prepack": "./scripts/prepack.sh"
},
"bin": {
"techdocs-cli": "bin/techdocs-cli"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
+ "@backstage/cli": "^0.14.1",
"@types/commander": "^2.12.2",
"@types/fs-extra": "^9.0.6",
"@types/http-proxy": "^1.17.4",
@@ -41,9 +45,11 @@
"@types/node": "^14.14.32",
"@types/serve-handler": "^6.1.0",
"@types/webpack-env": "^1.15.3",
- "techdocs-cli-embedded-app": "link:../techdocs-cli-embedded-app",
+ "cypress": "^9.5.0",
+ "cypress-plugin-snapshots": "^1.4.4",
"find-process": "^1.4.5",
"nodemon": "^2.0.2",
+ "techdocs-cli-embedded-app": "link:../techdocs-cli-embedded-app",
"ts-node": "^10.0.0"
},
"files": [
@@ -56,11 +62,11 @@
"ext": "ts"
},
"dependencies": {
- "@backstage/backend-common": "^0.10.7",
- "@backstage/catalog-model": "^0.9.10",
- "@backstage/cli-common": "^0.1.6",
- "@backstage/config": "^0.1.13",
- "@backstage/techdocs-common": "^0.11.7",
+ "@backstage/backend-common": "^0.11.0",
+ "@backstage/catalog-model": "^0.11.0",
+ "@backstage/cli-common": "^0.1.8",
+ "@backstage/config": "^0.1.15",
+ "@backstage/techdocs-common": "^0.11.10",
"@types/dockerode": "^3.3.0",
"commander": "^6.1.0",
"dockerode": "^3.3.1",
diff --git a/packages/techdocs-cli/scripts/prepack.sh b/packages/techdocs-cli/scripts/prepack.sh
index 6b769de37c..bfd62cfd1b 100755
--- a/packages/techdocs-cli/scripts/prepack.sh
+++ b/packages/techdocs-cli/scripts/prepack.sh
@@ -23,4 +23,4 @@ TECHDOCS_CLI_EMBEDDED_APP_DIR="$TECHDOCS_CLI_DIR"/../techdocs-cli-embedded-app
echo "🚚 Copying embedded app into dist/embedded-app"
rm -rf "$TECHDOCS_CLI_DIR"/dist/embedded-app
cp -r "$TECHDOCS_CLI_EMBEDDED_APP_DIR"/dist "$TECHDOCS_CLI_DIR"/dist/embedded-app
-echo "🏁 Ready!"
+echo "🏁 Finished copying embedded app into dist/embedded-app!"
diff --git a/packages/techdocs-cli/src/commands/index.ts b/packages/techdocs-cli/src/commands/index.ts
index d4f41cf7a3..115fe8e364 100644
--- a/packages/techdocs-cli/src/commands/index.ts
+++ b/packages/techdocs-cli/src/commands/index.ts
@@ -45,7 +45,7 @@ export function registerCommands(program: CommanderStatic) {
)
.option(
'--techdocs-ref ',
- 'The repository hosting documentation source files e.g. github:https://ghe.mycompany.net.com/org/repo.' +
+ 'The repository hosting documentation source files e.g. url:https://ghe.mycompany.net.com/org/repo.' +
'\nThis value is same as the backstage.io/techdocs-ref annotation of the corresponding Backstage entity.' +
'\nIt is completely fine to skip this as it is only being used to set repo_url in mkdocs.yml if not found.\n',
)
diff --git a/packages/techdocs-cli/src/e2e.test.ts b/packages/techdocs-cli/src/e2e.test.ts
index 088dbc44b8..7cdd867d0f 100644
--- a/packages/techdocs-cli/src/e2e.test.ts
+++ b/packages/techdocs-cli/src/e2e.test.ts
@@ -58,7 +58,7 @@ const timeout = 25000;
jest.setTimeout(timeout * 2);
describe('end-to-end', () => {
- const cwd = path.resolve(__dirname, 'fixture');
+ const cwd = path.resolve(__dirname, 'example-docs');
afterEach(async () => {
// On Windows the pid of a spawned process may be wrong
diff --git a/packages/techdocs-cli/src/example-docs/.gitignore b/packages/techdocs-cli/src/example-docs/.gitignore
new file mode 100644
index 0000000000..45ddf0ae39
--- /dev/null
+++ b/packages/techdocs-cli/src/example-docs/.gitignore
@@ -0,0 +1 @@
+site/
diff --git a/packages/techdocs-cli/src/example-docs/docs/index.md b/packages/techdocs-cli/src/example-docs/docs/index.md
new file mode 100644
index 0000000000..074d3ccb3e
--- /dev/null
+++ b/packages/techdocs-cli/src/example-docs/docs/index.md
@@ -0,0 +1,92 @@
+## hello mock docs
+
+!!! test
+Testing something
+
+Abbreviations:
+Some text about MOCDOC
+
+This is a paragraph.
+{: #test_id .test_class }
+
+Apple
+: A fruit.
+
+```javascript
+import { test } from 'something';
+
+const addThingToThing = (a, b) a + b;
+```
+
+- [abc](#abc)
+- [xyz](#xyz)
+
+## abc
+
+This is a b c.
+
+## xyz
+
+This is x y z.
+
+# Emojis
+
+:bulb: :smile:
+
+# Code blocks
+
+```javascript
+import { test } from 'something';
+
+const addThingToThing = (a, b) a + b;
+```
+
+# Grouped Code blocks
+
+=== "JavaScript"
+
+ ```javascript
+ import { test } from 'something';
+
+ const addThingToThing = (a, b) a + b;
+ ```
+
+=== "Java"
+
+ ```java
+ public void function() {
+ test();
+ }
+ ```
+
+```java tab="java"
+ public void function() {
+ test();
+ }
+```
+
+```java tab="java 2"
+ public void function() {
+ test();
+ }
+```
+
+# MDX truly sane lists
+
+- attributes
+
+- customer
+ - first_name
+ - test
+ - family_name
+ - email
+- person
+ - first_name
+ - family_name
+ - birth_date
+- subscription_id
+
+- request
+
+
+*[MOCDOC]: Mock Documentation
diff --git a/packages/techdocs-cli/src/fixture/mkdocs.yml b/packages/techdocs-cli/src/example-docs/mkdocs.yml
similarity index 50%
rename from packages/techdocs-cli/src/fixture/mkdocs.yml
rename to packages/techdocs-cli/src/example-docs/mkdocs.yml
index 5d5c2a02ae..9c9406f6e6 100644
--- a/packages/techdocs-cli/src/fixture/mkdocs.yml
+++ b/packages/techdocs-cli/src/example-docs/mkdocs.yml
@@ -2,7 +2,9 @@ site_name: docs-test-fixture
site_description: Documentation site test fixture
nav:
- - HOME: README.md
+ - Home: index.md
+ - SubDocs: '!include ./sub-docs/mkdocs.yml'
+ - Plugins: '*include ./plugins/*/mkdocs.yml'
plugins:
- techdocs-core
diff --git a/packages/techdocs-cli/src/example-docs/plugins/plugin-a/docs/index.md b/packages/techdocs-cli/src/example-docs/plugins/plugin-a/docs/index.md
new file mode 100644
index 0000000000..bd8bc3a4ea
--- /dev/null
+++ b/packages/techdocs-cli/src/example-docs/plugins/plugin-a/docs/index.md
@@ -0,0 +1,4 @@
+# Plugin A
+
+This is a description of Plugin A. This file exists to prove that glob'd
+includes using the `*include` syntax work as expected.
diff --git a/packages/techdocs-cli/src/example-docs/plugins/plugin-a/mkdocs.yml b/packages/techdocs-cli/src/example-docs/plugins/plugin-a/mkdocs.yml
new file mode 100644
index 0000000000..66407d5391
--- /dev/null
+++ b/packages/techdocs-cli/src/example-docs/plugins/plugin-a/mkdocs.yml
@@ -0,0 +1,5 @@
+site_name: Plugin A
+site_description: A description of Plugin A
+
+nav:
+ - Introduction: index.md
diff --git a/packages/techdocs-cli/src/example-docs/plugins/plugin-b/docs/index.md b/packages/techdocs-cli/src/example-docs/plugins/plugin-b/docs/index.md
new file mode 100644
index 0000000000..93e545252f
--- /dev/null
+++ b/packages/techdocs-cli/src/example-docs/plugins/plugin-b/docs/index.md
@@ -0,0 +1,4 @@
+# Plugin B
+
+This is a description of Plugin B. This file exists to prove that glob'd
+includes using the `*include` syntax work as expected.
diff --git a/packages/techdocs-cli/src/example-docs/plugins/plugin-b/mkdocs.yml b/packages/techdocs-cli/src/example-docs/plugins/plugin-b/mkdocs.yml
new file mode 100644
index 0000000000..81580c33af
--- /dev/null
+++ b/packages/techdocs-cli/src/example-docs/plugins/plugin-b/mkdocs.yml
@@ -0,0 +1,5 @@
+site_name: Plugin B
+site_description: A description of Plugin B
+
+nav:
+ - Introduction: index.md
diff --git a/packages/techdocs-cli/src/example-docs/sub-docs/docs/index.md b/packages/techdocs-cli/src/example-docs/sub-docs/docs/index.md
new file mode 100644
index 0000000000..65c6644ef8
--- /dev/null
+++ b/packages/techdocs-cli/src/example-docs/sub-docs/docs/index.md
@@ -0,0 +1 @@
+### This is an md file in another docs folder using the [MkDocs Monorepo Plugin](https://github.com/spotify/mkdocs-monorepo-plugin)
diff --git a/packages/techdocs-cli/src/example-docs/sub-docs/mkdocs.yml b/packages/techdocs-cli/src/example-docs/sub-docs/mkdocs.yml
new file mode 100644
index 0000000000..4490ddbefa
--- /dev/null
+++ b/packages/techdocs-cli/src/example-docs/sub-docs/mkdocs.yml
@@ -0,0 +1,4 @@
+site_name: subdocs
+
+nav:
+ - Home 2: 'index.md'
diff --git a/packages/techdocs-cli/src/fixture/docs/README.md b/packages/techdocs-cli/src/fixture/docs/README.md
deleted file mode 100644
index c32f73f6f4..0000000000
--- a/packages/techdocs-cli/src/fixture/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Test Fixture
diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md
index 44fbec4171..c99295e8db 100644
--- a/packages/techdocs-common/CHANGELOG.md
+++ b/packages/techdocs-common/CHANGELOG.md
@@ -1,5 +1,44 @@
# @backstage/techdocs-common
+## 0.11.10
+
+### Patch Changes
+
+- 209fd128e6: Updated usage of `github:` location types in docs to use `url:` instead.
+- 13ef228d03: Clean up the API interface for TechDocs common library.
+- Updated dependencies
+ - @backstage/backend-common@0.11.0
+ - @backstage/catalog-model@0.11.0
+ - @backstage/integration@0.7.5
+
+## 0.11.9
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+- Updated dependencies
+ - @backstage/backend-common@0.10.9
+ - @backstage/catalog-model@0.10.1
+ - @backstage/config@0.1.15
+ - @backstage/errors@0.2.2
+ - @backstage/integration@0.7.4
+ - @backstage/search-common@0.2.4
+
+## 0.11.8
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef`
+- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`.
+- Updated dependencies
+ - @backstage/backend-common@0.10.8
+ - @backstage/errors@0.2.1
+ - @backstage/integration@0.7.3
+ - @backstage/catalog-model@0.10.0
+ - @backstage/config@0.1.14
+ - @backstage/search-common@0.2.3
+
## 0.11.7
### Patch Changes
diff --git a/packages/techdocs-common/README.md b/packages/techdocs-common/README.md
index e4889d6f79..bbaac85e9b 100644
--- a/packages/techdocs-common/README.md
+++ b/packages/techdocs-common/README.md
@@ -39,7 +39,7 @@ Currently the build process is split up in these three stages.
- Generators
- Publishers
-Preparers read your entity data and creates a working directory with your documentation source code. For example if you have set your `backstage.io/techdocs-ref` to `github:https://github.com/backstage/backstage.git` it will clone that repository to a temp folder and pass that on to the generator.
+Preparers read your entity data and creates a working directory with your documentation source code. For example if you have set your `backstage.io/techdocs-ref` to `url:https://github.com/backstage/backstage.git` it will clone that repository to a temp folder and pass that on to the generator.
Generators takes the prepared source and runs the `techdocs-container` on it. It then passes on the output folder of that build to the publisher.
diff --git a/packages/techdocs-common/api-report.md b/packages/techdocs-common/api-report.md
index 281accca30..7c4fc95abb 100644
--- a/packages/techdocs-common/api-report.md
+++ b/packages/techdocs-common/api-report.md
@@ -17,38 +17,37 @@ import { ScmIntegrationRegistry } from '@backstage/integration';
import { UrlReader } from '@backstage/backend-common';
import { Writable } from 'stream';
-// Warning: (ae-missing-release-tag) "DirectoryPreparer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export class DirectoryPreparer implements PreparerBase {
- constructor(config: Config, _logger: Logger_2, reader: UrlReader);
- // Warning: (ae-forgotten-export) The symbol "PreparerResponse" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
- prepare(
- entity: Entity,
- options?: {
- logger?: Logger_2;
- etag?: string;
- },
- ): Promise;
+ // @deprecated
+ constructor(config: Config, _logger: Logger_2 | null, reader: UrlReader);
+ static fromConfig(
+ config: Config,
+ { logger, reader }: PreparerConfig,
+ ): DirectoryPreparer;
+ prepare(entity: Entity, options?: PreparerOptions): Promise;
}
-// Warning: (ae-missing-release-tag) "GeneratorBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
+export type ETag = string;
+
+// @public
export type GeneratorBase = {
run(opts: GeneratorRunOptions): Promise;
};
-// Warning: (ae-missing-release-tag) "GeneratorBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export type GeneratorBuilder = {
register(protocol: SupportedGeneratorKey, generator: GeneratorBase): void;
get(entity: Entity): GeneratorBase;
};
+// @public
+export type GeneratorOptions = {
+ containerRunner: ContainerRunner;
+ logger: Logger_2;
+};
+
// @public
export type GeneratorRunOptions = {
inputDir: string;
@@ -59,11 +58,8 @@ export type GeneratorRunOptions = {
logStream?: Writable;
};
-// Warning: (ae-missing-release-tag) "Generators" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export class Generators implements GeneratorBuilder {
- // (undocumented)
static fromConfig(
config: Config,
options: {
@@ -71,15 +67,11 @@ export class Generators implements GeneratorBuilder {
containerRunner: ContainerRunner;
},
): Promise;
- // (undocumented)
get(entity: Entity): GeneratorBase;
- // (undocumented)
register(generatorKey: SupportedGeneratorKey, generator: GeneratorBase): void;
}
-// Warning: (ae-missing-release-tag) "getDocFilesFromRepository" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export const getDocFilesFromRepository: (
reader: UrlReader,
entity: Entity,
@@ -91,78 +83,74 @@ export const getDocFilesFromRepository: (
| undefined,
) => Promise;
-// Warning: (ae-missing-release-tag) "getLocationForEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export const getLocationForEntity: (
entity: Entity,
scmIntegration: ScmIntegrationRegistry,
) => ParsedLocationAnnotation;
-// Warning: (ae-missing-release-tag) "ParsedLocationAnnotation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
+export type MigrateRequest = {
+ removeOriginal?: boolean;
+ concurrency?: number;
+};
+
+// @public
export type ParsedLocationAnnotation = {
type: RemoteProtocol;
target: string;
};
-// Warning: (ae-missing-release-tag) "parseReferenceAnnotation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export const parseReferenceAnnotation: (
annotationName: string,
entity: Entity,
) => ParsedLocationAnnotation;
-// Warning: (ae-missing-release-tag) "PreparerBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export type PreparerBase = {
- prepare(
- entity: Entity,
- options?: {
- logger?: Logger_2;
- etag?: string;
- },
- ): Promise;
+ prepare(entity: Entity, options?: PreparerOptions): Promise;
};
-// Warning: (ae-missing-release-tag) "PreparerBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export type PreparerBuilder = {
register(protocol: RemoteProtocol, preparer: PreparerBase): void;
get(entity: Entity): PreparerBase;
};
-// Warning: (ae-missing-release-tag) "Preparers" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
+export type PreparerConfig = {
+ logger: Logger_2;
+ reader: UrlReader;
+};
+
+// @public
+export type PreparerOptions = {
+ logger?: Logger_2;
+ etag?: ETag;
+};
+
+// @public
+export type PreparerResponse = {
+ preparedDir: string;
+ etag: ETag;
+};
+
+// @public
export class Preparers implements PreparerBuilder {
- // Warning: (ae-forgotten-export) The symbol "factoryOptions" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
static fromConfig(
- config: Config,
- { logger, reader }: factoryOptions,
+ backstageConfig: Config,
+ { logger, reader }: PreparerConfig,
): Promise;
- // (undocumented)
get(entity: Entity): PreparerBase;
- // (undocumented)
register(protocol: RemoteProtocol, preparer: PreparerBase): void;
}
-// Warning: (ae-missing-release-tag) "Publisher" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export class Publisher {
- // Warning: (ae-forgotten-export) The symbol "factoryOptions" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
static fromConfig(
config: Config,
- { logger, discovery }: factoryOptions_2,
+ { logger, discovery }: PublisherFactory,
): Promise;
}
@@ -172,15 +160,16 @@ export interface PublisherBase {
fetchTechDocsMetadata(entityName: EntityName): Promise;
getReadiness(): Promise;
hasDocsBeenGenerated(entityName: Entity): Promise;
- // Warning: (ae-forgotten-export) The symbol "MigrateRequest" needs to be exported by the entry point index.d.ts
migrateDocsCase?(migrateRequest: MigrateRequest): Promise;
- // Warning: (ae-forgotten-export) The symbol "PublishRequest" needs to be exported by the entry point index.d.ts
- // Warning: (ae-forgotten-export) The symbol "PublishResponse" needs to be exported by the entry point index.d.ts
publish(request: PublishRequest): Promise;
}
-// Warning: (ae-missing-release-tag) "PublisherType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
+// @public
+export type PublisherFactory = {
+ logger: Logger_2;
+ discovery: PluginEndpointDiscovery;
+};
+
// @public
export type PublisherType =
| 'local'
@@ -189,37 +178,40 @@ export type PublisherType =
| 'azureBlobStorage'
| 'openStackSwift';
+// @public
+export type PublishRequest = {
+ entity: Entity;
+ directory: string;
+};
+
+// @public
+export type PublishResponse = {
+ remoteUrl?: string;
+ objects?: string[];
+} | void;
+
// @public
export type ReadinessResponse = {
isAvailable: boolean;
};
-// Warning: (ae-missing-release-tag) "RemoteProtocol" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export type RemoteProtocol = 'url' | 'dir';
-// Warning: (ae-missing-release-tag) "TechDocsDocument" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
+export type SupportedGeneratorKey = 'techdocs' | string;
+
+// @public
export interface TechDocsDocument extends IndexableDocument {
- // (undocumented)
kind: string;
- // (undocumented)
lifecycle: string;
- // (undocumented)
name: string;
- // (undocumented)
namespace: string;
- // (undocumented)
owner: string;
- // (undocumented)
path: string;
}
-// Warning: (ae-missing-release-tag) "TechdocsGenerator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export class TechdocsGenerator implements GeneratorBase {
constructor(options: {
logger: Logger_2;
@@ -227,21 +219,14 @@ export class TechdocsGenerator implements GeneratorBase {
config: Config;
scmIntegrations: ScmIntegrationRegistry;
});
- static readonly defaultDockerImage = 'spotify/techdocs:v0.3.6';
- // (undocumented)
+ static readonly defaultDockerImage = 'spotify/techdocs:v0.3.7';
static fromConfig(
config: Config,
- options: {
- containerRunner: ContainerRunner;
- logger: Logger_2;
- },
+ options: GeneratorOptions,
): TechdocsGenerator;
- // (undocumented)
run(options: GeneratorRunOptions): Promise;
}
-// Warning: (ae-missing-release-tag) "TechDocsMetadata" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export type TechDocsMetadata = {
site_name: string;
@@ -251,8 +236,6 @@ export type TechDocsMetadata = {
files?: string[];
};
-// Warning: (ae-missing-release-tag) "transformDirLocation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export const transformDirLocation: (
entity: Entity,
@@ -263,21 +246,11 @@ export const transformDirLocation: (
target: string;
};
-// Warning: (ae-missing-release-tag) "UrlPreparer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export class UrlPreparer implements PreparerBase {
+ // @deprecated
constructor(reader: UrlReader, logger: Logger_2);
- // (undocumented)
- prepare(
- entity: Entity,
- options?: {
- etag?: string;
- },
- ): Promise;
+ static fromConfig({ reader, logger }: PreparerConfig): UrlPreparer;
+ prepare(entity: Entity, options?: PreparerOptions): Promise;
}
-
-// Warnings were encountered during analysis:
-//
-// src/stages/generate/types.d.ts:45:5 - (ae-forgotten-export) The symbol "SupportedGeneratorKey" needs to be exported by the entry point index.d.ts
```
diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json
index f45f842100..731e967637 100644
--- a/packages/techdocs-common/package.json
+++ b/packages/techdocs-common/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/techdocs-common",
"description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli",
- "version": "0.11.7",
+ "version": "0.11.10",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -10,6 +10,9 @@
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "node-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -25,12 +28,13 @@
"dist"
],
"scripts": {
- "build": "backstage-cli build --outputs cjs,types",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"bugs": {
"url": "https://github.com/backstage/backstage/issues"
@@ -38,12 +42,12 @@
"dependencies": {
"@azure/identity": "^2.0.1",
"@azure/storage-blob": "^12.5.0",
- "@backstage/backend-common": "^0.10.7",
- "@backstage/catalog-model": "^0.9.10",
- "@backstage/config": "^0.1.13",
- "@backstage/errors": "^0.2.0",
- "@backstage/search-common": "^0.2.2",
- "@backstage/integration": "^0.7.2",
+ "@backstage/backend-common": "^0.11.0",
+ "@backstage/catalog-model": "^0.11.0",
+ "@backstage/config": "^0.1.15",
+ "@backstage/errors": "^0.2.2",
+ "@backstage/search-common": "^0.2.4",
+ "@backstage/integration": "^0.7.5",
"@google-cloud/storage": "^5.6.0",
"@trendyol-js/openstack-swift-sdk": "^0.0.5",
"@types/express": "^4.17.6",
@@ -60,7 +64,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2",
+ "@backstage/cli": "^0.14.1",
"@types/fs-extra": "^9.0.5",
"@types/js-yaml": "^4.0.0",
"@types/mime-types": "^2.1.0",
diff --git a/packages/techdocs-common/src/helpers.ts b/packages/techdocs-common/src/helpers.ts
index ccf1256381..39a1f4c666 100644
--- a/packages/techdocs-common/src/helpers.ts
+++ b/packages/techdocs-common/src/helpers.ts
@@ -26,11 +26,21 @@ import path from 'path';
import { Logger } from 'winston';
import { PreparerResponse, RemoteProtocol } from './stages/prepare/types';
+/**
+ * Parsed location annotation
+ * @public
+ */
export type ParsedLocationAnnotation = {
type: RemoteProtocol;
target: string;
};
+/**
+ * Returns a parset locations annotation
+ * @public
+ * @param annotationName - The name of the annotation in the entity metadata
+ * @param entity - A TechDocs entity instance
+ */
export const parseReferenceAnnotation = (
annotationName: string,
entity: Entity,
@@ -56,7 +66,7 @@ export const parseReferenceAnnotation = (
* location, it returns a `url` location with a resolved target that points to the
* targeted subfolder. If the entity was registered by a `file` location, it returns
* an absolute `dir` location.
- *
+ * @public
* @param entity - the entity with annotations
* @param dirAnnotation - the parsed techdocs-ref annotation of type 'dir'
* @param scmIntegrations - access to the scmIntegration to do url transformations
@@ -101,6 +111,12 @@ export const transformDirLocation = (
}
};
+/**
+ * Returns a entity reference based on the TechDocs annotation type
+ * @public
+ * @param entity - A TechDocs instance
+ * @param scmIntegration - An implementation for SCM integration API
+ */
export const getLocationForEntity = (
entity: Entity,
scmIntegration: ScmIntegrationRegistry,
@@ -120,6 +136,13 @@ export const getLocationForEntity = (
}
};
+/**
+ * Returns a preparer response {@link PreparerResponse}
+ * @public
+ * @param reader - Read a tree of files from a repository
+ * @param entity - A TechDocs entity instance
+ * @param opts - Options for configuring the reader, e.g. logger, etag, etc.
+ */
export const getDocFilesFromRepository = async (
reader: UrlReader,
entity: Entity,
diff --git a/packages/techdocs-common/src/stages/generate/generators.ts b/packages/techdocs-common/src/stages/generate/generators.ts
index de39d4e7c3..630fccfa44 100644
--- a/packages/techdocs-common/src/stages/generate/generators.ts
+++ b/packages/techdocs-common/src/stages/generate/generators.ts
@@ -26,9 +26,18 @@ import {
SupportedGeneratorKey,
} from './types';
+/**
+ * Collection of docs generators
+ * @public
+ */
export class Generators implements GeneratorBuilder {
private generatorMap = new Map();
+ /**
+ * Returns a generators instance containing a generator for TechDocs
+ * @param config - A Backstage configuration
+ * @param options - Options to configure the TechDocs generator
+ */
static async fromConfig(
config: Config,
options: { logger: Logger; containerRunner: ContainerRunner },
@@ -41,10 +50,19 @@ export class Generators implements GeneratorBuilder {
return generators;
}
+ /**
+ * Register a generator in the generators collection
+ * @param generatorKey - Unique identifier for the generator
+ * @param generator - The generator instance to register
+ */
register(generatorKey: SupportedGeneratorKey, generator: GeneratorBase) {
this.generatorMap.set(generatorKey, generator);
}
+ /**
+ * Returns the generator for a given TechDocs entity
+ * @param entity - A TechDocs entity instance
+ */
get(entity: Entity): GeneratorBase {
const generatorKey = getGeneratorKey(entity);
const generator = this.generatorMap.get(generatorKey);
diff --git a/packages/techdocs-common/src/stages/generate/index.ts b/packages/techdocs-common/src/stages/generate/index.ts
index eb015a5c2d..1c20c58887 100644
--- a/packages/techdocs-common/src/stages/generate/index.ts
+++ b/packages/techdocs-common/src/stages/generate/index.ts
@@ -16,7 +16,9 @@
export { TechdocsGenerator } from './techdocs';
export { Generators } from './generators';
export type {
- GeneratorBuilder,
GeneratorBase,
+ GeneratorOptions,
+ GeneratorBuilder,
GeneratorRunOptions,
+ SupportedGeneratorKey,
} from './types';
diff --git a/packages/techdocs-common/src/stages/generate/techdocs.ts b/packages/techdocs-common/src/stages/generate/techdocs.ts
index 5cf992092c..baa2e008a1 100644
--- a/packages/techdocs-common/src/stages/generate/techdocs.ts
+++ b/packages/techdocs-common/src/stages/generate/techdocs.ts
@@ -34,26 +34,33 @@ import {
import {
GeneratorBase,
GeneratorConfig,
+ GeneratorOptions,
GeneratorRunInType,
GeneratorRunOptions,
} from './types';
import { ForwardedError } from '@backstage/errors';
+/**
+ * Generates documentation files
+ * @public
+ */
export class TechdocsGenerator implements GeneratorBase {
/**
* The default docker image (and version) used to generate content. Public
* and static so that techdocs-common consumers can use the same version.
*/
- public static readonly defaultDockerImage = 'spotify/techdocs:v0.3.6';
+ public static readonly defaultDockerImage = 'spotify/techdocs:v0.3.7';
private readonly logger: Logger;
private readonly containerRunner: ContainerRunner;
private readonly options: GeneratorConfig;
private readonly scmIntegrations: ScmIntegrationRegistry;
- static fromConfig(
- config: Config,
- options: { containerRunner: ContainerRunner; logger: Logger },
- ) {
+ /**
+ * Returns a instance of TechDocs generator
+ * @param config - A Backstage configuration
+ * @param options - Options to configure the generator
+ */
+ static fromConfig(config: Config, options: GeneratorOptions) {
const { containerRunner, logger } = options;
const scmIntegrations = ScmIntegrations.fromConfig(config);
return new TechdocsGenerator({
@@ -76,6 +83,7 @@ export class TechdocsGenerator implements GeneratorBase {
this.scmIntegrations = options.scmIntegrations;
}
+ /** {@inheritDoc GeneratorBase.run} */
public async run(options: GeneratorRunOptions): Promise {
const {
inputDir,
diff --git a/packages/techdocs-common/src/stages/generate/types.ts b/packages/techdocs-common/src/stages/generate/types.ts
index 2a090d5584..2ff3064991 100644
--- a/packages/techdocs-common/src/stages/generate/types.ts
+++ b/packages/techdocs-common/src/stages/generate/types.ts
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+import { ContainerRunner } from '@backstage/backend-common';
import { Entity } from '@backstage/catalog-model';
import { Writable } from 'stream';
import { Logger } from 'winston';
@@ -22,6 +23,15 @@ import { ParsedLocationAnnotation } from '../../helpers';
// Determines where the generator will be run
export type GeneratorRunInType = 'docker' | 'local';
+/**
+ * Options for building generators
+ * @public
+ */
+export type GeneratorOptions = {
+ containerRunner: ContainerRunner;
+ logger: Logger;
+};
+
/**
* The techdocs generator configurations options.
*/
@@ -51,18 +61,27 @@ export type GeneratorRunOptions = {
logStream?: Writable;
};
+/**
+ * Generates documentation files
+ * @public
+ */
export type GeneratorBase = {
- // Runs the generator with the values
+ /**
+ * Runs the generator with the values
+ * @public
+ */
run(opts: GeneratorRunOptions): Promise;
};
/**
* List of supported generator options
+ * @public
*/
export type SupportedGeneratorKey = 'techdocs' | string;
/**
* The generator builder holds the generator ready for run time
+ * @public
*/
export type GeneratorBuilder = {
register(protocol: SupportedGeneratorKey, generator: GeneratorBase): void;
diff --git a/packages/techdocs-common/src/stages/prepare/dir.test.ts b/packages/techdocs-common/src/stages/prepare/dir.test.ts
index 019bf51fe9..2bf3fe29fc 100644
--- a/packages/techdocs-common/src/stages/prepare/dir.test.ts
+++ b/packages/techdocs-common/src/stages/prepare/dir.test.ts
@@ -86,7 +86,7 @@ describe('directory preparer', () => {
);
});
- it('should reject when managed-by-location is a git repository', async () => {
+ it('should reject when managed-by-location has an unknown type', async () => {
const directoryPreparer = new DirectoryPreparer(
mockConfig,
logger,
@@ -95,12 +95,12 @@ describe('directory preparer', () => {
const mockEntity = createMockEntity({
'backstage.io/managed-by-location':
- 'github:https://github.com/backstage/backstage/blob/master/catalog-info.yaml',
+ 'does-not-exist:https://github.com/backstage/backstage/blob/master/catalog-info.yaml',
'backstage.io/techdocs-ref': 'dir:./docs',
});
await expect(directoryPreparer.prepare(mockEntity)).rejects.toThrow(
- /Unable to resolve location type github/,
+ /Unable to resolve location type does-not-exist/,
);
});
});
diff --git a/packages/techdocs-common/src/stages/prepare/dir.ts b/packages/techdocs-common/src/stages/prepare/dir.ts
index ade0b00162..42bfa5b903 100644
--- a/packages/techdocs-common/src/stages/prepare/dir.ts
+++ b/packages/techdocs-common/src/stages/prepare/dir.ts
@@ -24,20 +24,43 @@ import {
} from '@backstage/integration';
import { Logger } from 'winston';
import { parseReferenceAnnotation, transformDirLocation } from '../../helpers';
-import { PreparerBase, PreparerResponse } from './types';
+import {
+ PreparerBase,
+ PreparerConfig,
+ PreparerOptions,
+ PreparerResponse,
+} from './types';
+/**
+ * Preparer used to retrieve documentation files from a local directory
+ * @public
+ */
export class DirectoryPreparer implements PreparerBase {
private readonly scmIntegrations: ScmIntegrationRegistry;
private readonly reader: UrlReader;
- constructor(config: Config, _logger: Logger, reader: UrlReader) {
+ /** @deprecated use static fromConfig method instead */
+ constructor(config: Config, _logger: Logger | null, reader: UrlReader) {
this.reader = reader;
this.scmIntegrations = ScmIntegrations.fromConfig(config);
}
+ /**
+ * Returns a directory preparer instance
+ * @param config - A backstage config
+ * @param options - A directory preparer options containing a logger and reader
+ */
+ static fromConfig(
+ config: Config,
+ { logger, reader }: PreparerConfig,
+ ): DirectoryPreparer {
+ return new DirectoryPreparer(config, logger, reader);
+ }
+
+ /** {@inheritDoc PreparerBase.prepare} */
async prepare(
entity: Entity,
- options?: { logger?: Logger; etag?: string },
+ options?: PreparerOptions,
): Promise {
const annotation = parseReferenceAnnotation(
'backstage.io/techdocs-ref',
diff --git a/packages/techdocs-common/src/stages/prepare/index.ts b/packages/techdocs-common/src/stages/prepare/index.ts
index f129bf5315..3593b49c86 100644
--- a/packages/techdocs-common/src/stages/prepare/index.ts
+++ b/packages/techdocs-common/src/stages/prepare/index.ts
@@ -16,4 +16,12 @@
export { DirectoryPreparer } from './dir';
export { UrlPreparer } from './url';
export { Preparers } from './preparers';
-export type { PreparerBuilder, PreparerBase, RemoteProtocol } from './types';
+export type {
+ PreparerBase,
+ PreparerBuilder,
+ PreparerConfig,
+ PreparerOptions,
+ PreparerResponse,
+ RemoteProtocol,
+ ETag,
+} from './types';
diff --git a/packages/techdocs-common/src/stages/prepare/preparers.ts b/packages/techdocs-common/src/stages/prepare/preparers.ts
index 75c9a7f23b..575294e91a 100644
--- a/packages/techdocs-common/src/stages/prepare/preparers.ts
+++ b/packages/techdocs-common/src/stages/prepare/preparers.ts
@@ -13,26 +13,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { UrlReader } from '@backstage/backend-common';
import { Entity } from '@backstage/catalog-model';
import { Config } from '@backstage/config';
-import { Logger } from 'winston';
import { parseReferenceAnnotation } from '../../helpers';
import { DirectoryPreparer } from './dir';
import { UrlPreparer } from './url';
-import { PreparerBase, PreparerBuilder, RemoteProtocol } from './types';
-
-type factoryOptions = {
- logger: Logger;
- reader: UrlReader;
-};
+import {
+ PreparerBase,
+ PreparerBuilder,
+ PreparerConfig,
+ RemoteProtocol,
+} from './types';
+/**
+ * Collection of docs preparers (dir and url)
+ * @public
+ */
export class Preparers implements PreparerBuilder {
private preparerMap = new Map();
+ /**
+ * Returns a generators instance containing a generator for TechDocs
+ * @public
+ * @param backstageConfig - A Backstage configuration
+ * @param preparerConfig - Options to configure preparers
+ */
static async fromConfig(
- config: Config,
- { logger, reader }: factoryOptions,
+ backstageConfig: Config,
+ { logger, reader }: PreparerConfig,
): Promise {
const preparers = new Preparers();
@@ -43,16 +51,30 @@ export class Preparers implements PreparerBuilder {
* Dir preparer is a syntactic sugar for users to define techdocs-ref annotation.
* When using dir preparer, the docs will be fetched using URL Reader.
*/
- const directoryPreparer = new DirectoryPreparer(config, logger, reader);
+ const directoryPreparer = new DirectoryPreparer(
+ backstageConfig,
+ logger,
+ reader,
+ );
preparers.register('dir', directoryPreparer);
return preparers;
}
+ /**
+ * Register a preparer in the preparers collection
+ * @param protocol - url or dir to associate with preparer
+ * @param preparer - The preparer instance to set
+ */
register(protocol: RemoteProtocol, preparer: PreparerBase) {
this.preparerMap.set(protocol, preparer);
}
+ /**
+ * Returns the preparer for a given TechDocs entity
+ * @param entity - A TechDocs entity instance
+ * @returns
+ */
get(entity: Entity): PreparerBase {
const { type } = parseReferenceAnnotation(
'backstage.io/techdocs-ref',
diff --git a/packages/techdocs-common/src/stages/prepare/types.ts b/packages/techdocs-common/src/stages/prepare/types.ts
index 5c219752fa..aee9d216ab 100644
--- a/packages/techdocs-common/src/stages/prepare/types.ts
+++ b/packages/techdocs-common/src/stages/prepare/types.ts
@@ -15,19 +15,58 @@
*/
import type { Entity } from '@backstage/catalog-model';
+import { UrlReader } from '@backstage/backend-common';
import { Logger } from 'winston';
+/**
+ * A unique identifier of the tree blob, usually the commit SHA or etag from the target.
+ * @public
+ */
+export type ETag = string;
+
+/**
+ * Options for building preparers
+ * @public
+ */
+export type PreparerConfig = {
+ logger: Logger;
+ reader: UrlReader;
+};
+
+/**
+ * Options for configuring the content preparation process.
+ * @public
+ */
+export type PreparerOptions = {
+ /**
+ * An instance of the logger
+ */
+ logger?: Logger;
+ /**
+ * see {@link ETag}
+ */
+ etag?: ETag;
+};
+
+/**
+ * Result of the preparation step.
+ * @public
+ */
export type PreparerResponse = {
/**
* The path to directory where the tree is downloaded.
*/
preparedDir: string;
/**
- * A unique identifier of the tree blob, usually the commit SHA or etag from the target.
+ * see {@link ETag}
*/
- etag: string;
+ etag: ETag;
};
+/**
+ * Definition of a TechDocs preparer
+ * @public
+ */
export type PreparerBase = {
/**
* Given an Entity definition from the Software Catalog, go and prepare a directory
@@ -38,15 +77,20 @@ export type PreparerBase = {
* updated since the last build.
* @throws `NotModifiedError` when the prepared directory has not been changed since the last build.
*/
- prepare(
- entity: Entity,
- options?: { logger?: Logger; etag?: string },
- ): Promise;
+ prepare(entity: Entity, options?: PreparerOptions): Promise;
};
+/**
+ * Definition for a TechDocs preparer builder
+ * @public
+ */
export type PreparerBuilder = {
register(protocol: RemoteProtocol, preparer: PreparerBase): void;
get(entity: Entity): PreparerBase;
};
+/**
+ * Location where documentation files are stored
+ * @public
+ */
export type RemoteProtocol = 'url' | 'dir';
diff --git a/packages/techdocs-common/src/stages/prepare/url.ts b/packages/techdocs-common/src/stages/prepare/url.ts
index cd4a8860e4..8026dca41e 100644
--- a/packages/techdocs-common/src/stages/prepare/url.ts
+++ b/packages/techdocs-common/src/stages/prepare/url.ts
@@ -19,20 +19,39 @@ import { UrlReader } from '@backstage/backend-common';
import { Entity } from '@backstage/catalog-model';
import { Logger } from 'winston';
import { getDocFilesFromRepository } from '../../helpers';
-import { PreparerBase, PreparerResponse } from './types';
+import {
+ PreparerBase,
+ PreparerConfig,
+ PreparerOptions,
+ PreparerResponse,
+} from './types';
+/**
+ * Preparer used to retrieve documentation files from a remote repository
+ * @public
+ */
export class UrlPreparer implements PreparerBase {
private readonly logger: Logger;
private readonly reader: UrlReader;
+ /** @deprecated use static fromConfig method instead */
constructor(reader: UrlReader, logger: Logger) {
this.logger = logger;
this.reader = reader;
}
+ /**
+ * Returns a directory preparer instance
+ * @param config - A URL preparer config containing the a logger and reader
+ */
+ static fromConfig({ reader, logger }: PreparerConfig): UrlPreparer {
+ return new UrlPreparer(reader, logger);
+ }
+
+ /** {@inheritDoc PreparerBase.prepare} */
async prepare(
entity: Entity,
- options?: { etag?: string },
+ options?: PreparerOptions,
): Promise {
try {
return await getDocFilesFromRepository(this.reader, entity, {
diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.ts b/packages/techdocs-common/src/stages/publish/googleStorage.ts
index ba70c36e27..c3d9d3330b 100644
--- a/packages/techdocs-common/src/stages/publish/googleStorage.ts
+++ b/packages/techdocs-common/src/stages/publish/googleStorage.ts
@@ -83,7 +83,7 @@ export class GoogleGCSPublish implements PublisherBase {
const credentials = config.getOptionalString(
'techdocs.publisher.googleGcs.credentials',
);
- let credentialsJson = {};
+ let credentialsJson: any = {};
if (credentials) {
try {
credentialsJson = JSON.parse(credentials);
@@ -96,6 +96,7 @@ export class GoogleGCSPublish implements PublisherBase {
const storageClient = new Storage({
...(credentials && {
+ projectId: credentialsJson.project_id,
credentials: credentialsJson,
}),
});
diff --git a/packages/techdocs-common/src/stages/publish/index.ts b/packages/techdocs-common/src/stages/publish/index.ts
index 083cf2b8ff..c6f86f6bc1 100644
--- a/packages/techdocs-common/src/stages/publish/index.ts
+++ b/packages/techdocs-common/src/stages/publish/index.ts
@@ -17,6 +17,10 @@ export { Publisher } from './publish';
export type {
PublisherBase,
PublisherType,
- TechDocsMetadata,
+ PublisherFactory,
+ PublishRequest,
+ PublishResponse,
+ MigrateRequest,
ReadinessResponse,
+ TechDocsMetadata,
} from './types';
diff --git a/packages/techdocs-common/src/stages/publish/publish.ts b/packages/techdocs-common/src/stages/publish/publish.ts
index eb9e3104bf..bc7f50b5a3 100644
--- a/packages/techdocs-common/src/stages/publish/publish.ts
+++ b/packages/techdocs-common/src/stages/publish/publish.ts
@@ -14,29 +14,28 @@
* limitations under the License.
*/
-import { PluginEndpointDiscovery } from '@backstage/backend-common';
import { Config } from '@backstage/config';
-import { Logger } from 'winston';
import { AwsS3Publish } from './awsS3';
import { AzureBlobStoragePublish } from './azureBlobStorage';
import { GoogleGCSPublish } from './googleStorage';
import { LocalPublish } from './local';
import { OpenStackSwiftPublish } from './openStackSwift';
-import { PublisherBase, PublisherType } from './types';
-
-type factoryOptions = {
- logger: Logger;
- discovery: PluginEndpointDiscovery;
-};
+import { PublisherFactory, PublisherBase, PublisherType } from './types';
/**
* Factory class to create a TechDocs publisher based on defined publisher type in app config.
* Uses `techdocs.publisher.type`.
+ * @public
*/
export class Publisher {
+ /**
+ * Returns a instance of TechDocs publisher
+ * @param config - A Backstage configuration
+ * @param options - Options for configuring the publisher factory
+ */
static async fromConfig(
config: Config,
- { logger, discovery }: factoryOptions,
+ { logger, discovery }: PublisherFactory,
): Promise {
const publisherType = (config.getOptionalString(
'techdocs.publisher.type',
diff --git a/packages/techdocs-common/src/stages/publish/types.ts b/packages/techdocs-common/src/stages/publish/types.ts
index 37075a35a4..c6ad032484 100644
--- a/packages/techdocs-common/src/stages/publish/types.ts
+++ b/packages/techdocs-common/src/stages/publish/types.ts
@@ -14,10 +14,22 @@
* limitations under the License.
*/
import { Entity, EntityName } from '@backstage/catalog-model';
+import { PluginEndpointDiscovery } from '@backstage/backend-common';
+import { Logger } from 'winston';
import express from 'express';
+/**
+ * Options for building publishers
+ * @public
+ */
+export type PublisherFactory = {
+ logger: Logger;
+ discovery: PluginEndpointDiscovery;
+};
+
/**
* Key for all the different types of TechDocs publishers that are supported.
+ * @public
*/
export type PublisherType =
| 'local'
@@ -26,6 +38,10 @@ export type PublisherType =
| 'azureBlobStorage'
| 'openStackSwift';
+/**
+ * Request publish definition
+ * @public
+ */
export type PublishRequest = {
entity: Entity;
/* The Path to the directory where the generated files are stored. */
@@ -35,6 +51,7 @@ export type PublishRequest = {
/**
* Response containing metadata about where files were published and what may
* have been published or updated.
+ * @public
*/
export type PublishResponse = {
/**
@@ -51,7 +68,6 @@ export type PublishResponse = {
/**
* Result for the validation check.
- *
* @public
*/
export type ReadinessResponse = {
@@ -62,6 +78,7 @@ export type ReadinessResponse = {
/**
* Type to hold metadata found in techdocs_metadata.json and associated with each site
* @param etag - ETag of the resource used to generate the site. Usually the latest commit sha of the source repository.
+ * @public
*/
export type TechDocsMetadata = {
site_name: string;
@@ -71,6 +88,10 @@ export type TechDocsMetadata = {
files?: string[];
};
+/**
+ * TechDocs entity triplet migration request
+ * @public
+ */
export type MigrateRequest = {
/**
* Whether or not to remove the source file. Defaults to false (acting like a
diff --git a/packages/techdocs-common/src/techdocsTypes.ts b/packages/techdocs-common/src/techdocsTypes.ts
index 4aa3972b31..0b722f4da5 100644
--- a/packages/techdocs-common/src/techdocsTypes.ts
+++ b/packages/techdocs-common/src/techdocsTypes.ts
@@ -16,11 +16,33 @@
import { IndexableDocument } from '@backstage/search-common';
+/**
+ * TechDocs indexable document interface
+ * @public
+ */
export interface TechDocsDocument extends IndexableDocument {
+ /**
+ * Entity kind
+ */
kind: string;
+ /**
+ * Entity metadata namespace
+ */
namespace: string;
+ /**
+ * Entity metadata name
+ */
name: string;
+ /**
+ * Entity lifecycle
+ */
lifecycle: string;
+ /**
+ * Entity owner
+ */
owner: string;
+ /**
+ * Entity path
+ */
path: string;
}
diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md
index 35c9ebfb35..4de90a4aa7 100644
--- a/packages/test-utils/CHANGELOG.md
+++ b/packages/test-utils/CHANGELOG.md
@@ -1,5 +1,29 @@
# @backstage/test-utils
+## 0.2.6
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/core-plugin-api@0.7.0
+ - @backstage/core-app-api@0.5.4
+ - @backstage/plugin-permission-react@0.3.2
+
+## 0.2.5
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/core-app-api@0.5.3
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/plugin-permission-common@0.5.0
+ - @backstage/plugin-permission-react@0.3.1
+ - @backstage/config@0.1.14
+ - @backstage/theme@0.2.15
+ - @backstage/types@0.1.2
+
## 0.2.4
### Patch Changes
diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json
index 67b68e08cc..5465f7783a 100644
--- a/packages/test-utils/package.json
+++ b/packages/test-utils/package.json
@@ -1,13 +1,16 @@
{
"name": "@backstage/test-utils",
"description": "Utilities to test Backstage plugins and apps.",
- "version": "0.2.4",
+ "version": "0.2.6",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "web-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,21 +24,22 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build --outputs types,esm",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/config": "^0.1.13",
- "@backstage/core-app-api": "^0.5.2",
- "@backstage/core-plugin-api": "^0.6.0",
- "@backstage/plugin-permission-common": "^0.4.0",
- "@backstage/plugin-permission-react": "^0.3.0",
- "@backstage/theme": "^0.2.14",
- "@backstage/types": "^0.1.1",
+ "@backstage/config": "^0.1.15",
+ "@backstage/core-app-api": "^0.5.4",
+ "@backstage/core-plugin-api": "^0.7.0",
+ "@backstage/plugin-permission-common": "^0.5.1",
+ "@backstage/plugin-permission-react": "^0.3.2",
+ "@backstage/theme": "^0.2.15",
+ "@backstage/types": "^0.1.3",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.10.1",
@@ -51,7 +55,7 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0",
+ "@backstage/cli": "^0.14.1",
"@types/jest": "^26.0.7",
"@types/node": "^14.14.32",
"msw": "^0.35.0"
diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md
index cfa6ee3633..5c3e8cf5d6 100644
--- a/packages/theme/CHANGELOG.md
+++ b/packages/theme/CHANGELOG.md
@@ -1,5 +1,11 @@
# @backstage/theme
+## 0.2.15
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+
## 0.2.14
### Patch Changes
diff --git a/packages/theme/package.json b/packages/theme/package.json
index 2846db2805..17404e8db0 100644
--- a/packages/theme/package.json
+++ b/packages/theme/package.json
@@ -1,13 +1,16 @@
{
"name": "@backstage/theme",
"description": "material-ui theme for use with Backstage.",
- "version": "0.2.14",
+ "version": "0.2.15",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "web-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,17 +24,19 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build --outputs types,esm",
- "lint": "backstage-cli lint",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start",
+ "test": "backstage-cli package test"
},
"dependencies": {
"@material-ui/core": "^4.12.2"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0"
+ "@backstage/cli": "^0.14.0"
},
"files": [
"dist"
diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md
new file mode 100644
index 0000000000..238c61f68f
--- /dev/null
+++ b/packages/types/CHANGELOG.md
@@ -0,0 +1,13 @@
+# @backstage/types
+
+## 0.1.3
+
+### Patch Changes
+
+- Fix for the previous release with missing type declarations.
+
+## 0.1.2
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
diff --git a/packages/types/package.json b/packages/types/package.json
index ae18fe519d..ab0740d568 100644
--- a/packages/types/package.json
+++ b/packages/types/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/types",
"description": "Common TypeScript types used within Backstage",
- "version": "0.1.1",
+ "version": "0.1.3",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -12,6 +12,9 @@
"module": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "common-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -22,16 +25,16 @@
"backstage"
],
"scripts": {
- "build": "backstage-cli build",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean"
},
"dependencies": {},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0",
+ "@backstage/cli": "^0.14.0",
"@types/zen-observable": "^0.8.0",
"zen-observable": "^0.8.15"
},
diff --git a/packages/version-bridge/CHANGELOG.md b/packages/version-bridge/CHANGELOG.md
index e079cd6c61..fe131f7987 100644
--- a/packages/version-bridge/CHANGELOG.md
+++ b/packages/version-bridge/CHANGELOG.md
@@ -1,5 +1,11 @@
# @backstage/version-bridge
+## 0.1.2
+
+### Patch Changes
+
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+
## 0.1.1
### Patch Changes
diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json
index 6989aec3cf..485b0417cf 100644
--- a/packages/version-bridge/package.json
+++ b/packages/version-bridge/package.json
@@ -1,13 +1,16 @@
{
"name": "@backstage/version-bridge",
"description": "Utilities used by @backstage packages to support multiple concurrent versions",
- "version": "0.1.1",
+ "version": "0.1.2",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
+ "backstage": {
+ "role": "web-library"
+ },
"homepage": "https://backstage.io",
"repository": {
"type": "git",
@@ -21,19 +24,20 @@
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
- "build": "backstage-cli build --outputs types,esm",
- "lint": "backstage-cli lint",
- "test": "backstage-cli test",
- "prepack": "backstage-cli prepack",
- "postpack": "backstage-cli postpack",
- "clean": "backstage-cli clean"
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack",
+ "clean": "backstage-cli package clean",
+ "start": "backstage-cli package start"
},
"peerDependencies": {
"@types/react": "^16.13.1 || ^17.0.0",
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.13.2-next.0",
+ "@backstage/cli": "^0.14.0",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/react-hooks": "^7.0.2"
diff --git a/plugins/airbrake-backend/.eslintrc.js b/plugins/airbrake-backend/.eslintrc.js
new file mode 100644
index 0000000000..16a033dbc6
--- /dev/null
+++ b/plugins/airbrake-backend/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+ extends: [require.resolve('@backstage/cli/config/eslint.backend')],
+};
diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md
new file mode 100644
index 0000000000..148dbdeb07
--- /dev/null
+++ b/plugins/airbrake-backend/CHANGELOG.md
@@ -0,0 +1,25 @@
+# @backstage/plugin-airbrake-backend
+
+## 0.2.0
+
+### Minor Changes
+
+- da78e79a94: This marks the first release where the Airbrake plugin is useable. Airbrake frontend and Airbrake backend work with each other. Currently just a summary of the latest Airbrakes is shown on Backstage.
+
+### Patch Changes
+
+- 0045270527: Make config optional
+- Updated dependencies
+ - @backstage/backend-common@0.11.0
+
+## 0.1.0
+
+### Minor Changes
+
+- a5aebe3e30: Created the Airbrake backend plugin that proxies requests to the Airbrake API
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/backend-common@0.10.8
+ - @backstage/config@0.1.14
diff --git a/plugins/airbrake-backend/README.md b/plugins/airbrake-backend/README.md
new file mode 100644
index 0000000000..9c9b56ade4
--- /dev/null
+++ b/plugins/airbrake-backend/README.md
@@ -0,0 +1,32 @@
+# airbrake-backend
+
+The Airbrake backend plugin provides a simple proxy to the Airbrake API while hiding away the secret API key from the frontend.
+
+## How to use
+
+See the [Airbrake plugin instructions](../airbrake/README.md#how-to-use).
+
+## Local Development
+
+This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
+
+1. Add the required config to your `app-config.local.yaml`:
+
+ ```yaml
+ airbrake:
+ apiKey: ${AIRBRAKE_API_KEY}
+ ```
+
+2. Set the environment variable `AIRBRAKE_API_KEY` with your [API
+ key](https://airbrake.io/docs/api/#authentication). You can also write it
+ directly into the config file above for convenience - but beware of
+ accidentally leaking the key.
+
+3. Go into the plugin's directory and run it in standalone mode by running `yarn start`.
+
+Access it from http://localhost:7007/api/airbrake. Or use the Airbrake plugin which will talk to it automatically.
+
+Here are some example endpoints:
+
+- http://localhost:7007/api/airbrake/health
+- http://localhost:7007/api/airbrake/api/v4/projects
diff --git a/plugins/airbrake-backend/api-report.md b/plugins/airbrake-backend/api-report.md
new file mode 100644
index 0000000000..b9e9a50e0b
--- /dev/null
+++ b/plugins/airbrake-backend/api-report.md
@@ -0,0 +1,26 @@
+## API Report File for "@backstage/plugin-airbrake-backend"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+import { Config } from '@backstage/config';
+import express from 'express';
+import { Logger as Logger_2 } from 'winston';
+
+// @public
+export interface AirbrakeConfig {
+ apiKey: string;
+}
+
+// @public
+export function createRouter(options: RouterOptions): Promise;
+
+// @public
+export function extractAirbrakeConfig(config: Config): AirbrakeConfig;
+
+// @public
+export interface RouterOptions {
+ airbrakeConfig: AirbrakeConfig;
+ logger: Logger_2;
+}
+```
diff --git a/plugins/airbrake-backend/config.d.ts b/plugins/airbrake-backend/config.d.ts
new file mode 100644
index 0000000000..a21f609550
--- /dev/null
+++ b/plugins/airbrake-backend/config.d.ts
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export interface Config {
+ /** Configuration options for the Airbrake plugin */
+ airbrake?: {
+ /**
+ * The API Key to authenticate requests. More details on how to get this
+ * here: https://airbrake.io/docs/api/#authentication
+ *
+ * @visibility secret
+ */
+ apiKey: string;
+ };
+}
diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json
new file mode 100644
index 0000000000..2ee36eefb7
--- /dev/null
+++ b/plugins/airbrake-backend/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "@backstage/plugin-airbrake-backend",
+ "version": "0.2.0",
+ "main": "src/index.ts",
+ "types": "src/index.ts",
+ "license": "Apache-2.0",
+ "publishConfig": {
+ "access": "public",
+ "main": "dist/index.cjs.js",
+ "types": "dist/index.d.ts"
+ },
+ "scripts": {
+ "start": "backstage-cli backend:dev",
+ "build": "backstage-cli backend:build",
+ "lint": "backstage-cli lint",
+ "test": "backstage-cli test",
+ "prepack": "backstage-cli prepack",
+ "postpack": "backstage-cli postpack",
+ "clean": "backstage-cli clean"
+ },
+ "dependencies": {
+ "@backstage/backend-common": "^0.11.0",
+ "@backstage/config": "^0.1.15",
+ "@types/express": "*",
+ "express": "^4.17.1",
+ "express-promise-router": "^4.1.0",
+ "http-proxy-middleware": "^2.0.0",
+ "winston": "^3.2.1",
+ "cross-fetch": "^3.0.6",
+ "yn": "^4.0.0"
+ },
+ "devDependencies": {
+ "@backstage/cli": "^0.14.1",
+ "@types/http-proxy-middleware": "^0.19.3",
+ "@types/supertest": "^2.0.8",
+ "supertest": "^6.1.6",
+ "msw": "^0.35.0"
+ },
+ "files": [
+ "dist",
+ "config.d.ts"
+ ],
+ "configSchema": "config.d.ts"
+}
diff --git a/plugins/airbrake-backend/src/config/ExtractAirbrakeConfig.test.ts b/plugins/airbrake-backend/src/config/ExtractAirbrakeConfig.test.ts
new file mode 100644
index 0000000000..53d744b9ee
--- /dev/null
+++ b/plugins/airbrake-backend/src/config/ExtractAirbrakeConfig.test.ts
@@ -0,0 +1,38 @@
+/*
+ * 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 { ConfigReader } from '@backstage/config';
+import { extractAirbrakeConfig } from './ExtractAirbrakeConfig';
+
+describe('ExtractAirbrakeConfig', () => {
+ it('gets the API key', () => {
+ const config = new ConfigReader({
+ airbrake: {
+ apiKey: 'fakeApiKey',
+ },
+ });
+
+ const airbrakeConfig = extractAirbrakeConfig(config);
+ expect(airbrakeConfig.apiKey).toStrictEqual('fakeApiKey');
+ });
+
+ it('fails for missing keys', () => {
+ expect(() => extractAirbrakeConfig(new ConfigReader({}))).toThrow();
+ expect(() =>
+ extractAirbrakeConfig(new ConfigReader({ airbrake: {} })),
+ ).toThrow();
+ });
+});
diff --git a/plugins/airbrake-backend/src/config/ExtractAirbrakeConfig.ts b/plugins/airbrake-backend/src/config/ExtractAirbrakeConfig.ts
new file mode 100644
index 0000000000..de6a31feec
--- /dev/null
+++ b/plugins/airbrake-backend/src/config/ExtractAirbrakeConfig.ts
@@ -0,0 +1,42 @@
+/*
+ * 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 { Config } from '@backstage/config';
+
+/**
+ * The configuration needed for the airbrake-backend plugin
+ *
+ * @public
+ */
+export interface AirbrakeConfig {
+ /**
+ * The API Key to authenticate requests. More details on how to get this here: https://airbrake.io/docs/api/#authentication
+ */
+ apiKey: string;
+}
+
+/**
+ * Extract the Airbrake config from a config object
+ *
+ * @public
+ *
+ * @param config - The config object to extract from
+ */
+export function extractAirbrakeConfig(config: Config): AirbrakeConfig {
+ return {
+ apiKey: config.getString('airbrake.apiKey'),
+ };
+}
diff --git a/plugins/scaffolder/src/components/fields/TextValuePicker/index.ts b/plugins/airbrake-backend/src/config/index.ts
similarity index 85%
rename from plugins/scaffolder/src/components/fields/TextValuePicker/index.ts
rename to plugins/airbrake-backend/src/config/index.ts
index 8ab810b6ed..60d60c2761 100644
--- a/plugins/scaffolder/src/components/fields/TextValuePicker/index.ts
+++ b/plugins/airbrake-backend/src/config/index.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2021 The Backstage Authors
+ * 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.
@@ -13,4 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-export { TextValuePicker } from './TextValuePicker';
+
+export * from './ExtractAirbrakeConfig';
diff --git a/plugins/airbrake-backend/src/index.ts b/plugins/airbrake-backend/src/index.ts
new file mode 100644
index 0000000000..f4ec6008c2
--- /dev/null
+++ b/plugins/airbrake-backend/src/index.ts
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+/**
+ * The Airbrake Backend plugin used by \@backstage/plugin-airbrake
+ *
+ * @packageDocumentation
+ */
+
+export * from './service/router';
+export * from './config';
diff --git a/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.test.tsx b/plugins/airbrake-backend/src/run.ts
similarity index 51%
rename from plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.test.tsx
rename to plugins/airbrake-backend/src/run.ts
index a621eb281c..0a3ed2b7f0 100644
--- a/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.test.tsx
+++ b/plugins/airbrake-backend/src/run.ts
@@ -14,19 +14,20 @@
* limitations under the License.
*/
-import React from 'react';
-import { EntityAirbrakeContent } from './EntityAirbrakeContent';
-import exampleData from './example-data.json';
-import { renderInTestApp } from '@backstage/test-utils';
+import { getRootLogger } from '@backstage/backend-common';
+import yn from 'yn';
+import { startStandaloneServer } from './service/standaloneServer';
-describe('EntityAirbrakeContent', () => {
- it('renders all errors sent from Airbrake', async () => {
- const table = await renderInTestApp();
- expect(exampleData.groups.length).toBeGreaterThan(0);
- for (const group of exampleData.groups) {
- expect(
- await table.getByText(group.errors[0].message),
- ).toBeInTheDocument();
- }
- });
+const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
+const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
+const logger = getRootLogger();
+
+startStandaloneServer({ port, enableCors, logger }).catch(err => {
+ logger.error(err);
+ process.exit(1);
+});
+
+process.on('SIGINT', () => {
+ logger.info('CTRL+C pressed; exiting.');
+ process.exit(0);
});
diff --git a/plugins/airbrake-backend/src/service/router.test.ts b/plugins/airbrake-backend/src/service/router.test.ts
new file mode 100644
index 0000000000..7ccafd7eba
--- /dev/null
+++ b/plugins/airbrake-backend/src/service/router.test.ts
@@ -0,0 +1,92 @@
+/*
+ * 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 '@backstage/backend-common';
+import express from 'express';
+import request from 'supertest';
+import { ConfigReader } from '@backstage/config';
+import {
+ createRouter,
+ generateAirbrakePathRewrite,
+ RouterOptions,
+} from './router';
+import { AirbrakeConfig, extractAirbrakeConfig } from '../config';
+import * as winston from 'winston';
+
+describe('createRouter', () => {
+ let app: express.Express;
+ let airbrakeConfig: AirbrakeConfig;
+ let voidLogger: winston.Logger;
+
+ beforeEach(async () => {
+ jest.resetAllMocks();
+
+ voidLogger = getVoidLogger();
+ const config = new ConfigReader({
+ airbrake: {
+ apiKey: 'fakeApiKey',
+ },
+ });
+ airbrakeConfig = extractAirbrakeConfig(config);
+
+ const router = await createRouter({
+ logger: voidLogger,
+ airbrakeConfig,
+ });
+ app = express().use(router);
+ });
+
+ describe('GET /health', () => {
+ it('returns ok', async () => {
+ const response = await request(app).get('/health');
+
+ expect(response.status).toEqual(200);
+ expect(response.body).toEqual({ status: 'ok' });
+ });
+ });
+
+ describe('GET /api', () => {
+ it('appends the API Key properly with no other url parameters', () => {
+ const options: RouterOptions = {
+ logger: voidLogger,
+ airbrakeConfig,
+ };
+ const pathRewrite = generateAirbrakePathRewrite(options) as (
+ path: string,
+ ) => string;
+
+ expect(pathRewrite('/airbrake-backend/api/v4/random/endpoint')).toBe(
+ '/v4/random/endpoint?key=fakeApiKey',
+ );
+ });
+
+ it('appends the API Key properly despite there being other URL parameters', () => {
+ const options: RouterOptions = {
+ logger: voidLogger,
+ airbrakeConfig,
+ };
+ const pathRewrite = generateAirbrakePathRewrite(options) as (
+ path: string,
+ ) => string;
+
+ expect(
+ pathRewrite(
+ '/airbrake-backend/api/v4/random/endpoint?param1=123¶m2=abc',
+ ),
+ ).toBe('/v4/random/endpoint?param1=123¶m2=abc&key=fakeApiKey');
+ });
+ });
+});
diff --git a/plugins/airbrake-backend/src/service/router.ts b/plugins/airbrake-backend/src/service/router.ts
new file mode 100644
index 0000000000..b870eb5c13
--- /dev/null
+++ b/plugins/airbrake-backend/src/service/router.ts
@@ -0,0 +1,96 @@
+/*
+ * 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 { errorHandler } from '@backstage/backend-common';
+import express from 'express';
+import Router from 'express-promise-router';
+import { Logger } from 'winston';
+import { createProxyMiddleware } from 'http-proxy-middleware';
+import { AirbrakeConfig } from '../config';
+import { Options } from 'http-proxy-middleware/dist/types';
+
+/**
+ * The router options that are needed when creating a router.
+ *
+ * @public
+ */
+export interface RouterOptions {
+ /**
+ * A logger object
+ */
+ logger: Logger;
+
+ /**
+ * The Airbrake config obtained from {@link extractAirbrakeConfig}
+ */
+ airbrakeConfig: AirbrakeConfig;
+}
+
+/**
+ * Mainly used internally to generate the path.
+ *
+ * @internal
+ *
+ * @param options - Router options
+ */
+export const generateAirbrakePathRewrite = (
+ options: RouterOptions,
+): Options['pathRewrite'] => {
+ const apiKey = options.airbrakeConfig.apiKey;
+
+ return path => {
+ let newPath = path.replace(/.+?(\/api)/g, '');
+ if (newPath.includes('?')) {
+ newPath += `&key=${apiKey}`;
+ } else {
+ newPath += `?key=${apiKey}`;
+ }
+ return newPath;
+ };
+};
+
+/**
+ * Create the Airbrake Router, used for making API calls to the Airbrake API.
+ *
+ * @public
+ *
+ * @param options - Router options
+ */
+export async function createRouter(
+ options: RouterOptions,
+): Promise {
+ const { logger } = options;
+
+ const router = Router();
+ router.use(express.json());
+
+ router.get('/health', (_, response) => {
+ logger.info('PONG!');
+ response.send({ status: 'ok' });
+ });
+
+ router.use(
+ '/api',
+ createProxyMiddleware({
+ target: 'https://api.airbrake.io/api',
+ changeOrigin: true,
+ pathRewrite: generateAirbrakePathRewrite(options),
+ }),
+ );
+
+ router.use(errorHandler());
+ return router;
+}
diff --git a/plugins/airbrake-backend/src/service/standaloneServer.ts b/plugins/airbrake-backend/src/service/standaloneServer.ts
new file mode 100644
index 0000000000..6825e60a0a
--- /dev/null
+++ b/plugins/airbrake-backend/src/service/standaloneServer.ts
@@ -0,0 +1,61 @@
+/*
+ * 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 {
+ createServiceBuilder,
+ loadBackendConfig,
+} from '@backstage/backend-common';
+import { Server } from 'http';
+import { Logger } from 'winston';
+import { createRouter } from './router';
+import { extractAirbrakeConfig } from '../config';
+
+export interface ServerOptions {
+ port: number;
+ enableCors: boolean;
+ logger: Logger;
+}
+
+export async function startStandaloneServer(
+ options: ServerOptions,
+): Promise {
+ const logger = options.logger.child({ service: 'airbrake-backend' });
+ const config = await loadBackendConfig({ logger, argv: process.argv });
+ const airbrakeConfig = extractAirbrakeConfig(config);
+ logger.debug('Starting application server...');
+ const router = await createRouter({
+ logger,
+ airbrakeConfig,
+ });
+
+ let service = createServiceBuilder(module)
+ .setPort(options.port)
+ .addRouter('/api/airbrake', router);
+ if (options.enableCors) {
+ logger.info('CORS is enabled, limiting to localhost with port 3000');
+ service = service.enableCors({ origin: 'http://localhost:3000' });
+ } else {
+ logger.info('CORS is disabled, allowing all origins');
+ service = service.enableCors({ origin: '*' });
+ }
+
+ return await service.start().catch(err => {
+ logger.error(err);
+ process.exit(1);
+ });
+}
+
+module.hot?.accept();
diff --git a/plugins/airbrake-backend/src/setupTests.ts b/plugins/airbrake-backend/src/setupTests.ts
new file mode 100644
index 0000000000..d3232290a7
--- /dev/null
+++ b/plugins/airbrake-backend/src/setupTests.ts
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+export {};
diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md
index df784d0030..685ef4c0e7 100644
--- a/plugins/airbrake/CHANGELOG.md
+++ b/plugins/airbrake/CHANGELOG.md
@@ -1,5 +1,40 @@
# @backstage/plugin-airbrake
+## 0.3.0
+
+### Minor Changes
+
+- da78e79a94: This marks the first release where the Airbrake plugin is useable. Airbrake frontend and Airbrake backend work with each other. Currently just a summary of the latest Airbrakes is shown on Backstage.
+
+### Patch Changes
+
+- Updated dependencies
+ - @backstage/core-components@0.8.10
+ - @backstage/plugin-catalog-react@0.7.0
+ - @backstage/catalog-model@0.11.0
+ - @backstage/core-plugin-api@0.7.0
+ - @backstage/dev-utils@0.2.23
+ - @backstage/test-utils@0.2.6
+
+## 0.2.0
+
+### Minor Changes
+
+- 9e505d20a3: API connectivity has added, but currently will only work by running it standalone on a browser with CORS disabled.
+
+### Patch Changes
+
+- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
+- c77c5c7eb6: Added `backstage.role` to `package.json`
+- Updated dependencies
+ - @backstage/core-components@0.8.9
+ - @backstage/core-plugin-api@0.6.1
+ - @backstage/test-utils@0.2.5
+ - @backstage/plugin-catalog-react@0.6.15
+ - @backstage/catalog-model@0.10.0
+ - @backstage/dev-utils@0.2.22
+ - @backstage/theme@0.2.15
+
## 0.1.3
### Patch Changes
diff --git a/plugins/airbrake/README.md b/plugins/airbrake/README.md
index de041fb3ec..d5ea9bb006 100644
--- a/plugins/airbrake/README.md
+++ b/plugins/airbrake/README.md
@@ -1,13 +1,75 @@
# Airbrake
-Welcome to the Airbrake plugin!
+The Airbrake plugin provides connectivity between Backstage and Airbrake (https://airbrake.io/).
-This is a plugin providing connectivity between Backstage and Airbrake (https://airbrake.io/).
+## How to use
-_This plugin is currently not fit for use as it is work in progress_
+1. Install the Frontend plugin:
-## Getting started
+ ```bash
+ # From your Backstage root directory
+ cd packages/app
+ yarn add @backstage/plugin-airbrake
+ ```
-You can serve the plugin in isolation by running `yarn start` in the plugin directory.
-This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
-It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory.
+2. Install the Backend plugin:
+
+ ```bash
+ # From your Backstage root directory
+ cd packages/backend
+ yarn add @backstage/plugin-airbrake-backend
+ ```
+
+3. Add the `EntityAirbrakeContent` to `packages/app/src/components/catalog/EntityPage.tsx`:
+
+ ```typescript jsx
+ import { EntityAirbrakeContent } from '@backstage/plugin-airbrake';
+
+ const serviceEntityPage = (
+
+
+
+
+
+ );
+ ```
+
+4. Setup the Backend code in `packages/backend/src/index.ts`:
+
+ ```typescript
+ import {
+ createRouter as createAirbrakeRouter,
+ extractAirbrakeConfig,
+ } from '@backstage/plugin-airbrake-backend';
+
+ async function main() {
+ //... After const config = await loadBackendConfig({ ...
+
+ const airbrakeRouter = await createAirbrakeRouter({
+ logger,
+ airbrakeConfig: extractAirbrakeConfig(config),
+ });
+
+ const service = createServiceBuilder(module)
+ // ... Add the airbrakeRouter here
+ .addRouter('/api/airbrake', airbrakeRouter);
+ }
+ ```
+
+5. Add this config as a top level section in your `app-config.yaml`:
+
+ ```yaml
+ airbrake:
+ apiKey: ${AIRBRAKE_API_KEY}
+ ```
+
+6. Set an environment variable `AIRBRAKE_API_KEY` with your [API key](https://airbrake.io/docs/api/#authentication)
+ before starting Backstage backend.
+
+## Local Development
+
+Start this plugin in standalone mode by running `yarn start` inside the plugin directory. This method of serving the plugin provides quicker
+iteration speed and a faster startup and hot reloads. It is only meant for local development, and the setup for it can
+be found inside the [/dev](./dev) directory.
+
+> A mock API will be used to run it in standalone. If you want to talk to the real API [follow the instructions to start up Airbrake Backend in standalone](../airbrake-backend/README.md#local-development).
diff --git a/plugins/airbrake/api-report.md b/plugins/airbrake/api-report.md
index c01aa938ae..bd274e604d 100644
--- a/plugins/airbrake/api-report.md
+++ b/plugins/airbrake/api-report.md
@@ -8,9 +8,7 @@
import { BackstagePlugin } from '@backstage/core-plugin-api';
import { RouteRef } from '@backstage/core-plugin-api';
-// Warning: (ae-missing-release-tag) "airbrakePlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export const airbrakePlugin: BackstagePlugin<
{
root: RouteRef;
@@ -18,10 +16,6 @@ export const airbrakePlugin: BackstagePlugin<
{}
>;
-// Warning: (ae-missing-release-tag) "EntityAirbrakeContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export const EntityAirbrakeContent: () => JSX.Element;
-
-// (No @packageDocumentation comment for this package)
```
diff --git a/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx b/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx
new file mode 100644
index 0000000000..7a4ee42f14
--- /dev/null
+++ b/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx
@@ -0,0 +1,79 @@
+/*
+ * 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 {
+ createTheme,
+ makeStyles,
+ MuiThemeProvider,
+ TextField,
+} from '@material-ui/core';
+import { Context } from '../ContextProvider';
+
+const useStyles = makeStyles({
+ root: {
+ display: 'flex',
+ gap: '1em',
+ flexWrap: 'wrap',
+ },
+});
+
+const textFieldTheme = createTheme({
+ palette: {
+ type: 'dark',
+ primary: {
+ light: '#fff',
+ main: '#fff',
+ dark: '#fff',
+ contrastText: '#fff',
+ },
+ secondary: {
+ light: '#fff',
+ main: '#fff',
+ dark: '#fff',
+ contrastText: '#fff',
+ },
+ action: {
+ disabled: '#fff',
+ },
+ text: {
+ primary: '#fff',
+ secondary: '#fff',
+ },
+ },
+});
+
+export const ApiBar = () => {
+ const classes = useStyles();
+
+ return (
+
+ {value => (
+