diff --git a/.changeset/brave-goats-rush.md b/.changeset/brave-goats-rush.md new file mode 100644 index 0000000000..8a14f8ea00 --- /dev/null +++ b/.changeset/brave-goats-rush.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-node': minor +--- + +Deprecated the `LocationSpec` type. It got moved from this package to the `@backstage/plugin-catalog-common` so make sure imports are updated. diff --git a/.changeset/brown-grapes-battle.md b/.changeset/brown-grapes-battle.md index f94c938b02..21b345fc83 100644 --- a/.changeset/brown-grapes-battle.md +++ b/.changeset/brown-grapes-battle.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-backend-module-bitbucket-cloud': minor +'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch --- Bitbucket Cloud provider: Add option to configure schedule via `app-config.yaml` instead of in code. diff --git a/.changeset/clever-clocks-drive.md b/.changeset/clever-clocks-drive.md new file mode 100644 index 0000000000..0834133e36 --- /dev/null +++ b/.changeset/clever-clocks-drive.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-catalog-graph': patch +--- + +Added `curve` prop to the `DependencyGraph` component to select the type of layout diff --git a/.changeset/cuddly-ways-fail.md b/.changeset/cuddly-ways-fail.md new file mode 100644 index 0000000000..bb1b356036 --- /dev/null +++ b/.changeset/cuddly-ways-fail.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Make the `/next` scaffolder work end to end with the old `TaskPage` view diff --git a/.changeset/curvy-pets-wash.md b/.changeset/curvy-pets-wash.md new file mode 100644 index 0000000000..4c824f9ef4 --- /dev/null +++ b/.changeset/curvy-pets-wash.md @@ -0,0 +1,13 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Added a new method `addLocationAnalyzers` to the `CatalogBuilder`. With this you can add location analyzers to your catalog. These analyzers will be used by the /analyze-location endpoint to decide if the provided URL contains any catalog-info.yaml files already or not. + +Moved the following types from this package to `@backstage/plugin-catalog-backend`. + +- AnalyzeLocationResponse +- AnalyzeLocationRequest +- AnalyzeLocationExistingEntity +- AnalyzeLocationGenerateEntity +- AnalyzeLocationEntityField diff --git a/.changeset/early-rocks-smell.md b/.changeset/early-rocks-smell.md new file mode 100644 index 0000000000..e35554f03a --- /dev/null +++ b/.changeset/early-rocks-smell.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-bazaar': patch +--- + +Added a `Overview Card` for either latest or random projects. Changed `ProjectPreview.tsx` so it take `gridSize` and `useTablePagination` as props. diff --git a/.changeset/famous-ligers-repair.md b/.changeset/famous-ligers-repair.md new file mode 100644 index 0000000000..bc3780cba7 --- /dev/null +++ b/.changeset/famous-ligers-repair.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +--- + +`GitHubEntityProvider`: Add option to configure schedule via `app-config.yaml` instead of in code. + +Please find how to configure the schedule at the config at +https://backstage.io/docs/integrations/github/discovery diff --git a/.changeset/five-tables-grow.md b/.changeset/five-tables-grow.md new file mode 100644 index 0000000000..982b17b97b --- /dev/null +++ b/.changeset/five-tables-grow.md @@ -0,0 +1,11 @@ +--- +'@backstage/plugin-catalog-common': patch +--- + +Moved the following types from `@backstage/plugin-catalog-backend` to this package. + +- AnalyzeLocationResponse +- AnalyzeLocationRequest +- AnalyzeLocationExistingEntity +- AnalyzeLocationGenerateEntity +- AnalyzeLocationEntityField diff --git a/.changeset/fresh-donuts-arrive.md b/.changeset/fresh-donuts-arrive.md new file mode 100644 index 0000000000..55a85533b8 --- /dev/null +++ b/.changeset/fresh-donuts-arrive.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-backend-module-bitbucket': patch +--- + +Deprecate `@backstage/plugin-catalog-backend-module-bitbucket`. + +Please migrate to `@backstage/plugin-catalog-backend-module-bitbucket-cloud` +or `@backstage/plugin-catalog-backend-module-bitbucket-server` instead. diff --git a/.changeset/fuzzy-dolls-shake.md b/.changeset/fuzzy-dolls-shake.md new file mode 100644 index 0000000000..35ebcf6103 --- /dev/null +++ b/.changeset/fuzzy-dolls-shake.md @@ -0,0 +1,21 @@ +--- +'@backstage/plugin-catalog-import': minor +--- + +**Breaking** +Moved the code search for the existing catalog-info.yaml files to the backend from the frontend. It means it will use the configured GitHub integration's credentials. + +Add the following to your `CatalogBuilder` to have the repo URL ingestion working again. + +```ts +// catalog.ts +import { GitHubLocationAnalyzer } from '@backstage/plugin-catalog-backend-module-github'; +... + builder.addLocationAnalyzers( + new GitHubLocationAnalyzer({ + discovery: env.discovery, + config: env.config, + }), + ); +... +``` diff --git a/.changeset/great-numbers-reply.md b/.changeset/great-numbers-reply.md new file mode 100644 index 0000000000..b72b05debf --- /dev/null +++ b/.changeset/great-numbers-reply.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Fix BitBucket server integration diff --git a/.changeset/kind-bees-suffer.md b/.changeset/kind-bees-suffer.md new file mode 100644 index 0000000000..79e9c0a027 --- /dev/null +++ b/.changeset/kind-bees-suffer.md @@ -0,0 +1,30 @@ +--- +'@backstage/plugin-permission-common': minor +'@backstage/plugin-permission-node': minor +--- + +**BREAKING**: When defining permission rules, it's now necessary to provide a [ZodSchema](https://github.com/colinhacks/zod) that specifies the parameters the rule expects. This has been added to help better describe the parameters in the response of the metadata endpoint and to validate the parameters before a rule is executed. + +To help with this, we have also made a change to the API of permission rules. Before, the permission rules `toQuery` and `apply` signature expected parameters to be separate arguments, like so... + +```ts +createPermissionRule({ + apply: (resource, foo, bar) => true, + toQuery: (foo, bar) => {}, +}); +``` + +The API has now changed to expect the parameters as a single object + +```ts +createPermissionRule({ + paramSchema: z.object({ + foo: z.string().describe('Foo value to match'), + bar: z.string().describe('Bar value to match'), + }), + apply: (resource, { foo, bar }) => true, + toQuery: ({ foo, bar }) => {}, +}); +``` + +One final change made is to limit the possible values for a parameter to primitives and arrays of primitives. diff --git a/.changeset/lucky-beans-bathe.md b/.changeset/lucky-beans-bathe.md new file mode 100644 index 0000000000..b425a29599 --- /dev/null +++ b/.changeset/lucky-beans-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Bump to `react-jsonschema-form@v5-beta` for the `NextRouter` under `@alpha` exports diff --git a/.changeset/moody-carrots-shout.md b/.changeset/moody-carrots-shout.md new file mode 100644 index 0000000000..486590e0ba --- /dev/null +++ b/.changeset/moody-carrots-shout.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +--- + +Added `GitHubLocationAnalyzer`. This can be used to add to the `CatalogBuilder`. When added this will be used by `RepoLocationAnalyzer` to figure out if the given URL that you are trying to import from the /catalog-import page already contains catalog-info.yaml files. diff --git a/.changeset/old-frogs-invent.md b/.changeset/old-frogs-invent.md new file mode 100644 index 0000000000..b1e77fa369 --- /dev/null +++ b/.changeset/old-frogs-invent.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +--- + +Use schedule from config at backend module. + +Also, it removes `GithubEntityProviderCatalogModuleOptions` +in favor of config-only for the backend module setup +like at other similar modules. diff --git a/.changeset/pre.json b/.changeset/pre.json index c5f8b30596..dafb8797e2 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -1,5 +1,5 @@ { - "mode": "pre", + "mode": "exit", "tag": "next", "initialVersions": { "example-app": "0.2.75", @@ -177,47 +177,68 @@ }, "changesets": [ "blue-lions-greet", + "brave-goats-rush", "brave-peaches-brush", "breezy-pots-worry", "bright-rules-shout", + "brown-grapes-battle", "calm-moose-fetch", "calm-pianos-burn", "clean-camels-sneeze", "clever-ties-burn", "cuddly-bikes-tease", + "cuddly-ways-fail", "curly-rats-itch", "curvy-kiwis-fold", "curvy-lemons-change", + "curvy-pets-wash", "dry-shirts-attack", "dull-rocks-warn", + "early-rocks-smell", "eleven-apples-accept", "fair-tools-melt", "fifty-berries-learn", + "five-tables-grow", + "fresh-donuts-arrive", + "fuzzy-dolls-give", + "fuzzy-dolls-shake", + "giant-pianos-repeat", + "great-numbers-reply", "grumpy-pans-knock", "hot-geese-vanish", "itchy-schools-run", + "kind-bees-suffer", "kind-penguins-report", "large-dingos-juggle", + "large-jars-fry", "lazy-beds-pull", + "lazy-eyes-switch", "lazy-fireants-check", + "little-hats-yell", "little-roses-rule", "loud-dots-sit", "lovely-peaches-fold", + "lucky-beans-bathe", "lucky-cows-boil", "mean-spiders-design", "mighty-lions-march", + "moody-carrots-shout", "odd-pandas-suffer", "odd-singers-taste", "old-cobras-suffer", + "old-melons-bathe", "old-needles-brake", "perfect-moose-drum", "plenty-kids-fetch", "plenty-laws-end", "poor-clouds-ring", "pretty-buttons-develop", + "purple-masks-travel", + "quick-meals-talk", "quiet-dancers-jog", "quiet-hats-kick", "quiet-ligers-draw", + "rare-cougars-cross", "rare-hotels-cough", "red-dots-sleep", "red-pants-rush", @@ -225,6 +246,7 @@ "renovate-a02d90b", "rich-carrots-reflect", "rude-bulldogs-sleep", + "rude-tomatoes-behave", "search-bobcats-love", "search-cars-hide", "search-clouds-begin", @@ -232,10 +254,13 @@ "search-dull-planes-prove", "search-rats-grin", "selfish-turkeys-exist", + "seven-panthers-chew", "shaggy-books-smell", + "short-plants-return", "silent-bees-repeat", "silly-rules-join", "sixty-items-nail", + "slimy-suns-learn", "slow-mirrors-eat", "smooth-tables-pull", "soft-falcons-love", @@ -243,16 +268,20 @@ "sweet-insects-camp", "swift-phones-cheat", "tall-baboons-deliver", + "techdocs-olive-worms-yell", "tender-drinks-drive", "tender-parrots-peel", "thick-kings-destroy", "tiny-mails-bathe", "tough-hairs-sparkle", + "tough-seahorses-learn", "twelve-melons-notice", + "unlucky-seas-sip", "warm-days-watch", "wild-weeks-live", "wise-ligers-scream", "yellow-lemons-march", - "young-bugs-remember" + "young-bugs-remember", + "young-olives-cheer" ] } diff --git a/.changeset/pretty-flies-agree.md b/.changeset/pretty-flies-agree.md new file mode 100644 index 0000000000..da7ac4f6f5 --- /dev/null +++ b/.changeset/pretty-flies-agree.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fixed layout for core-components docs where table was broken by splitting with code sample diff --git a/.changeset/quick-meals-talk.md b/.changeset/quick-meals-talk.md new file mode 100644 index 0000000000..5834928e77 --- /dev/null +++ b/.changeset/quick-meals-talk.md @@ -0,0 +1,19 @@ +--- +'@backstage/plugin-playlist-backend': minor +--- + +**BREAKING** The exported permission rules have changed to reflect the breaking changes made to the PermissionRule type. + +For example, the `playlistConditions.isOwner` API has changed from: + +```ts +playlistConditions.isOwner(['user:default/me', 'group:default/owner']); +``` + +to: + +```ts +playlistConditions.isOwner({ + owners: ['user:default/me', 'group:default/owner'], +}); +``` diff --git a/.changeset/rude-tomatoes-behave.md b/.changeset/rude-tomatoes-behave.md new file mode 100644 index 0000000000..880b4dffd5 --- /dev/null +++ b/.changeset/rude-tomatoes-behave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-bazaar-backend': patch +--- + +Router now also has endpoint `getLatestProjects` that takes a limit of projects as prop. diff --git a/.changeset/search-days-pull.md b/.changeset/search-days-pull.md new file mode 100644 index 0000000000..45d59be514 --- /dev/null +++ b/.changeset/search-days-pull.md @@ -0,0 +1,99 @@ +--- +'@backstage/plugin-search-react': minor +--- + +A `` component was created for limiting the number of results shown per search page. Use this new component to give users options to select how many search results they want to display per page. The default options are 10, 25, 50, 100. + +See examples below: + +_Basic_ + +```jsx +import React, { useState } from 'react'; +import { Grid } from '@material-ui/core'; +import { Page, Header, Content, Lifecycle } from '@backstage/core-components'; +import { + SearchBarBase, + SearchPaginationBase, + SearchResultList, +} from '@backstage/plugin-search-react'; + +const SearchPage = () => { + const [term, setTerm] = useState(''); + const [pageLimit, setPageLimit] = useState(25); + const [pageCursor, setPageCursor] = useState(); + + return ( + +
} /> + + + + + + + + + + + + + + + ); +}; +``` + +_With context_ + +```jsx +import React from 'react'; +import { Grid } from '@material-ui/core'; +import { Page, Header, Content, Lifecycle } from '@backstage/core-components'; +import { + SearchBar, + SearchResult, + SearchPagination, + SearchResultListLayout, + SearchContextProvider, + DefaultResultListItem, +} from '@backstage/plugin-search-react'; + +const SearchPage = () => ( + + +
} /> + + + + + + + + + + + {({ results }) => ( + ( + + )} + /> + )} + + + + + + +); +``` diff --git a/.changeset/search-konstiga-fika-reglar.md b/.changeset/search-konstiga-fika-reglar.md new file mode 100644 index 0000000000..fb79a8ad6f --- /dev/null +++ b/.changeset/search-konstiga-fika-reglar.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-adr-backend': patch +'@backstage/plugin-search-backend-module-elasticsearch': patch +'@backstage/plugin-search-backend-node': patch +'@backstage/plugin-stack-overflow-backend': patch +'@backstage/plugin-techdocs-backend': patch +--- + +In order to improve the debuggability of the search indexing process, messages logged during indexing are now tagged with a `documentType` whose value corresponds to the `type` being indexed. diff --git a/.changeset/seven-panthers-chew.md b/.changeset/seven-panthers-chew.md new file mode 100644 index 0000000000..110df1d389 --- /dev/null +++ b/.changeset/seven-panthers-chew.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +The exported permission rules and the API of `createCatalogConditionalDecision` have changed to reflect the breaking changes made to the `PermissionRule` type. Note that all involved types are exported from `@backstage/plugin-catalog-backend/alpha` diff --git a/.changeset/short-plants-return.md b/.changeset/short-plants-return.md new file mode 100644 index 0000000000..0a4974c38a --- /dev/null +++ b/.changeset/short-plants-return.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Leverage cache mounts in Dockerfile during `yarn install ...` and `apt-get ...` commands to speed up repeated builds. diff --git a/.changeset/silent-mice-brake.md b/.changeset/silent-mice-brake.md new file mode 100644 index 0000000000..fde02146c9 --- /dev/null +++ b/.changeset/silent-mice-brake.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Add the new search pagination component to the search page template. diff --git a/.changeset/techdocs-olive-worms-yell.md b/.changeset/techdocs-olive-worms-yell.md new file mode 100644 index 0000000000..66b205fc19 --- /dev/null +++ b/.changeset/techdocs-olive-worms-yell.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': minor +--- + +Add optional `catalogClient` argument to `createRoute` parameters diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index ae94912f38..1e90802d35 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -2,6 +2,7 @@ abc accessors addon addons +ADRs Airbrake Airbrakes airbrake @@ -28,6 +29,7 @@ bool boolean builtins callout +CDNs Chai changeset changesets @@ -68,6 +70,7 @@ dataflow dayjs debounce Debounce +debuggability declaratively deduplicated deps @@ -129,6 +132,7 @@ hotspots http https Iain +iLert img incentivised Indal @@ -139,6 +143,7 @@ JaCoCo JavaScript jenkins Jira +JWTs jq js json @@ -147,6 +152,7 @@ jsx Kaewkasi Keyv Knex +KPIs kubectl kubernetes kubernetes @@ -308,6 +314,7 @@ Superfences superset supertype storable +SVGs talkdesk Talkdesk tasklist @@ -352,12 +359,15 @@ utils validator validators varchar +VPCs +VSCode Wayfair Weaveworks Webpack winston www WWW +XCMetrics XML xyz yaml diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 46a6227f2c..089474e5b8 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -13,6 +13,9 @@ jobs: matrix: node-version: [14.x] + env: + NODE_OPTIONS: --max-old-space-size=4096 + steps: - uses: actions/checkout@v3 diff --git a/ADOPTERS.md b/ADOPTERS.md index ca56a00890..574623cd14 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -22,7 +22,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. | | [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. | | [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. | -| [Expedia Group](https://www.expediagroup.com) | [@guillermomanzo](https://github.com/guillermomanzo), [Sheena Sharma](mailto:shesharma@expediagroup.com), [@ajbw](https://github.com/ajbw) | EG Common Developer Toolkit | +| [Expedia Group](https://www.expediagroup.com) | [@gman0922](https://github.com/gman0922), [Sheena Sharma](mailto:shesharma@expediagroup.com), [Alekhya Karuturi](mailto:akaruturi@expediagroup.com) | EG Developer Front Door | | [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go | | [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling | | [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. | diff --git a/docs/assets/getting-started/portal.png b/docs/assets/getting-started/portal.png index f16ad44757..b3133f2278 100644 Binary files a/docs/assets/getting-started/portal.png and b/docs/assets/getting-started/portal.png differ diff --git a/docs/assets/getting-started/wizard.png b/docs/assets/getting-started/wizard.png index 679878e252..8b6dce6131 100644 Binary files a/docs/assets/getting-started/wizard.png and b/docs/assets/getting-started/wizard.png differ diff --git a/docs/conf/defining.md b/docs/conf/defining.md index 6462f4f60a..29964dbcbc 100644 --- a/docs/conf/defining.md +++ b/docs/conf/defining.md @@ -23,6 +23,17 @@ Each package is searched for a schema at a single point of entry, a top-level inlined JSON schema, or a relative path to a schema file. Supported schema file formats are `.json` or `.d.ts`. +```jsonc title="package.json" +{ + // ... + "files": [ + // ... + "config.d.ts" + ], + "configSchema": "config.d.ts" +} +``` + > When defining a schema file, be sure to include the file in your > `package.json` > `"files"` field as well! diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md index d35e7dd593..1cd351c2bc 100644 --- a/docs/deployment/docker.md +++ b/docs/deployment/docker.md @@ -61,9 +61,10 @@ FROM node:16-bullseye-slim # Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image, # in which case you should also move better-sqlite3 to "devDependencies" in package.json. -RUN apt-get update && \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + apt-get update && \ apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \ - rm -rf /var/lib/apt/lists/* && \ yarn config set python /usr/bin/python3 # From here on we use the least-privileged `node` user to run the backend. @@ -79,7 +80,8 @@ ENV NODE_ENV production COPY --chown=node:node yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz -RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" +RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \ + yarn install --frozen-lockfile --production --network-timeout 300000 # Then copy the rest of the backend bundle, along with any other files we might want. COPY --chown=node:node packages/backend/dist/bundle.tar.gz app-config*.yaml ./ @@ -163,53 +165,64 @@ RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -exec rm -rf { # Stage 2 - Install dependencies and build packages FROM node:16-bullseye-slim AS build -WORKDIR /app -COPY --from=packages /app . - # install sqlite3 dependencies -RUN apt-get update && \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + apt-get update && \ apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \ yarn config set python /usr/bin/python3 -RUN yarn install --frozen-lockfile --network-timeout 600000 && rm -rf "$(yarn cache dir)" +USER node +WORKDIR /app -COPY . . +COPY --from=packages --chown=node:node /app . + +# Stop cypress from downloading it's massive binary. +ENV CYPRESS_INSTALL_BINARY=0 +RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \ + yarn install --frozen-lockfile --network-timeout 600000 + +COPY --chown=node:node . . RUN yarn tsc RUN yarn --cwd packages/backend build # If you have not yet migrated to package roles, use the following command instead: # RUN yarn --cwd packages/backend backstage-cli backend:bundle --build-dependencies +RUN mkdir packages/backend/dist/skeleton packages/backend/dist/bundle \ + && tar xzf packages/backend/dist/skeleton.tar.gz -C packages/backend/dist/skeleton \ + && tar xzf packages/backend/dist/bundle.tar.gz -C packages/backend/dist/bundle + # Stage 3 - Build the actual backend image and install production dependencies FROM node:16-bullseye-slim # Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image, # in which case you should also move better-sqlite3 to "devDependencies" in package.json. -RUN apt-get update && \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + apt-get update && \ apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \ - rm -rf /var/lib/apt/lists/* && \ yarn config set python /usr/bin/python3 # From here on we use the least-privileged `node` user to run the backend. USER node WORKDIR /app -# This switches many Node.js dependencies to production mode. -ENV NODE_ENV production - # Copy the install dependencies from the build stage and context -COPY --from=build --chown=node:node /app/yarn.lock /app/package.json /app/packages/backend/dist/skeleton.tar.gz ./ -RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz +COPY --from=build --chown=node:node /app/yarn.lock /app/package.json /app/packages/backend/dist/skeleton/ ./ -RUN yarn install --frozen-lockfile --production --network-timeout 600000 && rm -rf "$(yarn cache dir)" +RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \ + yarn install --frozen-lockfile --production --network-timeout 600000 # Copy the built packages from the build stage -COPY --from=build --chown=node:node /app/packages/backend/dist/bundle.tar.gz . -RUN tar xzf bundle.tar.gz && rm bundle.tar.gz +COPY --from=build --chown=node:node /app/packages/backend/dist/bundle/ ./ # Copy any other files that we need at runtime COPY --chown=node:node app-config.yaml ./ +# This switches many Node.js dependencies to production mode. +ENV NODE_ENV production + CMD ["node", "packages/backend", "--config", "app-config.yaml"] ``` @@ -225,6 +238,7 @@ however ignore any existing build output or dependencies on the host. For our new `.dockerignore`, replace the contents of your existing one with this: ```text +dist-types node_modules packages/*/dist packages/*/node_modules diff --git a/docs/features/kubernetes/configuration.md b/docs/features/kubernetes/configuration.md index 1dd684db5f..7dc0e326fa 100644 --- a/docs/features/kubernetes/configuration.md +++ b/docs/features/kubernetes/configuration.md @@ -62,7 +62,7 @@ This is an array used to determine where to retrieve cluster configuration from. Valid cluster locator methods are: - [`catalog`](#catalog) -- [`localKubectlProxy`](#localKubectlProxy) +- [`localKubectlProxy`](#localkubectlproxy) - [`config`](#config) - [`gke`](#gke) - [custom `KubernetesClustersSupplier`](#custom-kubernetesclusterssupplier) diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 17a9029b2d..dfbd4b0a42 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -123,7 +123,7 @@ will set the available actions that the scaffolder has access to. ```ts import { createBuiltinActions } from '@backstage/plugin-scaffolder-backend'; import { ScmIntegrations } from '@backstage/integration'; -import { createNewFileAction } from './actions/custom'; +import { createNewFileAction } from './scaffolder/actions/custom'; export default async function createPlugin( env: PluginEnvironment, diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index ade73d3f68..477467bb88 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -51,14 +51,10 @@ create a subdirectory inside your current working directory. npx @backstage/create-app ``` -The wizard will ask you - -- The name of the app, which will also be the name of the directory -- The database type to use for the backend. For this guide, you'll be using the - SQLite option. +The wizard will ask you for the name of the app, which will also be the name of the directory

- Screenshot of the wizard asking for a name for the app, and a selection menu for the database. + Screenshot of the wizard asking for a name for the app.

### Run the Backstage app diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md index 9b60b41682..26cd660cde 100644 --- a/docs/integrations/github/discovery.md +++ b/docs/integrations/github/discovery.md @@ -39,10 +39,13 @@ And then add the entity provider to your catalog builder: + builder.addEntityProvider( + GitHubEntityProvider.fromConfig(env.config, { + logger: env.logger, ++ // optional: alternatively, use scheduler with schedule defined in app-config.yaml + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 30 }, + timeout: { minutes: 3 }, + }), ++ // optional: alternatively, use schedule ++ scheduler: env.scheduler, + }), + ); @@ -68,6 +71,11 @@ catalog: filters: branch: 'main' # string repository: '.*' # Regex + schedule: # optional; same options as in TaskScheduleDefinition + # supports cron, ISO duration, "human duration" as used in code + frequency: { minutes: 30 } + # supports ISO duration, "human duration" as used in code + timeout: { minutes: 3 } customProviderId: organization: 'new-org' # string catalogPath: '/custom/path/catalog-info.yaml' # string @@ -111,26 +119,35 @@ This provider supports multiple organizations via unique provider IDs. Default: `/catalog-info.yaml`. Path where to look for `catalog-info.yaml` files. You can use wildcards - `*` or `**` - to search the path and/or the filename -- **filters** _(optional)_: - - **branch** _(optional)_: +- **`filters`** _(optional)_: + - **`branch`** _(optional)_: String used to filter results based on the branch name. - - **repository** _(optional)_: + - **`repository`** _(optional)_: Regular expression used to filter results based on the repository name. - - **topic** _(optional)_: + - **`topic`** _(optional)_: Both of the filters below may be used at the same time but the exclusion filter has the highest priority. In the example above, a repository with the `backstage-include` topic would still be excluded if it were also carrying the `experiments` topic. - - **include** _(optional)_: + - **`include`** _(optional)_: An array of strings used to filter in results based on their associated GitHub topics. If configured, only repositories with one (or more) topic(s) present in the inclusion filter will be ingested - - **exclude** _(optional)_: + - **`exclude`** _(optional)_: An array of strings used to filter out results based on their associated GitHub topics. If configured, all repositories _except_ those with one (or more) topics(s) present in the exclusion filter will be ingested. -- **organization**: +- **`host`** _(optional)_: + The hostname of your GitHub Enterprise instance. It must match a host defined in [integrations.github](locations.md). +- **`organization`**: Name of your organization account/workspace. If you want to add multiple organizations, you need to add one provider config each. -- **host** _(optional)_: - The hostname of your GitHub Enterprise instance. It must match a host defined in [integrations.github](locations.md). +- **`schedule`** _(optional)_: + - **`frequency`**: + How often you want the task to run. The system does its best to avoid overlapping invocations. + - **`timeout`**: + The maximum amount of time that a single task invocation can take. + - **`initialDelay`** _(optional)_: + The amount of time that should pass before the first invocation happens. + - **`scope`** _(optional)_: + `'global'` or `'local'`. Sets the scope of concurrency control. ## GitHub API Rate Limits diff --git a/docs/permissions/custom-rules.md b/docs/permissions/custom-rules.md index 1408d732d3..bef1c0941f 100644 --- a/docs/permissions/custom-rules.md +++ b/docs/permissions/custom-rules.md @@ -30,7 +30,7 @@ export const isInSystemRule = createCatalogPermissionRule({ }, toQuery: (systemRef: string) => ({ key: 'relations.partOf', - value: systemRef, + values: [systemRef], }), }); diff --git a/docs/releases/v1.7.0-next.2-changelog.md b/docs/releases/v1.7.0-next.2-changelog.md new file mode 100644 index 0000000000..d5a9b0ddad --- /dev/null +++ b/docs/releases/v1.7.0-next.2-changelog.md @@ -0,0 +1,2127 @@ +# Release v1.7.0-next.2 + +## @backstage/plugin-bazaar-backend@0.2.0-next.2 + +### Minor Changes + +- 8554533546: **BREAKING** The bazaar-backend `createRouter` now requires that the `identityApi` is passed to the router. + + These changes are **required** to `packages/backend/src/plugins/bazaar.ts` + + The user entity ref is now added to the members table and is taken from the requesting user using the `identityApi`. + + ```diff + import { PluginEnvironment } from '../types'; + import { createRouter } from '@backstage/plugin-bazaar-backend'; + import { Router } from 'express'; + + export default async function createPlugin( + env: PluginEnvironment, + ): Promise { + return await createRouter({ + logger: env.logger, + config: env.config, + database: env.database, + + identity: env.identity, + }); + } + ``` + +### Patch Changes + +- f7c2855d76: Router now also has endpoint `getLatestProjects` that takes a limit of projects as prop. +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/backend-test-utils@0.1.29-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-catalog-backend@1.5.0-next.2 + +### Minor Changes + +- b2e6cb6acf: Added a new method `addLocationAnalyzers` to the `CatalogBuilder`. With this you can add location analyzers to your catalog. These analyzers will be used by the /analyze-location endpoint to decide if the provided URL contains any catalog-info.yaml files already or not. + + Moved the following types from this package to `@backstage/plugin-catalog-backend`. + + - AnalyzeLocationResponse + - AnalyzeLocationRequest + - AnalyzeLocationExistingEntity + - AnalyzeLocationGenerateEntity + - AnalyzeLocationEntityField + +- eb25f7e12d: The exported permission rules and the API of `createCatalogConditionalDecision` have changed to reflect the breaking changes made to the `PermissionRule` type. Note that all involved types are exported from `@backstage/plugin-catalog-backend/alpha` + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/plugin-catalog-node@1.2.0-next.2 + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-node@0.7.0-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + - @backstage/plugin-scaffolder-common@1.2.1-next.2 + +## @backstage/plugin-catalog-import@0.9.0-next.2 + +### Minor Changes + +- b2e6cb6acf: **Breaking** + Moved the code search for the existing catalog-info.yaml files to the backend from the frontend. It means it will use the configured GitHub integration's credentials. + + Add the following to your `CatalogBuilder` to have the repo URL ingestion working again. + + ```ts + // catalog.ts + import { GitHubLocationAnalyzer } from '@backstage/plugin-catalog-backend-module-github'; + ... + builder.addLocationAnalyzers( + new GitHubLocationAnalyzer({ + discovery: env.discovery, + config: env.config, + }), + ); + ... + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/integration-react@1.1.5-next.2 + +## @backstage/plugin-catalog-node@1.2.0-next.2 + +### Minor Changes + +- 404366c853: Deprecated the `LocationSpec` type. It got moved from this package to the `@backstage/plugin-catalog-common` so make sure imports are updated. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-permission-common@0.7.0-next.2 + +### Minor Changes + +- 46b4a72cee: **BREAKING**: When defining permission rules, it's now necessary to provide a [ZodSchema](https://github.com/colinhacks/zod) that specifies the parameters the rule expects. This has been added to help better describe the parameters in the response of the metadata endpoint and to validate the parameters before a rule is executed. + + To help with this, we have also made a change to the API of permission rules. Before, the permission rules `toQuery` and `apply` signature expected parameters to be separate arguments, like so... + + ```ts + createPermissionRule({ + apply: (resource, foo, bar) => true, + toQuery: (foo, bar) => {}, + }); + ``` + + The API has now changed to expect the parameters as a single object + + ```ts + createPermissionRule({ + paramSchema: z.object({ + foo: z.string().describe('Foo value to match'), + bar: z.string().describe('Bar value to match'), + }), + apply: (resource, { foo, bar }) => true, + toQuery: ({ foo, bar }) => {}, + }); + ``` + + One final change made is to limit the possible values for a parameter to primitives and arrays of primitives. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-permission-node@0.7.0-next.2 + +### Minor Changes + +- 46b4a72cee: **BREAKING**: When defining permission rules, it's now necessary to provide a [ZodSchema](https://github.com/colinhacks/zod) that specifies the parameters the rule expects. This has been added to help better describe the parameters in the response of the metadata endpoint and to validate the parameters before a rule is executed. + + To help with this, we have also made a change to the API of permission rules. Before, the permission rules `toQuery` and `apply` signature expected parameters to be separate arguments, like so... + + ```ts + createPermissionRule({ + apply: (resource, foo, bar) => true, + toQuery: (foo, bar) => {}, + }); + ``` + + The API has now changed to expect the parameters as a single object + + ```ts + createPermissionRule({ + paramSchema: z.object({ + foo: z.string().describe('Foo value to match'), + bar: z.string().describe('Bar value to match'), + }), + apply: (resource, { foo, bar }) => true, + toQuery: ({ foo, bar }) => {}, + }); + ``` + + One final change made is to limit the possible values for a parameter to primitives and arrays of primitives. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-playlist-backend@0.2.0-next.2 + +### Minor Changes + +- eb25f7e12d: **BREAKING** The exported permission rules have changed to reflect the breaking changes made to the PermissionRule type. + + For example, the `playlistConditions.isOwner` API has changed from: + + ```ts + playlistConditions.isOwner(['user:default/me', 'group:default/owner']); + ``` + + to: + + ```ts + playlistConditions.isOwner({ + owners: ['user:default/me', 'group:default/owner'], + }); + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-node@0.7.0-next.2 + - @backstage/backend-test-utils@0.1.29-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/plugin-playlist-common@0.1.1-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-scaffolder-backend@1.7.0-next.2 + +### Minor Changes + +- 17ff77154c: Update the `github:publish` action to allow passing whether pull + requests must be up to date with the default branch before merging. +- a8e9848479: Added optional `sourcePath` parameter to `publish:gitlab:merge-request` action, `targetPath` is now optional and falls back to current workspace path. + +### Patch Changes + +- 4880d43e25: Fixed setting default branch for Bitbucket Server +- Updated dependencies + - @backstage/plugin-catalog-node@1.2.0-next.2 + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + - @backstage/plugin-scaffolder-common@1.2.1-next.2 + +## @backstage/plugin-techdocs-backend@1.4.0-next.2 + +### Minor Changes + +- 7ced1b4076: Add optional `catalogClient` argument to `createRoute` parameters + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-techdocs-node@1.4.1-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + +## @backstage/app-defaults@1.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-react@0.4.6-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/backend-app-api@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-node@0.7.0-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/backend-common@0.15.2-next.2 + +### Patch Changes + +- c44cf412de: Fix BitBucket server integration +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/cli-common@0.1.10 + - @backstage/config@1.0.3-next.2 + - @backstage/config-loader@1.1.5-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/backend-defaults@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.2.2-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + +## @backstage/backend-plugin-api@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/backend-tasks@0.3.6-next.2 + +### Patch Changes + +- d4fea86ea3: Added new function `readTaskScheduleDefinitionFromConfig` to read `TaskScheduleDefinition` (aka. schedule) from the `Config`. +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/backend-test-utils@0.1.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/cli@0.20.0-next.2 + - @backstage/backend-app-api@0.2.2-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/catalog-client@1.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/catalog-model@1.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/cli@0.20.0-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/cli-common@0.1.10 + - @backstage/config@1.0.3-next.2 + - @backstage/config-loader@1.1.5-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/release-manifests@0.0.6 + - @backstage/types@1.0.0 + +## @backstage/codemods@0.1.40-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.10 + +## @backstage/config@1.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.0.0 + +## @backstage/config-loader@1.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.10 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/core-app-api@1.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/types@1.0.0 + - @backstage/version-bridge@1.0.1 + +## @backstage/core-components@0.11.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/version-bridge@1.0.1 + +## @backstage/core-plugin-api@1.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/types@1.0.0 + - @backstage/version-bridge@1.0.1 + +## @backstage/create-app@0.4.32-next.2 + +### Patch Changes + +- 01dff06be4: Leverage cache mounts in Dockerfile during `yarn install ...` and `apt-get ...` commands to speed up repeated builds. +- Updated dependencies + - @backstage/cli-common@0.1.10 + +## @backstage/dev-utils@1.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/test-utils@1.2.1-next.2 + - @backstage/app-defaults@1.0.7-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + +## @backstage/errors@1.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.0.0 + +## @backstage/integration@1.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/integration-react@1.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/theme@0.2.16 + +## @techdocs/cli@1.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-techdocs-node@1.4.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/cli-common@0.1.10 + - @backstage/config@1.0.3-next.2 + +## @backstage/test-utils@1.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-react@0.4.6-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + +## @backstage/plugin-adr@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-adr-common@0.2.2-next.2 + - @backstage/plugin-search-react@1.2.0-next.2 + +## @backstage/plugin-adr-backend@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/plugin-adr-common@0.2.2-next.2 + +## @backstage/plugin-adr-common@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + +## @backstage/plugin-airbrake@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/test-utils@1.2.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/dev-utils@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-airbrake-backend@0.2.10-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/plugin-allure@0.1.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-analytics-module-ga@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-apache-airflow@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + +## @backstage/plugin-api-docs@0.8.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-apollo-explorer@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-app-backend@0.3.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/config-loader@1.1.5-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-auth-backend@0.17.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-auth-node@0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-azure-devops@0.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-devops-backend@0.3.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-badges@0.2.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-badges-backend@0.1.31-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-bazaar@0.1.25-next.2 + +### Patch Changes + +- f7c2855d76: Added a `Overview Card` for either latest or random projects. Changed `ProjectPreview.tsx` so it take `gridSize` and `useTablePagination` as props. +- c0352bbc69: Link to the user catalog entity of a member +- Updated dependencies + - @backstage/cli@0.20.0-next.2 + - @backstage/plugin-catalog@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-bitbucket-cloud-common@0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.3.2-next.2 + +## @backstage/plugin-bitrise@0.1.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-catalog@1.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + - @backstage/plugin-search-react@1.2.0-next.2 + +## @backstage/plugin-catalog-backend-module-aws@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-catalog-backend-module-azure@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.4-next.2 + +### Patch Changes + +- 23f9199a0f: Deprecate `@backstage/plugin-catalog-backend-module-bitbucket`. + + Please migrate to `@backstage/plugin-catalog-backend-module-bitbucket-cloud` + or `@backstage/plugin-catalog-backend-module-bitbucket-server` instead. + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.0-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.4-next.2 + +### Patch Changes + +- f66e696e7b: Bitbucket Cloud provider: Add option to configure schedule via `app-config.yaml` instead of in code. + + Please find how to configure the schedule at the config at + + +- a9b91d39bb: Add `bitbucketCloudCatalogModule` (new backend-plugin-api, alpha). + +- Updated dependencies + - @backstage/plugin-catalog-node@1.2.0-next.2 + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.0-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + +## @backstage/plugin-catalog-backend-module-github@0.1.8-next.2 + +### Patch Changes + +- 7022aebf35: Added `GitHubLocationAnalyzer`. This can be used to add to the `CatalogBuilder`. When added this will be used by `RepoLocationAnalyzer` to figure out if the given URL that you are trying to import from the /catalog-import page already contains catalog-info.yaml files. +- 7edb5909e8: Add missing config schema for the `GitHubEntityProvider`. +- Updated dependencies + - @backstage/plugin-catalog-node@1.2.0-next.2 + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-catalog-backend-module-gitlab@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-catalog-backend-module-msgraph@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.2.0-next.2 + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-catalog-common@1.0.7-next.2 + +### Patch Changes + +- 823acaa88b: Moved the following types from `@backstage/plugin-catalog-backend` to this package. + + - AnalyzeLocationResponse + - AnalyzeLocationRequest + - AnalyzeLocationExistingEntity + - AnalyzeLocationGenerateEntity + - AnalyzeLocationEntityField + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + +## @backstage/plugin-catalog-graph@0.2.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-catalog-graphql@0.3.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-catalog-react@1.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-react@0.4.6-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + - @backstage/version-bridge@1.0.1 + +## @backstage/plugin-cicd-statistics@0.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/plugin-cicd-statistics@0.1.12-next.2 + +## @backstage/plugin-circleci@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-cloudbuild@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-code-climate@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-code-coverage@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-code-coverage-backend@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + +## @backstage/plugin-codescene@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-config-schema@0.1.33-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + +## @backstage/plugin-cost-insights@0.11.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-cost-insights-common@0.1.1 + +## @backstage/plugin-dynatrace@1.0.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-explore@0.3.41-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-explore-react@0.0.22-next.2 + +## @backstage/plugin-explore-react@0.0.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.0.7-next.2 + +## @backstage/plugin-firehydrant@0.1.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-fossa@0.2.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gcalendar@0.3.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gcp-projects@0.3.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-git-release-manager@0.3.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-actions@0.5.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-deployments@0.1.41-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-issues@0.1.2-next.2 + +### Patch Changes + +- df226e124c: Add filtering and ordering to the graphql query +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-pull-requests-board@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gitops-profiles@0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gocd@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-graphiql@0.2.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-graphql-backend@0.1.27-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/plugin-catalog-graphql@0.3.14-next.2 + +## @backstage/plugin-home@0.4.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-stack-overflow@0.1.6-next.2 + +## @backstage/plugin-ilert@0.1.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-jenkins@0.7.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-jenkins-common@0.1.9-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-jenkins-backend@0.1.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-jenkins-common@0.1.9-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-jenkins-common@0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + +## @backstage/plugin-kafka@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-kafka-backend@0.2.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-kubernetes@0.7.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-kubernetes-common@0.4.3-next.2 + +## @backstage/plugin-kubernetes-backend@0.7.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/plugin-kubernetes-common@0.4.3-next.2 + +## @backstage/plugin-kubernetes-common@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.2-next.2 + +## @backstage/plugin-lighthouse@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-newrelic@0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-newrelic-dashboard@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-org@0.5.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-pagerduty@0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-periskop@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-periskop-backend@0.1.8-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/plugin-permission-backend@0.5.12-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-node@0.7.0-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-permission-react@0.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + +## @backstage/plugin-playlist@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-permission-react@0.4.6-next.2 + - @backstage/plugin-playlist-common@0.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-search-react@1.2.0-next.2 + +## @backstage/plugin-playlist-common@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.0-next.2 + +## @backstage/plugin-proxy-backend@0.2.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/plugin-rollbar@0.4.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-rollbar-backend@0.1.34-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/plugin-scaffolder@1.7.0-next.2 + +### Patch Changes + +- 92e490d6b4: Make the `/next` scaffolder work end to end with the old `TaskPage` view +- 1047baa926: Bump to `react-jsonschema-form@v5-beta` for the `NextRouter` under `@alpha` exports +- 98ae18b68f: Fixed a bug where the `allowed*` values for the `RepoUrlPicker` would be reset on render. +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-permission-react@0.4.6-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + - @backstage/plugin-scaffolder-common@1.2.1-next.2 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-scaffolder-backend@1.7.0-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-scaffolder-backend@1.7.0-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.7.0-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-scaffolder-common@1.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-search@1.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + - @backstage/version-bridge@1.0.1 + - @backstage/plugin-search-react@1.2.0-next.2 + +## @backstage/plugin-search-backend@1.1.0-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-node@0.7.0-next.2 + - @backstage/plugin-search-backend-node@1.0.3-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-search-backend-module-elasticsearch@1.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-node@1.0.3-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/plugin-search-backend-module-pg@0.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-search-backend-node@1.0.3-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/plugin-search-backend-node@1.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-search-common@1.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-search-react@1.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + - @backstage/version-bridge@1.0.1 + +## @backstage/plugin-sentry@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-shortcuts@0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + +## @backstage/plugin-sonarqube@0.4.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-sonarqube-backend@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-splunk-on-call@0.3.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-stack-overflow@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-home@0.4.26-next.2 + +## @backstage/plugin-stack-overflow-backend@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.20.0-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/config@1.0.3-next.2 + +## @backstage/plugin-tech-insights@0.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + - @backstage/plugin-tech-insights-common@0.2.7-next.2 + +## @backstage/plugin-tech-insights-backend@0.5.3-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-tech-insights-node@0.3.5-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/plugin-tech-insights-common@0.2.7-next.2 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-tech-insights-node@0.3.5-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/plugin-tech-insights-common@0.2.7-next.2 + +## @backstage/plugin-tech-insights-common@0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.0.0 + +## @backstage/plugin-tech-insights-node@0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/types@1.0.0 + - @backstage/plugin-tech-insights-common@0.2.7-next.2 + +## @backstage/plugin-tech-radar@0.5.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-techdocs@1.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-search-react@1.2.0-next.2 + - @backstage/plugin-techdocs-react@1.0.5-next.2 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.6.0-next.2 + - @backstage/test-utils@1.2.1-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-search-react@1.2.0-next.2 + - @backstage/plugin-techdocs@1.3.3-next.2 + - @backstage/plugin-techdocs-react@1.0.5-next.2 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.0.5-next.2 + +## @backstage/plugin-techdocs-node@1.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + +## @backstage/plugin-techdocs-react@1.0.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/version-bridge@1.0.1 + +## @backstage/plugin-todo@0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-todo-backend@0.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + +## @backstage/plugin-user-settings@0.5.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + +## @backstage/plugin-user-settings-backend@0.1.1-next.2 + +### Patch Changes + +- f3463b176b: Use `Response.status` instead of `.send(number)` +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + +## @backstage/plugin-vault@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-vault-backend@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/backend-test-utils@0.1.29-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @backstage/plugin-xcmetrics@0.2.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + +## example-app@0.2.76-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.7.0-next.2 + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/plugin-catalog-import@0.9.0-next.2 + - @backstage/cli@0.20.0-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-playlist@0.1.1-next.2 + - @backstage/plugin-permission-react@0.4.6-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/app-defaults@1.0.7-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-airbrake@0.3.10-next.2 + - @backstage/plugin-apache-airflow@0.2.3-next.2 + - @backstage/plugin-api-docs@0.8.10-next.2 + - @backstage/plugin-azure-devops@0.2.1-next.2 + - @backstage/plugin-badges@0.2.34-next.2 + - @backstage/plugin-catalog-graph@0.2.22-next.2 + - @backstage/plugin-circleci@0.3.10-next.2 + - @backstage/plugin-cloudbuild@0.3.10-next.2 + - @backstage/plugin-code-coverage@0.2.3-next.2 + - @backstage/plugin-cost-insights@0.11.32-next.2 + - @backstage/plugin-dynatrace@1.0.0-next.2 + - @backstage/plugin-explore@0.3.41-next.2 + - @backstage/plugin-gcalendar@0.3.6-next.2 + - @backstage/plugin-gcp-projects@0.3.29-next.2 + - @backstage/plugin-github-actions@0.5.10-next.2 + - @backstage/plugin-gocd@0.1.16-next.2 + - @backstage/plugin-graphiql@0.2.42-next.2 + - @backstage/plugin-home@0.4.26-next.2 + - @backstage/plugin-jenkins@0.7.9-next.2 + - @backstage/plugin-kafka@0.3.10-next.2 + - @backstage/plugin-kubernetes@0.7.3-next.2 + - @backstage/plugin-lighthouse@0.3.10-next.2 + - @backstage/plugin-newrelic@0.3.28-next.2 + - @backstage/plugin-newrelic-dashboard@0.2.3-next.2 + - @backstage/plugin-org@0.5.10-next.2 + - @backstage/plugin-pagerduty@0.5.3-next.2 + - @backstage/plugin-rollbar@0.4.10-next.2 + - @backstage/plugin-search@1.0.3-next.2 + - @backstage/plugin-search-react@1.2.0-next.2 + - @backstage/plugin-sentry@0.4.3-next.2 + - @backstage/plugin-shortcuts@0.3.2-next.2 + - @backstage/plugin-stack-overflow@0.1.6-next.2 + - @backstage/plugin-tech-insights@0.3.1-next.2 + - @backstage/plugin-tech-radar@0.5.17-next.2 + - @backstage/plugin-techdocs@1.3.3-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.5-next.2 + - @backstage/plugin-techdocs-react@1.0.5-next.2 + - @backstage/plugin-todo@0.2.12-next.2 + - @backstage/plugin-user-settings@0.5.0-next.2 + - @internal/plugin-catalog-customized@0.0.3-next.2 + +## example-backend@0.2.76-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-node@0.7.0-next.2 + - @backstage/plugin-scaffolder-backend@1.7.0-next.2 + - @backstage/plugin-playlist-backend@0.2.0-next.2 + - @backstage/plugin-badges-backend@0.1.31-next.2 + - @backstage/plugin-graphql-backend@0.1.27-next.2 + - @backstage/plugin-permission-backend@0.5.12-next.2 + - @backstage/plugin-rollbar-backend@0.1.34-next.2 + - @backstage/plugin-search-backend@1.1.0-next.2 + - @backstage/plugin-tech-insights-backend@0.5.3-next.2 + - @backstage/plugin-techdocs-backend@1.4.0-next.2 + - example-app@0.2.76-next.2 + - @backstage/plugin-search-backend-node@1.0.3-next.2 + - @backstage/plugin-tech-insights-node@0.3.5-next.2 + - @backstage/plugin-app-backend@0.3.37-next.2 + - @backstage/plugin-auth-backend@0.17.0-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/plugin-azure-devops-backend@0.3.16-next.2 + - @backstage/plugin-code-coverage-backend@0.2.3-next.2 + - @backstage/plugin-jenkins-backend@0.1.27-next.2 + - @backstage/plugin-kafka-backend@0.2.30-next.2 + - @backstage/plugin-kubernetes-backend@0.7.3-next.2 + - @backstage/plugin-proxy-backend@0.2.31-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.5-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.0.3-next.2 + - @backstage/plugin-search-backend-module-pg@0.4.1-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.21-next.2 + - @backstage/plugin-todo-backend@0.1.34-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/integration@1.3.2-next.2 + +## example-backend-next@0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/plugin-scaffolder-backend@1.7.0-next.2 + - @backstage/plugin-app-backend@0.3.37-next.2 + - @backstage/backend-defaults@0.1.2-next.2 + +## techdocs-cli-embedded-app@0.2.75-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.20.0-next.2 + - @backstage/plugin-catalog@1.6.0-next.2 + - @backstage/test-utils@1.2.1-next.2 + - @backstage/app-defaults@1.0.7-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs@1.3.3-next.2 + - @backstage/plugin-techdocs-react@1.0.5-next.2 + +## @internal/plugin-catalog-customized@0.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + +## @internal/plugin-todo-list@1.0.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + +## @internal/plugin-todo-list-backend@1.0.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + +## @internal/plugin-todo-list-common@1.0.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.0-next.2 diff --git a/docs/tutorials/switching-sqlite-postgres.md b/docs/tutorials/switching-sqlite-postgres.md index c0c35999c6..bd067ee388 100644 --- a/docs/tutorials/switching-sqlite-postgres.md +++ b/docs/tutorials/switching-sqlite-postgres.md @@ -72,6 +72,12 @@ backend: + port: ${POSTGRES_PORT} + user: ${POSTGRES_USER} + password: ${POSTGRES_PASSWORD} ++ # https://node-postgres.com/features/ssl ++ # you can set the sslmode configuration option via the `PGSSLMODE` environment variable ++ # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require) ++ # ssl: ++ # ca: # if you have a CA file and want to verify it you can uncomment this section ++ # $file: /ca/server.crt + # Refer to Tarn docs for default values on PostgreSQL pool configuration - https://github.com/Vincit/tarn.js + knexConfig: + pool: @@ -79,12 +85,6 @@ backend: + max: 12 + acquireTimeoutMillis: 60000 + idleTimeoutMillis: 60000 -+ # https://node-postgres.com/features/ssl -+ # you can set the sslmode configuration option via the `PGSSLMODE` environment variable -+ # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require) -+ # ssl: -+ # ca: # if you have a CA file and want to verify it you can uncomment this section -+ # $file: /ca/server.crt ``` ### Using a single database diff --git a/docs/tutorials/yarn-migration.md b/docs/tutorials/yarn-migration.md index 7f898c7b98..6dee343e78 100644 --- a/docs/tutorials/yarn-migration.md +++ b/docs/tutorials/yarn-migration.md @@ -67,6 +67,13 @@ COPY .yarn ./.yarn COPY .yarnrc.yml ./ ``` +In a multi-stage `Dockerfile`, each stage that runs a `yarn` command will also need the Yarn 3 installation. For example, in the final stage you may need to add the following: + +```Dockerfile +COPY --from=build --chown=node:node /app/.yarn ./.yarn +COPY --from=build --chown=node:node /app/.yarnrc.yml ./ +``` + The `--production` flag to `yarn install` has been removed in Yarn 3, instead you need to use `yarn workspaces focus --all --production` to avoid installing development dependencies in your production deployment. A tradeoff of this is that `yarn workspaces focus` does not support the `--immutable` flag. ```Dockerfile diff --git a/microsite/sidebars.json b/microsite/sidebars.json index a93e148317..bf6b036daf 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -226,6 +226,7 @@ "plugins/composability", "plugins/customization", "plugins/analytics", + "plugins/feature-flags", { "type": "subcategory", "label": "Backends and APIs", diff --git a/package.json b/package.json index 40e2056e8c..c586b3a580 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build": "backstage-cli repo build --all", "build:api-reports": "yarn build:api-reports:only --tsc", "build:api-reports:only": "ts-node -T -P scripts/tsconfig.json scripts/api-extractor.ts", - "build:api-docs": "yarn build:api-reports --docs", + "build:api-docs": "LANG=en_EN yarn build:api-reports --docs", "tsc": "tsc", "tsc:full": "backstage-cli repo clean && tsc --skipLibCheck false --incremental false", "clean": "backstage-cli repo clean", @@ -44,8 +44,9 @@ "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.7.0-next.1", + "version": "1.7.0-next.2", "dependencies": { + "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3", "@microsoft/api-documenter": "^7.17.11", "@microsoft/api-extractor": "^7.23.0", diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index c4082ad530..1b07baeade 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/app-defaults +## 1.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-react@0.4.6-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + ## 1.0.7-next.1 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 476509730a..eb62cab691 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "1.0.7-next.1", + "version": "1.0.7-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index d492b19a1a..e10bfddff8 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,67 @@ # example-app +## 0.2.76-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.7.0-next.2 + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/plugin-catalog-import@0.9.0-next.2 + - @backstage/cli@0.20.0-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-playlist@0.1.1-next.2 + - @backstage/plugin-permission-react@0.4.6-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/app-defaults@1.0.7-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-airbrake@0.3.10-next.2 + - @backstage/plugin-apache-airflow@0.2.3-next.2 + - @backstage/plugin-api-docs@0.8.10-next.2 + - @backstage/plugin-azure-devops@0.2.1-next.2 + - @backstage/plugin-badges@0.2.34-next.2 + - @backstage/plugin-catalog-graph@0.2.22-next.2 + - @backstage/plugin-circleci@0.3.10-next.2 + - @backstage/plugin-cloudbuild@0.3.10-next.2 + - @backstage/plugin-code-coverage@0.2.3-next.2 + - @backstage/plugin-cost-insights@0.11.32-next.2 + - @backstage/plugin-dynatrace@1.0.0-next.2 + - @backstage/plugin-explore@0.3.41-next.2 + - @backstage/plugin-gcalendar@0.3.6-next.2 + - @backstage/plugin-gcp-projects@0.3.29-next.2 + - @backstage/plugin-github-actions@0.5.10-next.2 + - @backstage/plugin-gocd@0.1.16-next.2 + - @backstage/plugin-graphiql@0.2.42-next.2 + - @backstage/plugin-home@0.4.26-next.2 + - @backstage/plugin-jenkins@0.7.9-next.2 + - @backstage/plugin-kafka@0.3.10-next.2 + - @backstage/plugin-kubernetes@0.7.3-next.2 + - @backstage/plugin-lighthouse@0.3.10-next.2 + - @backstage/plugin-newrelic@0.3.28-next.2 + - @backstage/plugin-newrelic-dashboard@0.2.3-next.2 + - @backstage/plugin-org@0.5.10-next.2 + - @backstage/plugin-pagerduty@0.5.3-next.2 + - @backstage/plugin-rollbar@0.4.10-next.2 + - @backstage/plugin-search@1.0.3-next.2 + - @backstage/plugin-search-react@1.2.0-next.2 + - @backstage/plugin-sentry@0.4.3-next.2 + - @backstage/plugin-shortcuts@0.3.2-next.2 + - @backstage/plugin-stack-overflow@0.1.6-next.2 + - @backstage/plugin-tech-insights@0.3.1-next.2 + - @backstage/plugin-tech-radar@0.5.17-next.2 + - @backstage/plugin-techdocs@1.3.3-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.5-next.2 + - @backstage/plugin-techdocs-react@1.0.5-next.2 + - @backstage/plugin-todo@0.2.12-next.2 + - @backstage/plugin-user-settings@0.5.0-next.2 + - @internal/plugin-catalog-customized@0.0.3-next.2 + ## 0.2.76-next.1 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 7960bb115b..db024431a4 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.76-next.1", + "version": "0.2.76-next.2", "private": true, "backstage": { "role": "frontend" @@ -84,7 +84,6 @@ }, "devDependencies": { "@backstage/test-utils": "workspace:^", - "@rjsf/core": "^3.2.1", "@testing-library/cypress": "^8.0.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx index 99814130c2..d324b683d8 100644 --- a/packages/app/src/components/search/SearchPage.tsx +++ b/packages/app/src/components/search/SearchPage.tsx @@ -35,6 +35,7 @@ import { SearchBar, SearchFilter, SearchResult, + SearchPagination, SearchResultPager, useSearch, } from '@backstage/plugin-search-react'; @@ -129,6 +130,7 @@ const SearchPage = () => { )} + {({ results }) => ( diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index 3823d025ac..2b179d7d7a 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-app-api +## 0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-node@0.7.0-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/errors@1.1.2-next.2 + ## 0.2.2-next.1 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index c454785aa2..fd27521572 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-app-api", "description": "Core API used by Backstage backend apps", - "version": "0.2.2-next.1", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 143b6d28c9..3029c424fc 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/backend-common +## 0.15.2-next.2 + +### Patch Changes + +- c44cf412de: Fix BitBucket server integration +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/cli-common@0.1.10 + - @backstage/config@1.0.3-next.2 + - @backstage/config-loader@1.1.5-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + ## 0.15.2-next.1 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index b6b0c5e35a..133c8590fc 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.15.2-next.1", + "version": "0.15.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/src/reading/BitbucketServerUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketServerUrlReader.test.ts index f308b4d33d..15f1c0d4be 100644 --- a/packages/backend-common/src/reading/BitbucketServerUrlReader.test.ts +++ b/packages/backend-common/src/reading/BitbucketServerUrlReader.test.ts @@ -83,11 +83,23 @@ describe('BitbucketServerUrlReader', () => { ), ), rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits/*', + 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/branches', (_, res, ctx) => res( ctx.status(200), - ctx.json({ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }), + ctx.json({ + size: 2, + values: [ + { + displayId: 'some-branch-that-should-be-ignored', + latestCommit: 'bogus hash', + }, + { + displayId: 'some-branch', + latestCommit: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st', + }, + ], + }), ), ), ); @@ -130,12 +142,22 @@ describe('BitbucketServerUrlReader', () => { ), ), rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits/*', + 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/branches', (_, res, ctx) => res( ctx.status(200), ctx.json({ - values: [{ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }], + size: 2, + values: [ + { + displayId: 'some-branch-that-should-be-ignored', + latestCommit: 'bogus hash', + }, + { + displayId: 'some-branch', + latestCommit: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st', + }, + ], }), ), ), @@ -179,11 +201,23 @@ describe('BitbucketServerUrlReader', () => { ), ), rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits/*', + 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/branches', (_, res, ctx) => res( ctx.status(200), - ctx.json({ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }), + ctx.json({ + size: 2, + values: [ + { + displayId: 'master-of-none', + latestCommit: 'bogus hash', + }, + { + displayId: 'master', + latestCommit: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st', + }, + ], + }), ), ), ); diff --git a/packages/backend-common/src/reading/BitbucketServerUrlReader.ts b/packages/backend-common/src/reading/BitbucketServerUrlReader.ts index e9a229a1ff..98f95b88cb 100644 --- a/packages/backend-common/src/reading/BitbucketServerUrlReader.ts +++ b/packages/backend-common/src/reading/BitbucketServerUrlReader.ts @@ -188,38 +188,36 @@ export class BitbucketServerUrlReader implements UrlReader { private async getLastCommitShortHash(url: string): Promise { const { name: repoName, owner: project, ref: branch } = parseGitUrl(url); - // Bitbucket Server https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp224 - const commitApiUrl = `${this.integration.config.apiBaseUrl}/projects/${project}/repos/${repoName}/commits/${branch}`; + const branchListUrl = `${ + this.integration.config.apiBaseUrl + }/projects/${project}/repos/${repoName}/branches?filterText=${encodeURIComponent( + branch, + )}`; - const commitResponse = await fetch( - commitApiUrl, + const branchListResponse = await fetch( + branchListUrl, getBitbucketServerRequestOptions(this.integration.config), ); - if (!commitResponse.ok) { - const message = `Failed to retrieve commits from ${commitApiUrl}, ${commitResponse.status} ${commitResponse.statusText}`; - if (commitResponse.status === 404) { + if (!branchListResponse.ok) { + const message = `Failed to retrieve branch list from ${branchListUrl}, ${branchListResponse.status} ${branchListResponse.statusText}`; + if (branchListResponse.status === 404) { throw new NotFoundError(message); } throw new Error(message); } - const commits = await commitResponse.json(); + const branchMatches = await branchListResponse.json(); - // Handles case when a branch is provided in the URL - if (commits && commits.id) { - return commits.id.substring(0, 12); + if (branchMatches && branchMatches.size > 0) { + const exactBranchMatch = branchMatches.values.filter( + (branchDetails: { displayId: string }) => + branchDetails.displayId === branch, + )[0]; + return exactBranchMatch.latestCommit.substring(0, 12); } - // Handles case when no branch is provided in the URL - if ( - commits && - commits.values && - commits.values.length > 0 && - commits.values[0].id - ) { - return commits.values[0].id.substring(0, 12); - } - - throw new Error(`Failed to read response from ${commitApiUrl}`); + throw new Error( + `Failed to find branch "${branch}" in property "displayId" of response to ${branchListUrl}`, + ); } } diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 8d980fe1bc..986a4a39f2 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/backend-defaults +## 0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.2.2-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + ## 0.1.2-next.1 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 1d0a3f09f6..c0344572fa 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-defaults", "description": "Backend defaults used by Backstage backend apps", - "version": "0.1.2-next.1", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index e8d6cefa1b..5849d5b088 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,15 @@ # example-backend-next +## 0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/plugin-scaffolder-backend@1.7.0-next.2 + - @backstage/plugin-app-backend@0.3.37-next.2 + - @backstage/backend-defaults@0.1.2-next.2 + ## 0.0.4-next.1 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 7db8ef9775..8965c8b1c8 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.4-next.1", + "version": "0.0.4-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 21897d0a97..230092c0ba 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/backend-plugin-api +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/config@1.0.3-next.2 + ## 0.1.3-next.1 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 80e3a8adfa..389e36aa93 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-api", "description": "Core API used by Backstage backend plugins", - "version": "0.1.3-next.1", + "version": "0.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index 97468f3856..bff6fa4e7d 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-tasks +## 0.3.6-next.2 + +### Patch Changes + +- d4fea86ea3: Added new function `readTaskScheduleDefinitionFromConfig` to read `TaskScheduleDefinition` (aka. schedule) from the `Config`. +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + ## 0.3.6-next.1 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 9fc7d6cbae..06cbe14bf7 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-tasks", "description": "Common distributed task management library for Backstage backends", - "version": "0.3.6-next.1", + "version": "0.3.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 753ad24289..ab7f6ef60a 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-test-utils +## 0.1.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/cli@0.20.0-next.2 + - @backstage/backend-app-api@0.2.2-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/config@1.0.3-next.2 + ## 0.1.29-next.1 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 5249196860..d9ab0e195d 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.29-next.1", + "version": "0.1.29-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index c5dc2f71bd..c4df56a55f 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,47 @@ # example-backend +## 0.2.76-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-node@0.7.0-next.2 + - @backstage/plugin-scaffolder-backend@1.7.0-next.2 + - @backstage/plugin-playlist-backend@0.2.0-next.2 + - @backstage/plugin-badges-backend@0.1.31-next.2 + - @backstage/plugin-graphql-backend@0.1.27-next.2 + - @backstage/plugin-permission-backend@0.5.12-next.2 + - @backstage/plugin-rollbar-backend@0.1.34-next.2 + - @backstage/plugin-search-backend@1.1.0-next.2 + - @backstage/plugin-tech-insights-backend@0.5.3-next.2 + - @backstage/plugin-techdocs-backend@1.4.0-next.2 + - example-app@0.2.76-next.2 + - @backstage/plugin-search-backend-node@1.0.3-next.2 + - @backstage/plugin-tech-insights-node@0.3.5-next.2 + - @backstage/plugin-app-backend@0.3.37-next.2 + - @backstage/plugin-auth-backend@0.17.0-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/plugin-azure-devops-backend@0.3.16-next.2 + - @backstage/plugin-code-coverage-backend@0.2.3-next.2 + - @backstage/plugin-jenkins-backend@0.1.27-next.2 + - @backstage/plugin-kafka-backend@0.2.30-next.2 + - @backstage/plugin-kubernetes-backend@0.7.3-next.2 + - @backstage/plugin-proxy-backend@0.2.31-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.5-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.0.3-next.2 + - @backstage/plugin-search-backend-module-pg@0.4.1-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.21-next.2 + - @backstage/plugin-todo-backend@0.1.34-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/integration@1.3.2-next.2 + ## 0.2.76-next.1 ### Patch Changes diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile index 21ff07deb4..60c6ffd27f 100644 --- a/packages/backend/Dockerfile +++ b/packages/backend/Dockerfile @@ -13,9 +13,10 @@ FROM node:16-bullseye-slim # Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image, # in which case you should also move better-sqlite3 to "devDependencies" in package.json. -RUN apt-get update && \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + apt-get update && \ apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \ - rm -rf /var/lib/apt/lists/* && \ yarn config set python /usr/bin/python3 # From here on we use the least-privileged `node` user to run the backend. @@ -38,7 +39,8 @@ COPY --chown=node:node yarn.lock package.json packages/backend/dist/skeleton.tar RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz # Note that this install is not immutable, which is one of the reasons we don't recommend Yarn 3 yet -RUN yarn workspaces focus --all --production && rm -rf "$(yarn cache clean)" +RUN --mount=type=cache,target=/home/node/.yarn/berry/cache,sharing=locked,uid=1000,gid=1000 \ + yarn workspaces focus --all --production # Then copy the rest of the backend bundle, along with any other files we might want. COPY --chown=node:node packages/backend/dist/bundle.tar.gz app-config*.yaml ./ diff --git a/packages/backend/package.json b/packages/backend/package.json index f89fcbf0e5..9b02d62f36 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.76-next.1", + "version": "0.2.76-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 0e5a847703..27c2f9d1bf 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-client +## 1.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/errors@1.1.2-next.2 + ## 1.1.1-next.1 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 31b8654556..d27efc6257 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "1.1.1-next.1", + "version": "1.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 6352f13760..ac53d99efc 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/catalog-model +## 1.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + ## 1.1.2-next.1 ### Patch Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index b1a83fbeb0..0cfebe36d6 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "1.1.2-next.1", + "version": "1.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 90caca8f18..9263da9053 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/cli +## 0.20.0-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/cli-common@0.1.10 + - @backstage/config@1.0.3-next.2 + - @backstage/config-loader@1.1.5-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/release-manifests@0.0.6 + - @backstage/types@1.0.0 + ## 0.20.0-next.1 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 66f69772d5..213c6dad00 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.20.0-next.1", + "version": "0.20.0-next.2", "publishConfig": { "access": "public" }, diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 673054c186..e95f39dcfe 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/codemods +## 0.1.40-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.10 + ## 0.1.40-next.1 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 4996887eed..37342231a8 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.40-next.1", + "version": "0.1.40-next.2", "publishConfig": { "access": "public", "main": "dist/index.cjs.js" diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 0c1afa75c1..42eaa97e53 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/config-loader +## 1.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.10 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + ## 1.1.5-next.1 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 3fb1da9e1f..7bd0ffb1bf 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": "1.1.5-next.1", + "version": "1.1.5-next.2", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 151201bfa7..a08d4341e4 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/config +## 1.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.0.0 + ## 1.0.3-next.1 ### Patch Changes diff --git a/packages/config/package.json b/packages/config/package.json index 2305784051..55891f8c63 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": "1.0.3-next.1", + "version": "1.0.3-next.2", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 8914390d89..0c197cfb1e 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-app-api +## 1.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/types@1.0.0 + - @backstage/version-bridge@1.0.1 + ## 1.1.1-next.1 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 219244eacc..c1beb853cb 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "1.1.1-next.1", + "version": "1.1.1-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index a27be20b9f..cb75cb5fb8 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/core-components +## 0.11.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/version-bridge@1.0.1 + ## 0.11.2-next.1 ### Patch Changes diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 99d18b9b12..9587a32ab5 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -242,6 +242,7 @@ export interface DependencyGraphProps acyclicer?: 'greedy'; // Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver align?: Alignment; + curve?: 'curveStepBefore' | 'curveMonotoneX'; defs?: SVGDefsElement | SVGDefsElement[]; // Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver direction?: Direction; diff --git a/packages/core-components/package.json b/packages/core-components/package.json index a32d8c9af8..3a58be3529 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.11.2-next.1", + "version": "0.11.2-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx index 9f447f80cc..5159f67d9e 100644 --- a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx +++ b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx @@ -162,6 +162,14 @@ export interface DependencyGraphProps * Default: `enabled` */ zoom?: 'enabled' | 'disabled' | 'enable-on-click'; + /** + * A factory for curve generators addressing both lines and areas. + * + * @remarks + * + * Default: 'curveMonotoneX' + */ + curve?: 'curveStepBefore' | 'curveMonotoneX'; } const WORKSPACE_ID = 'workspace'; @@ -194,6 +202,7 @@ export function DependencyGraph( renderLabel, defs, zoom = 'enabled', + curve = 'curveMonotoneX', ...svgProps } = props; const theme: BackstageTheme = useTheme(); @@ -424,6 +433,7 @@ export function DependencyGraph( setEdge={setEdge} render={renderLabel} edge={edge} + curve={curve} /> ); })} diff --git a/packages/core-components/src/components/DependencyGraph/Edge.test.tsx b/packages/core-components/src/components/DependencyGraph/Edge.test.tsx index db6fbe7552..21d677388e 100644 --- a/packages/core-components/src/components/DependencyGraph/Edge.test.tsx +++ b/packages/core-components/src/components/DependencyGraph/Edge.test.tsx @@ -21,6 +21,7 @@ import { RenderLabelProps } from './types'; const fromNode = 'node'; const toNode = 'other-node'; +const curve: 'curveStepBefore' | 'curveMonotoneX' = 'curveMonotoneX'; const edge = { points: [ @@ -46,6 +47,7 @@ const minProps = { setEdge, renderElement, edge, + curve, }; const label = 'label'; diff --git a/packages/core-components/src/components/DependencyGraph/Edge.tsx b/packages/core-components/src/components/DependencyGraph/Edge.tsx index cc6a044beb..aae737b9ea 100644 --- a/packages/core-components/src/components/DependencyGraph/Edge.tsx +++ b/packages/core-components/src/components/DependencyGraph/Edge.tsx @@ -25,7 +25,7 @@ import { DependencyEdge, LabelPosition, } from './types'; -import { ARROW_MARKER_ID, EDGE_TEST_ID, LABEL_TEST_ID } from './constants'; +import { EDGE_TEST_ID, LABEL_TEST_ID } from './constants'; import { DefaultLabel } from './DefaultLabel'; import dagre from 'dagre'; @@ -47,7 +47,7 @@ export type DependencyGraphEdgeClassKey = 'path' | 'label'; const useStyles = makeStyles( (theme: BackstageTheme) => ({ path: { - strokeWidth: 2, + strokeWidth: 1, stroke: theme.palette.textSubtle, fill: 'none', transition: `${theme.transitions.duration.shortest}ms`, @@ -70,23 +70,19 @@ export type EdgeComponentProps = { id: dagre.Edge, edge: DependencyEdge, ) => dagre.graphlib.Graph<{}>; + curve: 'curveStepBefore' | 'curveMonotoneX'; }; const renderDefault = (props: RenderLabelProps) => ( ); -const createPath = d3Shape - .line() - .x(d => d.x) - .y(d => d.y) - .curve(d3Shape.curveMonotoneX); - export function Edge({ render = renderDefault, setEdge, id, edge, + curve, }: EdgeComponentProps) { const { x = 0, y = 0, width, height, points } = edge; const labelProps: DependencyEdge = edge; @@ -114,6 +110,16 @@ export function Edge({ let path: string = ''; + const createPath = React.useMemo( + () => + d3Shape + .line() + .x(d => d.x) + .y(d => d.y) + .curve(d3Shape[curve]), + [curve], + ); + if (points) { const finitePoints = points.filter( (point: EdgePoint) => isFinite(point.x) && isFinite(point.y), @@ -124,12 +130,7 @@ export function Edge({ return ( <> {path && ( - + )} {labelProps.label ? ( { }; /** - * WarningPanel. Show a user friendly error message to a user similar to + * Show a user friendly error message to a user similar to * ErrorPanel except that the warning panel only shows the warning message to * the user. * diff --git a/packages/core-components/src/layout/ItemCard/ItemCard.tsx b/packages/core-components/src/layout/ItemCard/ItemCard.tsx index e2efd0c136..fedcf7de8f 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCard.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCard.tsx @@ -40,6 +40,7 @@ type ItemCardProps = { * This card type has been deprecated. Instead use plain MUI Card and helpers * where appropriate. * + * @example * ``` * * diff --git a/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx b/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx index b27d224418..885b43ca34 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx @@ -49,6 +49,7 @@ export type ItemCardGridProps = Partial> & { * A default grid to use when arranging "item cards" - cards that let users * select among several options. * + * @remarks * The immediate children are expected to be MUI Card components. * * Styles for the grid can be overridden using the `classes` prop, e.g.: diff --git a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx index d9443ffc9a..76cf668079 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx @@ -64,6 +64,7 @@ export type ItemCardHeaderProps = Partial> & { * A simple card header, rendering a default look for "item cards" - cards that * are arranged in a grid for users to select among several options. * + * @remarks * This component expects to be placed within a MUI ``. * * Styles for the header can be overridden using the `classes` prop, e.g.: diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index 5a0b92f558..4bc972e272 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -510,6 +510,7 @@ const SidebarItemWithSubmenu = ({ /** * Creates a `SidebarItem` * + * @remarks * If children contain a `SidebarSubmenu` component the `SidebarItem` will have a expandable submenu */ export const SidebarItem = forwardRef((props, ref) => { @@ -663,6 +664,8 @@ export const SidebarScrollWrapper = styled('div')(({ theme }) => { /** * A button which allows you to expand the sidebar when clicked. + * + * @remarks * Use optionally to replace sidebar's expand-on-hover feature with expand-on-click. * * If you are using this you might want to set the `disableExpandOnHover` of the `Sidebar` to `true`. diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx index c85e6d11f2..bfa841690d 100644 --- a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx +++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx @@ -159,6 +159,7 @@ export const MobileSidebarContext = createContext({ /** * A navigation component for mobile screens, which sticks to the bottom. * + * @remarks * It alternates the normal sidebar by grouping the `SidebarItems` based on provided `SidebarGroup`s * either rendering them as a link or an overlay menu. * If no `SidebarGroup`s are provided the sidebar content is wrapped in an default overlay menu. diff --git a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx index 1158cc14df..cb9c786ea9 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx @@ -115,6 +115,7 @@ const MobileSidebarGroup = (props: SidebarGroupProps) => { /** * Groups items of the `Sidebar` together. * + * @remarks * On bigger screens, this won't have any effect at the moment. * On small screens, it will add an action to the bottom navigation - either triggering an overlay menu or acting as a link * diff --git a/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx b/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx index a1565a348f..51092d7e81 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx @@ -111,6 +111,7 @@ export type SidebarSubmenuItemDropdownItem = { /** * Holds submenu item content. * + * @remarks * title: Text content of submenu item * subtitle: A subtitle displayed under the main title * to: Path to navigate to when item is clicked diff --git a/packages/core-components/src/layout/Sidebar/config.ts b/packages/core-components/src/layout/Sidebar/config.ts index bb0ff207fb..dacf4bd0a5 100644 --- a/packages/core-components/src/layout/Sidebar/config.ts +++ b/packages/core-components/src/layout/Sidebar/config.ts @@ -20,13 +20,13 @@ const drawerWidthClosed = 72; const iconPadding = 24; const userBadgePadding = 18; -/** @public **/ +/** @public */ export type SidebarOptions = { drawerWidthClosed?: number; drawerWidthOpen?: number; }; -/** @public **/ +/** @public */ export type SubmenuOptions = { drawerWidthClosed?: number; drawerWidthOpen?: number; diff --git a/packages/core-components/src/layout/SignInPage/types.ts b/packages/core-components/src/layout/SignInPage/types.ts index 0909e7242d..8a0430a27d 100644 --- a/packages/core-components/src/layout/SignInPage/types.ts +++ b/packages/core-components/src/layout/SignInPage/types.ts @@ -32,7 +32,7 @@ export type SignInProviderConfig = { apiRef: ApiRef; }; -/** @public **/ +/** @public */ export type IdentityProviders = ('guest' | 'custom' | SignInProviderConfig)[]; export type ProviderComponent = ComponentType< diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index 26e18ea244..f0ac2c4dfb 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/core-plugin-api +## 1.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/types@1.0.0 + - @backstage/version-bridge@1.0.1 + ## 1.0.7-next.1 ### Patch Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 48b78a1daf..c1097bdf9e 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "1.0.7-next.1", + "version": "1.0.7-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-plugin-api/src/routing/SubRouteRef.ts b/packages/core-plugin-api/src/routing/SubRouteRef.ts index 61d89fcbdb..14a614c2ba 100644 --- a/packages/core-plugin-api/src/routing/SubRouteRef.ts +++ b/packages/core-plugin-api/src/routing/SubRouteRef.ts @@ -72,7 +72,7 @@ export type ParamNames = export type PathParams = { [name in ParamNames]: string }; /** - * Merges a param object type with with an optional params type into a params object. + * Merges a param object type with an optional params type into a params object. * @public */ export type MergeParams< diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 0e1d1a98af..2640775b77 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/create-app +## 0.4.32-next.2 + +### Patch Changes + +- 01dff06be4: Leverage cache mounts in Dockerfile during `yarn install ...` and `apt-get ...` commands to speed up repeated builds. +- Updated dependencies + - @backstage/cli-common@0.1.10 + ## 0.4.32-next.1 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 9633c890fa..a42c7830df 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.4.32-next.1", + "version": "0.4.32-next.2", "publishConfig": { "access": "public" }, 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 928b8201ea..9f11d0c80c 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 @@ -14,6 +14,7 @@ import { SearchBar, SearchFilter, SearchResult, + SearchPagination, useSearch, } from '@backstage/plugin-search-react'; import { @@ -109,6 +110,7 @@ const SearchPage = () => { + {({ results }) => ( diff --git a/packages/create-app/templates/default-app/packages/backend/Dockerfile b/packages/create-app/templates/default-app/packages/backend/Dockerfile index 682798b826..3e9ca5ba48 100644 --- a/packages/create-app/templates/default-app/packages/backend/Dockerfile +++ b/packages/create-app/templates/default-app/packages/backend/Dockerfile @@ -13,9 +13,10 @@ FROM node:16-bullseye-slim # Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image, # in which case you should also move better-sqlite3 to "devDependencies" in package.json. -RUN apt-get update && \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + apt-get update && \ apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \ - rm -rf /var/lib/apt/lists/* && \ yarn config set python /usr/bin/python3 # From here on we use the least-privileged `node` user to run the backend. @@ -31,7 +32,8 @@ ENV NODE_ENV production COPY --chown=node:node yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz -RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" +RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \ + yarn install --frozen-lockfile --production --network-timeout 300000 # Then copy the rest of the backend bundle, along with any other files we might want. COPY --chown=node:node packages/backend/dist/bundle.tar.gz app-config*.yaml ./ diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 01c97a4c74..31ca46b945 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/dev-utils +## 1.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/test-utils@1.2.1-next.2 + - @backstage/app-defaults@1.0.7-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + ## 1.0.7-next.1 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 60c877f736..990b45d692 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "1.0.7-next.1", + "version": "1.0.7-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 26f45611fc..fe478f0bd7 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/errors +## 1.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.0.0 + ## 1.1.2-next.1 ### Patch Changes diff --git a/packages/errors/package.json b/packages/errors/package.json index ad10bb7ed5..e78ecb45d2 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": "1.1.2-next.1", + "version": "1.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 00439a9771..a547cf131a 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/integration-react +## 1.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/theme@0.2.16 + ## 1.1.5-next.1 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index cab328f88d..f097a116b4 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": "1.1.5-next.1", + "version": "1.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 134dc34c11..e3433efaf8 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration +## 1.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + ## 1.3.2-next.1 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index 169bf56353..cf2c7af7fe 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": "1.3.2-next.1", + "version": "1.3.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 49b59771c3..cc2fdb84a3 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,24 @@ # techdocs-cli-embedded-app +## 0.2.75-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.20.0-next.2 + - @backstage/plugin-catalog@1.6.0-next.2 + - @backstage/test-utils@1.2.1-next.2 + - @backstage/app-defaults@1.0.7-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs@1.3.3-next.2 + - @backstage/plugin-techdocs-react@1.0.5-next.2 + ## 0.2.75-next.1 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 25eb9f2b27..b6b2a40832 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.75-next.1", + "version": "0.2.75-next.2", "private": true, "backstage": { "role": "frontend" diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index c04b3b8681..3fee2b5e70 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @techdocs/cli +## 1.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-techdocs-node@1.4.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/cli-common@0.1.10 + - @backstage/config@1.0.3-next.2 + ## 1.2.2-next.1 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 3f00391865..63dbe14e03 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "1.2.2-next.1", + "version": "1.2.2-next.2", "publishConfig": { "access": "public" }, diff --git a/packages/techdocs-cli/src/example-docs/docs/index.md b/packages/techdocs-cli/src/example-docs/docs/index.md index 074d3ccb3e..66e4c96b2f 100644 --- a/packages/techdocs-cli/src/example-docs/docs/index.md +++ b/packages/techdocs-cli/src/example-docs/docs/index.md @@ -73,20 +73,20 @@ const addThingToThing = (a, b) a + b; # MDX truly sane lists -- attributes +- `attributes` -- customer - - first_name - - test - - family_name - - email -- person - - first_name - - family_name - - birth_date -- subscription_id +- `customer` + - `first_name` + - `test` + - `family_name` + - `email` +- `person` + - `first_name` + - `family_name` + - `birth_date` +- `subscription_id` -- request +- `request` *[MOCDOC]: Mock Documentation diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 28a4a92294..4495c72de1 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/test-utils +## 1.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-react@0.4.6-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/core-app-api@1.1.1-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.0 + ## 1.2.1-next.1 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index a7bcbab826..f950c42dde 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "1.2.1-next.1", + "version": "1.2.1-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index a13f16e340..3349492a65 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-adr-backend +## 0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/plugin-adr-common@0.2.2-next.2 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index ff232e6b69..903e462bc9 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.2.2-next.1", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr-backend/src/search/DefaultAdrCollatorFactory.ts b/plugins/adr-backend/src/search/DefaultAdrCollatorFactory.ts index 21f0f1945f..78f6e0226e 100644 --- a/plugins/adr-backend/src/search/DefaultAdrCollatorFactory.ts +++ b/plugins/adr-backend/src/search/DefaultAdrCollatorFactory.ts @@ -113,7 +113,7 @@ export class DefaultAdrCollatorFactory implements DocumentCollatorFactory { this.catalogClient = options.catalogClient ?? new CatalogClient({ discoveryApi: options.discovery }); - this.logger = options.logger; + this.logger = options.logger.child({ documentType: this.type }); this.parser = options.parser ?? createMadrParser(); this.reader = options.reader; this.scmIntegrations = ScmIntegrations.fromConfig(options.config); diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index d1738d9920..3472fc1e18 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-adr-common +## 0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index 8358349631..7bfd4d4aa2 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.2.2-next.1", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index 7ac3655e03..544b13ef77 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-adr +## 0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/integration-react@1.1.5-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-adr-common@0.2.2-next.2 + - @backstage/plugin-search-react@1.2.0-next.2 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 4eb9cf7b03..dc324e05f2 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.2.2-next.1", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index b61f76db54..45a049c672 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-airbrake-backend +## 0.2.10-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + ## 0.2.10-next.1 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 2817861740..a96a05e753 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.2.10-next.1", + "version": "0.2.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index c466c6cb3a..cf7f67e46b 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-airbrake +## 0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/test-utils@1.2.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/dev-utils@1.0.7-next.2 + - @backstage/theme@0.2.16 + ## 0.3.10-next.1 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 28677b7948..d81ddf3cdf 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.10-next.1", + "version": "0.3.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index ae170e29c7..c9f80be792 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-allure +## 0.1.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + ## 0.1.26-next.1 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 1691a77ecf..395295512a 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.26-next.1", + "version": "0.1.26-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 13c445f246..8e7cbbed8d 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-ga +## 0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.3-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + ## 0.1.21-next.1 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 87d6d4f0fc..56489d3753 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.21-next.1", + "version": "0.1.21-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 5cd28f0827..37504b440d 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-apache-airflow +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + ## 0.2.3-next.1 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 5f9c1b4f9d..f3baa62412 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.2.3-next.1", + "version": "0.2.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 432ff12f76..75b2e41b0b 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-api-docs +## 0.8.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + ## 0.8.10-next.1 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index bd38fa9c65..695cbbc1ef 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.8.10-next.1", + "version": "0.8.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index a1c6c6c8df..405f7558ad 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-apollo-explorer +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + ## 0.1.3-next.1 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index a5e598ede1..ddf5996037 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.3-next.1", + "version": "0.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index b1b112a030..8e9ad5420b 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-app-backend +## 0.3.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/config-loader@1.1.5-next.2 + - @backstage/types@1.0.0 + ## 0.3.37-next.1 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index db100ea12b..64378b4adf 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-backend", "description": "A Backstage backend plugin that serves the Backstage frontend app", - "version": "0.3.37-next.1", + "version": "0.3.37-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index afa2d700fd..54cce8a7b0 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-auth-backend +## 0.17.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + ## 0.17.0-next.1 ### Minor Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index be02a90a71..0a199443b1 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.17.0-next.1", + "version": "0.17.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 147861383f..b84e726467 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-node +## 0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + ## 0.2.6-next.1 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 7c0c3b51e2..7649826982 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.2.6-next.1", + "version": "0.2.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 00cc426c0e..3516169016 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-azure-devops-backend +## 0.3.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.3.16-next.1 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 27be6291ed..062fa44c0b 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.3.16-next.1", + "version": "0.3.16-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index 4919b1226d..f3538acd45 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-azure-devops +## 0.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.2.1-next.1 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 14f2c29310..dca00111f6 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.2.1-next.1", + "version": "0.2.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 770491ec15..0b980d94c4 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-badges-backend +## 0.1.31-next.2 + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + ## 0.1.31-next.1 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 678dc8d56e..ea3524ce8a 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.1.31-next.1", + "version": "0.1.31-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 5adc7d112b..3692f7280a 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-badges +## 0.2.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/theme@0.2.16 + ## 0.2.34-next.1 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 0f05f6fa25..18d9f76ce6 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.34-next.1", + "version": "0.2.34-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index bb39eff121..53d888b247 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-bazaar-backend +## 0.2.0-next.2 + +### Minor Changes + +- 8554533546: **BREAKING** The bazaar-backend `createRouter` now requires that the `identityApi` is passed to the router. + + These changes are **required** to `packages/backend/src/plugins/bazaar.ts` + + The user entity ref is now added to the members table and is taken from the requesting user using the `identityApi`. + + ```diff + import { PluginEnvironment } from '../types'; + import { createRouter } from '@backstage/plugin-bazaar-backend'; + import { Router } from 'express'; + + export default async function createPlugin( + env: PluginEnvironment, + ): Promise { + return await createRouter({ + logger: env.logger, + config: env.config, + database: env.database, + + identity: env.identity, + }); + } + ``` + +### Patch Changes + +- f7c2855d76: Router now also has endpoint `getLatestProjects` that takes a limit of projects as prop. +- Updated dependencies + - @backstage/backend-common@0.15.2-next.2 + - @backstage/backend-test-utils@0.1.29-next.2 + - @backstage/plugin-auth-node@0.2.6-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + ## 0.1.21-next.1 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 131959cbd6..9a203ed0f2 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.1.21-next.1", + "version": "0.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,6 +25,7 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/config": "workspace:^", + "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@types/express": "^4.17.6", "express": "^4.17.1", diff --git a/plugins/bazaar-backend/src/service/DatabaseHandler.ts b/plugins/bazaar-backend/src/service/DatabaseHandler.ts index 352866b4b5..8fbe985a10 100644 --- a/plugins/bazaar-backend/src/service/DatabaseHandler.ts +++ b/plugins/bazaar-backend/src/service/DatabaseHandler.ts @@ -175,14 +175,22 @@ export class DatabaseHandler { return await this.client('metadata').where({ id: id }).del(); } - async getProjects() { + async getProjects(limit?: number, order?: string) { const coalesce = this.client.raw( 'coalesce(count(members.item_id), 0) as members_count', ); - - return await this.client('metadata') + let get = this.client('metadata') .select([...this.columns, coalesce]) - .groupBy(this.columns) - .leftJoin('members', 'metadata.id', '=', 'members.item_id'); + .groupBy(this.columns); + if (limit) { + get = get.limit(limit); + } + if (order === 'latest') { + get = get.orderByRaw('id desc'); + } + if (order === 'random') { + get = get.orderByRaw('RANDOM()'); + } + return await get.leftJoin('members', 'metadata.id', '=', 'members.item_id'); } } diff --git a/plugins/bazaar-backend/src/service/router.ts b/plugins/bazaar-backend/src/service/router.ts index 359945f298..f902d0e8cc 100644 --- a/plugins/bazaar-backend/src/service/router.ts +++ b/plugins/bazaar-backend/src/service/router.ts @@ -92,8 +92,14 @@ export async function createRouter( response.json({ status: 'ok', data: data }); }); - router.get('/projects', async (_, response) => { - const data = await dbHandler.getProjects(); + router.get('/projects', async (request, response) => { + const limit = request.query.limit?.toString(); + const order = request.query.order?.toString(); + + const data = await dbHandler.getProjects( + limit ? parseInt(limit, 10) : undefined, + order, + ); response.json({ status: 'ok', data: data }); }); diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index b2d0e8a8d4..c5042a6585 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-bazaar +## 0.1.25-next.2 + +### Patch Changes + +- f7c2855d76: Added a `Overview Card` for either latest or random projects. Changed `ProjectPreview.tsx` so it take `gridSize` and `useTablePagination` as props. +- c0352bbc69: Link to the user catalog entity of a member +- Updated dependencies + - @backstage/cli@0.20.0-next.2 + - @backstage/plugin-catalog@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/errors@1.1.2-next.2 + ## 0.1.25-next.1 ### Patch Changes diff --git a/plugins/bazaar/README.md b/plugins/bazaar/README.md index eeebf6eb19..6168b0c4ba 100644 --- a/plugins/bazaar/README.md +++ b/plugins/bazaar/README.md @@ -64,6 +64,30 @@ const overviewContent = ( {/* ...other entity-cards */} ``` +Add a **Bazaar overview card** to the homepage that displays either the latest projects or random projects. In `packages/app/src/components/home/HomePage.tsx` add: + +```diff ++ import { BazaarOverviewCard } from '@backstage/plugin-bazaar'; + +export const homePage = ( + + + + + ++ ++ ++ + ++ ++ ++ + + {/* ...other homepage items */} +``` + +Specify how many projects you want through the "limit" props. In the example above 4 cards is specified. + ## How does the Bazaar work? ### Layout @@ -72,6 +96,10 @@ The latest modified Bazaar projects are displayed in the Bazaar landing page, lo ![home](media/layout.png) +The "BazaarOverviewCard" can be displayed in Backstage homepage. + +![home](media/overviewCard.png) + ### Workflow To add a project to the bazaar, simply click on the `add-project` button and fill in the form. diff --git a/plugins/bazaar/api-report.md b/plugins/bazaar/api-report.md index c6afde73f2..2e6ebe6746 100644 --- a/plugins/bazaar/api-report.md +++ b/plugins/bazaar/api-report.md @@ -8,6 +8,17 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { RouteRef } from '@backstage/core-plugin-api'; +// @public (undocumented) +export const BazaarOverviewCard: ( + props: BazaarOverviewCardProps, +) => JSX.Element; + +// @public (undocumented) +export type BazaarOverviewCardProps = { + order: 'latest' | 'random'; + limit: number; +}; + // @public (undocumented) export const BazaarPage: () => JSX.Element; diff --git a/plugins/bazaar/media/overviewCard.png b/plugins/bazaar/media/overviewCard.png new file mode 100644 index 0000000000..676764f6e4 Binary files /dev/null and b/plugins/bazaar/media/overviewCard.png differ diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index c88357ef4a..94905d0387 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.1.25-next.1", + "version": "0.1.25-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,6 +27,7 @@ "@backstage/cli": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", "@backstage/plugin-catalog": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@date-io/luxon": "1.x", diff --git a/plugins/bazaar/src/api.ts b/plugins/bazaar/src/api.ts index d2486f74dc..33455e69fc 100644 --- a/plugins/bazaar/src/api.ts +++ b/plugins/bazaar/src/api.ts @@ -20,6 +20,7 @@ import { FetchApi, IdentityApi, } from '@backstage/core-plugin-api'; +import { ResponseError } from '@backstage/errors'; export const bazaarApiRef = createApiRef({ id: 'bazaar', @@ -40,7 +41,7 @@ export interface BazaarApi { addMember(id: number, userId: string): Promise; - getProjects(): Promise; + getProjects(limit?: number, order?: string): Promise; deleteProject(id: number): Promise; } @@ -148,12 +149,20 @@ export class BazaarClient implements BazaarApi { ); } - async getProjects(): Promise { + async getProjects(limit?: number, order?: string): Promise { const baseUrl = await this.discoveryApi.getBaseUrl('bazaar'); + const params = { + ...(limit ? { limit: limit.toString() } : {}), + ...(order ? { order } : {}), + }; + const query = new URLSearchParams(params); + const url = `projects?${query.toString()}`; - return await this.fetchApi - .fetch(`${baseUrl}/projects`) - .then(resp => resp.json()); + const data = await this.fetchApi.fetch(`${baseUrl}/${url}`); + if (!data.ok) { + throw await ResponseError.fromResponse(data); + } + return data.json(); } async deleteProject(id: number): Promise { diff --git a/plugins/bazaar/src/components/BazaarOverviewCard/BazaarOverviewCard.tsx b/plugins/bazaar/src/components/BazaarOverviewCard/BazaarOverviewCard.tsx new file mode 100644 index 0000000000..83358c0a05 --- /dev/null +++ b/plugins/bazaar/src/components/BazaarOverviewCard/BazaarOverviewCard.tsx @@ -0,0 +1,141 @@ +/* + * 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, { useEffect, useState } from 'react'; +import { ProjectPreview } from '../ProjectPreview/ProjectPreview'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { useApi, useRouteRef } from '@backstage/core-plugin-api'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import type { BazaarProject } from '../../types'; +import { bazaarApiRef } from '../../api'; +import { fetchCatalogItems } from '../../util/fetchMethods'; +import { parseBazaarProject } from '../../util/parseMethods'; +import { ErrorPanel, InfoCard } from '@backstage/core-components'; +import { bazaarPlugin } from '../../plugin'; + +/** @public */ +export type BazaarOverviewCardProps = { + order: 'latest' | 'random'; + limit: number; +}; + +const getUnlinkedCatalogEntities = ( + bazaarProjects: BazaarProject[], + catalogEntities: Entity[], +) => { + const bazaarProjectRefs = bazaarProjects.map( + (project: BazaarProject) => project.entityRef, + ); + + return catalogEntities.filter((entity: Entity) => { + return !bazaarProjectRefs?.includes(stringifyEntityRef(entity)); + }); +}; + +/** @public */ +export const BazaarOverviewCard = (props: BazaarOverviewCardProps) => { + const { order, limit } = props; + const bazaarApi = useApi(bazaarApiRef); + const catalogApi = useApi(catalogApiRef); + const root = useRouteRef(bazaarPlugin.routes.root); + + const bazaarLink = { + title: 'Go to Bazaar', + link: root.toString(), + }; + + const [unlinkedCatalogEntities, setUnlinkedCatalogEntities] = + useState(); + + const [catalogEntities, fetchCatalogEntities] = useAsyncFn(async () => { + return await fetchCatalogItems(catalogApi); + }); + + const [bazaarProjects, fetchBazaarProjects] = useAsyncFn(async () => { + const response = await bazaarApi.getProjects(limit, order); + return response.data.map(parseBazaarProject) as BazaarProject[]; + }); + + const catalogEntityRefs = catalogEntities.value?.map((project: Entity) => + stringifyEntityRef(project), + ); + + useEffect(() => { + const filterBrokenLinks = () => { + if (catalogEntityRefs) { + bazaarProjects.value?.forEach(async (project: BazaarProject) => { + if (project.entityRef) { + if (!catalogEntityRefs?.includes(project.entityRef)) { + await bazaarApi.updateProject({ + ...project, + entityRef: null, + }); + } + } + }); + } + }; + filterBrokenLinks(); + }, [ + bazaarApi, + bazaarProjects.value, + catalogEntityRefs, + catalogEntities.value, + ]); + + useEffect(() => { + fetchCatalogEntities(); + fetchBazaarProjects(); + }, [fetchBazaarProjects, fetchCatalogEntities]); + + useEffect(() => { + const unlinkedCEntities = getUnlinkedCatalogEntities( + bazaarProjects.value || [], + catalogEntities.value || [], + ); + + if (unlinkedCEntities) { + setUnlinkedCatalogEntities(unlinkedCEntities); + } + }, [bazaarProjects, catalogEntities]); + + if (catalogEntities.error) { + return ; + } + + if (bazaarProjects.error) { + return ; + } + + return ( + + + + ); +}; diff --git a/plugins/bazaar/src/components/BazaarOverviewCard/index.ts b/plugins/bazaar/src/components/BazaarOverviewCard/index.ts new file mode 100644 index 0000000000..06ea623e1b --- /dev/null +++ b/plugins/bazaar/src/components/BazaarOverviewCard/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +export { BazaarOverviewCard } from './BazaarOverviewCard'; +export type { BazaarOverviewCardProps } from './BazaarOverviewCard'; diff --git a/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx b/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx index 3aeba305a9..dace9b8185 100644 --- a/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx +++ b/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx @@ -30,6 +30,13 @@ import { DateTime } from 'luxon'; import { HomePageBazaarInfoCard } from '../HomePageBazaarInfoCard'; import { Entity } from '@backstage/catalog-model'; +type Props = { + project: BazaarProject; + fetchBazaarProjects: () => Promise; + catalogEntities: Entity[]; + fullHeight?: boolean; +}; + const useStyles = makeStyles({ statusTag: { display: 'inline-block', @@ -47,7 +54,7 @@ const useStyles = makeStyles({ float: 'right', }, content: { - height: '13rem', + overflow: 'scroll', }, header: { whiteSpace: 'nowrap', @@ -56,16 +63,11 @@ const useStyles = makeStyles({ }, }); -type Props = { - project: BazaarProject; - fetchBazaarProjects: () => Promise; - catalogEntities: Entity[]; -}; - export const ProjectCard = ({ project, fetchBazaarProjects, catalogEntities, + fullHeight, }: Props) => { const classes = useStyles(); const [openCard, setOpenCard] = useState(false); @@ -101,7 +103,10 @@ export const ProjectCard = ({ base: DateTime.now(), })}`} /> - + {Number(membersCount) === Number(1) diff --git a/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx b/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx index 435d80408d..77c16ef306 100644 --- a/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx +++ b/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx @@ -25,6 +25,9 @@ type Props = { bazaarProjects: BazaarProject[]; fetchBazaarProjects: () => Promise; catalogEntities: Entity[]; + useTablePagination?: boolean; + fullHeight?: boolean; + fixedWidth?: boolean; }; const useStyles = makeStyles({ @@ -51,6 +54,9 @@ export const ProjectPreview = ({ bazaarProjects, fetchBazaarProjects, catalogEntities, + useTablePagination = true, + fullHeight = true, + fixedWidth = false, }: Props) => { const classes = useStyles(); const [page, setPage] = useState(1); @@ -80,31 +86,39 @@ export const ProjectPreview = ({ .slice((page - 1) * rows, rows * page) .map((bazaarProject: BazaarProject, i: number) => { return ( - + ); })} - = bazaarProjects.length, - }} - /> + {useTablePagination && ( + = bazaarProjects.length, + }} + /> + )} ); }; diff --git a/plugins/bazaar/src/index.ts b/plugins/bazaar/src/index.ts index 895469c031..0014c66b6d 100644 --- a/plugins/bazaar/src/index.ts +++ b/plugins/bazaar/src/index.ts @@ -15,5 +15,7 @@ */ export { bazaarPlugin, BazaarPage } from './plugin'; +export { BazaarOverviewCard } from './components/BazaarOverviewCard'; +export type { BazaarOverviewCardProps } from './components/BazaarOverviewCard'; export { EntityBazaarInfoCard } from './components/EntityBazaarInfoCard'; export { SortView } from './components/SortView'; diff --git a/plugins/bitbucket-cloud-common/CHANGELOG.md b/plugins/bitbucket-cloud-common/CHANGELOG.md index 2dc4bd1ae3..0fb56e97ae 100644 --- a/plugins/bitbucket-cloud-common/CHANGELOG.md +++ b/plugins/bitbucket-cloud-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-bitbucket-cloud-common +## 0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.3.2-next.2 + ## 0.2.0-next.1 ### Patch Changes diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index 10d443e2a5..50b2706494 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitbucket-cloud-common", "description": "Common functionalities for bitbucket-cloud plugins", - "version": "0.2.0-next.1", + "version": "0.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index d8781740ec..987576897a 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-bitrise +## 0.1.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + ## 0.1.37-next.1 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 0645020104..29c6be025c 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.37-next.1", + "version": "0.1.37-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 54717bb37d..e1b79a9bee 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + ## 0.1.10-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 8be3ca3031..8a511b0019 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", "description": "A Backstage catalog backend module that helps integrate towards AWS", - "version": "0.1.10-next.1", + "version": "0.1.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 4342307cf5..bdd495a472 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + ## 0.1.8-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 0385655259..5ccc68a70e 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", "description": "A Backstage catalog backend module that helps integrate towards Azure", - "version": "0.1.8-next.1", + "version": "0.1.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index bbc999591c..4df7a0fd82 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.4-next.2 + +### Patch Changes + +- f66e696e7b: Bitbucket Cloud provider: Add option to configure schedule via `app-config.yaml` instead of in code. + + Please find how to configure the schedule at the config at + https://backstage.io/docs/integrations/bitbucketCloud/discovery + +- a9b91d39bb: Add `bitbucketCloudCatalogModule` (new backend-plugin-api, alpha). +- Updated dependencies + - @backstage/plugin-catalog-node@1.2.0-next.2 + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.0-next.2 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 54603b128f..df8fd11e8c 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index ca248ce215..7ba7e97d21 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 2490b79ffa..94b9cdd780 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.1.2-next.1", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index eb9eb97acc..448b4b6eee 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.4-next.2 + +### Patch Changes + +- 23f9199a0f: Deprecate `@backstage/plugin-catalog-backend-module-bitbucket`. + + Please migrate to `@backstage/plugin-catalog-backend-module-bitbucket-cloud` + or `@backstage/plugin-catalog-backend-module-bitbucket-server` instead. + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.0-next.2 + ## 0.2.4-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/api-report.md b/plugins/catalog-backend-module-bitbucket/api-report.md index 34acd6e76d..053c6040a4 100644 --- a/plugins/catalog-backend-module-bitbucket/api-report.md +++ b/plugins/catalog-backend-module-bitbucket/api-report.md @@ -12,7 +12,7 @@ import { LocationSpec } from '@backstage/plugin-catalog-backend'; import { Logger } from 'winston'; import { ScmIntegrationRegistry } from '@backstage/integration'; -// @public (undocumented) +// @public @deprecated (undocumented) export class BitbucketDiscoveryProcessor implements CatalogProcessor { constructor(options: { integrations: ScmIntegrationRegistry; @@ -37,7 +37,7 @@ export class BitbucketDiscoveryProcessor implements CatalogProcessor { ): Promise; } -// @public +// @public @deprecated export type BitbucketRepositoryParser = (options: { integration: BitbucketIntegration; target: string; diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index ff0594154d..dd6ebbf75c 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -1,7 +1,8 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket", - "version": "0.2.4-next.1", + "version": "0.2.4-next.2", + "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket/src/BitbucketDiscoveryProcessor.ts b/plugins/catalog-backend-module-bitbucket/src/BitbucketDiscoveryProcessor.ts index 14bf90ee62..6924765483 100644 --- a/plugins/catalog-backend-module-bitbucket/src/BitbucketDiscoveryProcessor.ts +++ b/plugins/catalog-backend-module-bitbucket/src/BitbucketDiscoveryProcessor.ts @@ -41,7 +41,10 @@ import { const DEFAULT_BRANCH = 'master'; const DEFAULT_CATALOG_LOCATION = '/catalog-info.yaml'; -/** @public */ +/** + * @public + * @deprecated Please migrate to `@backstage/plugin-catalog-backend-module-bitbucket-cloud` or `@backstage/plugin-catalog-backend-module-bitbucket-server` instead. + */ export class BitbucketDiscoveryProcessor implements CatalogProcessor { private readonly integrations: ScmIntegrationRegistry; private readonly parser: BitbucketRepositoryParser; @@ -70,6 +73,9 @@ export class BitbucketDiscoveryProcessor implements CatalogProcessor { this.integrations = options.integrations; this.parser = options.parser || defaultRepositoryParser; this.logger = options.logger; + this.logger.warn( + 'Please migrate to `@backstage/plugin-catalog-backend-module-bitbucket-cloud` or `@backstage/plugin-catalog-backend-module-bitbucket-server` instead.', + ); } getProcessorName(): string { diff --git a/plugins/catalog-backend-module-bitbucket/src/lib/BitbucketRepositoryParser.ts b/plugins/catalog-backend-module-bitbucket/src/lib/BitbucketRepositoryParser.ts index 57a162e1e4..97225e2579 100644 --- a/plugins/catalog-backend-module-bitbucket/src/lib/BitbucketRepositoryParser.ts +++ b/plugins/catalog-backend-module-bitbucket/src/lib/BitbucketRepositoryParser.ts @@ -26,6 +26,7 @@ import { Logger } from 'winston'; * results. * * @public + * @deprecated Please migrate to `@backstage/plugin-catalog-backend-module-bitbucket-cloud` or `@backstage/plugin-catalog-backend-module-bitbucket-server` instead. */ export type BitbucketRepositoryParser = (options: { integration: BitbucketIntegration; diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index 8e1b11c1f7..bba01147a2 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + ## 0.1.5-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index e3665a96ae..23ae165a01 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.1.5-next.1", + "version": "0.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 1a7a4a512c..e52ec4390b 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-github +## 0.1.8-next.2 + +### Patch Changes + +- 7022aebf35: Added `GitHubLocationAnalyzer`. This can be used to add to the `CatalogBuilder`. When added this will be used by `RepoLocationAnalyzer` to figure out if the given URL that you are trying to import from the /catalog-import page already contains catalog-info.yaml files. +- 7edb5909e8: Add missing config schema for the `GitHubEntityProvider`. +- Updated dependencies + - @backstage/plugin-catalog-node@1.2.0-next.2 + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + ## 0.1.8-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/api-report.md b/plugins/catalog-backend-module-github/api-report.md index 8e8055bafc..4ab534e6d3 100644 --- a/plugins/catalog-backend-module-github/api-report.md +++ b/plugins/catalog-backend-module-github/api-report.md @@ -3,19 +3,23 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AnalyzeOptions } from '@backstage/plugin-catalog-backend'; import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; +import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-backend'; import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; import { GithubCredentialsProvider } from '@backstage/integration'; import { GitHubIntegrationConfig } from '@backstage/integration'; import { LocationSpec } from '@backstage/plugin-catalog-backend'; import { Logger } from 'winston'; +import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { ScmIntegrationRegistry } from '@backstage/integration'; +import { ScmLocationAnalyzer } from '@backstage/plugin-catalog-backend'; import { TaskRunner } from '@backstage/backend-tasks'; -import { TaskScheduleDefinition } from '@backstage/backend-tasks'; // @public export class GithubDiscoveryProcessor implements CatalogProcessor { @@ -51,7 +55,8 @@ export class GitHubEntityProvider implements EntityProvider { config: Config, options: { logger: Logger; - schedule: TaskRunner; + schedule?: TaskRunner; + scheduler?: PluginTaskScheduler; }, ): GitHubEntityProvider[]; // (undocumented) @@ -62,12 +67,31 @@ export class GitHubEntityProvider implements EntityProvider { // @alpha export const githubEntityProviderCatalogModule: ( - options?: GithubEntityProviderCatalogModuleOptions | undefined, + options?: undefined, ) => BackendFeature; -// @alpha -export type GithubEntityProviderCatalogModuleOptions = { - schedule?: TaskScheduleDefinition; +// @public (undocumented) +export class GitHubLocationAnalyzer implements ScmLocationAnalyzer { + constructor(options: GitHubLocationAnalyzerOptions); + // (undocumented) + analyze({ url, catalogFilename }: AnalyzeOptions): Promise<{ + existing: { + location: { + type: string; + target: string; + }; + isRegistered: boolean; + entity: Entity; + }[]; + }>; + // (undocumented) + supports(url: string): boolean; +} + +// @public (undocumented) +export type GitHubLocationAnalyzerOptions = { + config: Config; + discovery: PluginEndpointDiscovery; }; // @public diff --git a/plugins/catalog-backend-module-github/config.d.ts b/plugins/catalog-backend-module-github/config.d.ts index 1dcd49ea4e..8648490001 100644 --- a/plugins/catalog-backend-module-github/config.d.ts +++ b/plugins/catalog-backend-module-github/config.d.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { TaskScheduleDefinitionConfig } from '@backstage/backend-tasks'; + export interface Config { catalog?: { processors?: { @@ -103,6 +105,10 @@ export interface Config { exclude?: string[]; }; }; + /** + * (Optional) TaskScheduleDefinition for the refresh. + */ + schedule?: TaskScheduleDefinitionConfig; } | Record< string, @@ -156,6 +162,10 @@ export interface Config { exclude?: string[]; }; }; + /** + * (Optional) TaskScheduleDefinition for the refresh. + */ + schedule?: TaskScheduleDefinitionConfig; } >; }; diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 686b45f13c..0fd75b6a11 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.1.8-next.1", + "version": "0.1.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,6 +36,7 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", + "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", @@ -44,6 +45,8 @@ "@backstage/plugin-catalog-node": "workspace:^", "@backstage/types": "workspace:^", "@octokit/graphql": "^5.0.0", + "@octokit/rest": "^19.0.3", + "git-url-parse": "^13.0.0", "lodash": "^4.17.21", "msw": "^0.47.0", "node-fetch": "^2.6.7", @@ -53,7 +56,8 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@types/lodash": "^4.14.151" + "@types/lodash": "^4.14.151", + "luxon": "^3.0.0" }, "files": [ "dist", diff --git a/plugins/catalog-backend-module-github/src/analyzers/GitHubLocationAnalyzer.test.ts b/plugins/catalog-backend-module-github/src/analyzers/GitHubLocationAnalyzer.test.ts new file mode 100644 index 0000000000..0dcc131502 --- /dev/null +++ b/plugins/catalog-backend-module-github/src/analyzers/GitHubLocationAnalyzer.test.ts @@ -0,0 +1,156 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const octokit = { + search: { + code: jest.fn(), + }, + repos: { + get: jest.fn(), + }, +}; + +jest.mock('@octokit/rest', () => { + class Octokit { + constructor() { + return octokit; + } + } + return { Octokit }; +}); + +import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { GitHubLocationAnalyzer } from './GitHubLocationAnalyzer'; +import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { setupServer } from 'msw/node'; +import { rest } from 'msw'; +import { ConfigReader } from '@backstage/config'; + +const server = setupServer(); + +describe('GitHubLocationAnalyzer', () => { + const mockDiscoveryApi: jest.Mocked = { + getBaseUrl: jest.fn().mockResolvedValue('http://localhost:7007'), + getExternalBaseUrl: jest.fn(), + }; + const config = new ConfigReader({ + integrations: { + github: [ + { + host: 'h.com', + token: 't', + }, + ], + }, + }); + + setupRequestMockHandlers(server); + + beforeEach(() => { + server.use( + rest.post('http://localhost:7007/locations', async (_, res, ctx) => { + return res( + ctx.status(201), + ctx.json({ + location: 'test', + exists: false, + entities: [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Location', + metadata: { + name: 'test-entity', + }, + spec: { + type: 'url', + target: 'whatever', + }, + }, + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + title: 'Test Entity', + name: 'test-entity-2', + description: 'The expected description 2', + }, + spec: { + type: 'some-type', + lifecycle: 'experimental', + owner: 'someone', + }, + }, + ], + }), + ); + }), + ); + + octokit.repos.get.mockResolvedValue({ + data: { default_branch: 'my_default_branch' }, + }); + }); + + it('should analyze', async () => { + octokit.search.code.mockImplementation((opts: { q: string }) => { + if (opts.q === 'filename:catalog-info.yaml repo:foo/bar') { + return Promise.resolve({ + data: { items: [{ path: 'catalog-info.yaml' }], total_count: 1 }, + }); + } + return Promise.reject(); + }); + + const analyzer = new GitHubLocationAnalyzer({ + discovery: mockDiscoveryApi, + config, + }); + const result = await analyzer.analyze({ + url: 'https://github.com/foo/bar', + }); + + expect(result.existing[0].isRegistered).toBeFalsy(); + expect(result.existing[0].location).toEqual({ + type: 'url', + target: + 'https://github.com/foo/bar/blob/my_default_branch/catalog-info.yaml', + }); + }); + it('should use the provided entity filename for search', async () => { + octokit.search.code.mockImplementation((opts: { q: string }) => { + if (opts.q === 'filename:anvil.yaml repo:foo/bar') { + return Promise.resolve({ + data: { items: [{ path: 'anvil.yaml' }], total_count: 1 }, + }); + } + return Promise.reject(); + }); + + const analyzer = new GitHubLocationAnalyzer({ + discovery: mockDiscoveryApi, + config, + }); + const result = await analyzer.analyze({ + url: 'https://github.com/foo/bar', + catalogFilename: 'anvil.yaml', + }); + + expect(result.existing[0].location).toEqual({ + type: 'url', + target: 'https://github.com/foo/bar/blob/my_default_branch/anvil.yaml', + }); + }); +}); diff --git a/plugins/catalog-backend-module-github/src/analyzers/GitHubLocationAnalyzer.ts b/plugins/catalog-backend-module-github/src/analyzers/GitHubLocationAnalyzer.ts new file mode 100644 index 0000000000..d1112d2cc0 --- /dev/null +++ b/plugins/catalog-backend-module-github/src/analyzers/GitHubLocationAnalyzer.ts @@ -0,0 +1,103 @@ +/* + * 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 { CatalogApi, CatalogClient } from '@backstage/catalog-client'; +import { ScmIntegrations } from '@backstage/integration'; +import { Octokit } from '@octokit/rest'; +import { trimEnd } from 'lodash'; +import parseGitUrl from 'git-url-parse'; +import { + AnalyzeOptions, + ScmLocationAnalyzer, +} from '@backstage/plugin-catalog-backend'; +import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { Config } from '@backstage/config'; + +/** @public */ +export type GitHubLocationAnalyzerOptions = { + config: Config; + discovery: PluginEndpointDiscovery; +}; +/** @public */ +export class GitHubLocationAnalyzer implements ScmLocationAnalyzer { + private readonly catalogClient: CatalogApi; + private readonly config: Config; + + constructor(options: GitHubLocationAnalyzerOptions) { + this.config = options.config; + this.catalogClient = new CatalogClient({ discoveryApi: options.discovery }); + } + supports(url: string) { + const integrations = ScmIntegrations.fromConfig(this.config); + const integration = integrations.byUrl(url); + return integration?.type === 'github'; + } + async analyze({ url, catalogFilename }: AnalyzeOptions) { + const { owner, name: repo } = parseGitUrl(url); + + const catalogFile = catalogFilename || 'catalog-info.yaml'; + + const query = `filename:${catalogFile} repo:${owner}/${repo}`; + + const integration = ScmIntegrations.fromConfig(this.config).github.byUrl( + url, + ); + if (!integration) { + throw new Error('Make sure you have a GitHub integration configured'); + } + + const octokitClient = new Octokit({ + auth: integration.config.token, + baseUrl: integration.config.apiBaseUrl, + }); + + const searchResult = await octokitClient.search + .code({ q: query }) + .catch(e => { + throw new Error(`Couldn't search repository for metadata file, ${e}`); + }); + + const exists = searchResult.data.total_count > 0; + if (exists) { + const repoInformation = await octokitClient.repos + .get({ owner, repo }) + .catch(e => { + throw new Error(`Couldn't fetch repo data, ${e}`); + }); + const defaultBranch = repoInformation.data.default_branch; + + const result = await Promise.all( + searchResult.data.items + .map(i => `${trimEnd(url, '/')}/blob/${defaultBranch}/${i.path}`) + .map(async target => { + const addLocationResult = await this.catalogClient.addLocation({ + type: 'url', + target, + dryRun: true, + }); + return addLocationResult.entities.map(e => ({ + location: { type: 'url', target }, + isRegistered: !!addLocationResult.exists, + entity: e, + })); + }), + ); + + return { existing: result.flat() }; + } + return { existing: [] }; + } +} diff --git a/plugins/catalog-backend-module-github/src/index.ts b/plugins/catalog-backend-module-github/src/index.ts index d793d48f1e..3d7a7a2b4e 100644 --- a/plugins/catalog-backend-module-github/src/index.ts +++ b/plugins/catalog-backend-module-github/src/index.ts @@ -20,12 +20,13 @@ * @packageDocumentation */ +export { GitHubLocationAnalyzer } from './analyzers/GitHubLocationAnalyzer'; +export type { GitHubLocationAnalyzerOptions } from './analyzers/GitHubLocationAnalyzer'; +export type { GithubMultiOrgConfig } from './lib'; export { GithubDiscoveryProcessor } from './processors/GithubDiscoveryProcessor'; export { GithubMultiOrgReaderProcessor } from './processors/GithubMultiOrgReaderProcessor'; export { GithubOrgReaderProcessor } from './processors/GithubOrgReaderProcessor'; export { GitHubEntityProvider } from './providers/GitHubEntityProvider'; export { GitHubOrgEntityProvider } from './providers/GitHubOrgEntityProvider'; export type { GitHubOrgEntityProviderOptions } from './providers/GitHubOrgEntityProvider'; -export type { GithubMultiOrgConfig } from './lib'; -export { githubEntityProviderCatalogModule } from './module'; -export type { GithubEntityProviderCatalogModuleOptions } from './module'; +export { githubEntityProviderCatalogModule } from './service/GithubEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.test.ts b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.test.ts index 63fb77288b..b2078172e9 100644 --- a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.test.ts @@ -15,7 +15,11 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { TaskInvocationDefinition, TaskRunner } from '@backstage/backend-tasks'; +import { + PluginTaskScheduler, + TaskInvocationDefinition, + TaskRunner, +} from '@backstage/backend-tasks'; import { ConfigReader } from '@backstage/config'; import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; import { GitHubEntityProvider } from './GitHubEntityProvider'; @@ -381,132 +385,201 @@ describe('GitHubEntityProvider', () => { entities: expectedEntities, }); }); -}); -it('apply full update on scheduled execution with topic exclusion taking priority over topic inclusion', async () => { - const config = new ConfigReader({ - catalog: { - providers: { - github: { - myProvider: { - organization: 'test-org', - catalogPath: 'custom/path/catalog-custom.yaml', - filters: { - branch: 'main', - repository: 'test-.*', - topic: { - exclude: ['backstage-exclude'], - include: ['backstage-include'], + it('apply full update on scheduled execution with topic exclusion taking priority over topic inclusion', async () => { + const config = new ConfigReader({ + catalog: { + providers: { + github: { + myProvider: { + organization: 'test-org', + catalogPath: 'custom/path/catalog-custom.yaml', + filters: { + branch: 'main', + repository: 'test-.*', + topic: { + exclude: ['backstage-exclude'], + include: ['backstage-include'], + }, }, }, }, }, }, - }, + }); + const schedule = new PersistingTaskRunner(); + const entityProviderConnection: EntityProviderConnection = { + applyMutation: jest.fn(), + refresh: jest.fn(), + }; + + const provider = GitHubEntityProvider.fromConfig(config, { + logger, + schedule, + })[0]; + + const mockGetOrganizationRepositories = jest.spyOn( + helpers, + 'getOrganizationRepositories', + ); + + mockGetOrganizationRepositories.mockReturnValue( + Promise.resolve({ + repositories: [ + { + name: 'test-repo', + url: 'https://github.com/test-org/test-repo', + repositoryTopics: { + nodes: [ + { + topic: { name: 'backstage-include' }, + }, + ], + }, + isArchived: false, + defaultBranchRef: { + name: 'main', + }, + }, + { + name: 'test-repo-2', + url: 'https://github.com/test-org/test-repo-2', + repositoryTopics: { + nodes: [ + { + topic: { name: 'backstage-include' }, + }, + { + topic: { name: 'backstage-exclude' }, + }, + ], + }, + isArchived: false, + defaultBranchRef: { + name: 'main', + }, + }, + { + name: 'test-repo-3', + url: 'https://github.com/test-org/test-repo-3', + repositoryTopics: { + nodes: [ + { + topic: { name: 'backstage-exclude' }, + }, + ], + }, + isArchived: false, + defaultBranchRef: { + name: 'main', + }, + }, + ], + }), + ); + + await provider.connect(entityProviderConnection); + + const taskDef = schedule.getTasks()[0]; + expect(taskDef.id).toEqual('github-provider:myProvider:refresh'); + await (taskDef.fn as () => Promise)(); + + const url = `https://github.com/test-org/test-repo/blob/main/custom/path/catalog-custom.yaml`; + const expectedEntities = [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Location', + metadata: { + annotations: { + 'backstage.io/managed-by-location': `url:${url}`, + 'backstage.io/managed-by-origin-location': `url:${url}`, + }, + name: 'generated-5e4b9498097f15434e88c477cfba6c079aa8ca7f', + }, + spec: { + presence: 'optional', + target: `${url}`, + type: 'url', + }, + }, + locationKey: 'github-provider:myProvider', + }, + ]; + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: expectedEntities, + }); }); - const schedule = new PersistingTaskRunner(); - const entityProviderConnection: EntityProviderConnection = { - applyMutation: jest.fn(), - refresh: jest.fn(), - }; - const provider = GitHubEntityProvider.fromConfig(config, { - logger, - schedule, - })[0]; - - const mockGetOrganizationRepositories = jest.spyOn( - helpers, - 'getOrganizationRepositories', - ); - - mockGetOrganizationRepositories.mockReturnValue( - Promise.resolve({ - repositories: [ - { - name: 'test-repo', - url: 'https://github.com/test-org/test-repo', - repositoryTopics: { - nodes: [ - { - topic: { name: 'backstage-include' }, - }, - ], + it('fail without schedule and scheduler', () => { + const config = new ConfigReader({ + catalog: { + providers: { + github: { + organization: 'test-org', }, - isArchived: false, - defaultBranchRef: { - name: 'main', - }, - }, - { - name: 'test-repo-2', - url: 'https://github.com/test-org/test-repo-2', - repositoryTopics: { - nodes: [ - { - topic: { name: 'backstage-include' }, - }, - { - topic: { name: 'backstage-exclude' }, - }, - ], - }, - isArchived: false, - defaultBranchRef: { - name: 'main', - }, - }, - { - name: 'test-repo-3', - url: 'https://github.com/test-org/test-repo-3', - repositoryTopics: { - nodes: [ - { - topic: { name: 'backstage-exclude' }, - }, - ], - }, - isArchived: false, - defaultBranchRef: { - name: 'main', - }, - }, - ], - }), - ); - - await provider.connect(entityProviderConnection); - - const taskDef = schedule.getTasks()[0]; - expect(taskDef.id).toEqual('github-provider:myProvider:refresh'); - await (taskDef.fn as () => Promise)(); - - const url = `https://github.com/test-org/test-repo/blob/main/custom/path/catalog-custom.yaml`; - const expectedEntities = [ - { - entity: { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Location', - metadata: { - annotations: { - 'backstage.io/managed-by-location': `url:${url}`, - 'backstage.io/managed-by-origin-location': `url:${url}`, - }, - name: 'generated-5e4b9498097f15434e88c477cfba6c079aa8ca7f', - }, - spec: { - presence: 'optional', - target: `${url}`, - type: 'url', }, }, - locationKey: 'github-provider:myProvider', - }, - ]; + }); - expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); - expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ - type: 'full', - entities: expectedEntities, + expect(() => + GitHubEntityProvider.fromConfig(config, { + logger, + }), + ).toThrow('Either schedule or scheduler must be provided'); + }); + + it('fail with scheduler but no schedule config', () => { + const scheduler = { + createScheduledTaskRunner: (_: any) => jest.fn(), + } as unknown as PluginTaskScheduler; + const config = new ConfigReader({ + catalog: { + providers: { + github: { + organization: 'test-org', + }, + }, + }, + }); + + expect(() => + GitHubEntityProvider.fromConfig(config, { + logger, + scheduler, + }), + ).toThrow( + 'No schedule provided neither via code nor config for github-provider:default', + ); + }); + + it('single simple provider config with schedule in config', async () => { + const schedule = new PersistingTaskRunner(); + const scheduler = { + createScheduledTaskRunner: (_: any) => schedule, + } as unknown as PluginTaskScheduler; + const config = new ConfigReader({ + catalog: { + providers: { + github: { + organization: 'test-org', + schedule: { + frequency: 'P1M', + timeout: 'PT3M', + }, + }, + }, + }, + }); + const providers = GitHubEntityProvider.fromConfig(config, { + logger, + scheduler, + }); + + expect(providers).toHaveLength(1); + expect(providers[0].getProviderName()).toEqual('github-provider:default'); }); }); diff --git a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.ts index 3909b5a3c2..7d04b749dd 100644 --- a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { TaskRunner } from '@backstage/backend-tasks'; +import { PluginTaskScheduler, TaskRunner } from '@backstage/backend-tasks'; import { Config } from '@backstage/config'; import { GithubCredentialsProvider, @@ -60,9 +60,14 @@ export class GitHubEntityProvider implements EntityProvider { config: Config, options: { logger: Logger; - schedule: TaskRunner; + schedule?: TaskRunner; + scheduler?: PluginTaskScheduler; }, ): GitHubEntityProvider[] { + if (!options.schedule && !options.scheduler) { + throw new Error('Either schedule or scheduler must be provided.'); + } + const integrations = ScmIntegrations.fromConfig(config); return readProviderConfigs(config).map(providerConfig => { @@ -75,11 +80,21 @@ export class GitHubEntityProvider implements EntityProvider { ); } + if (!options.schedule && !providerConfig.schedule) { + throw new Error( + `No schedule provided neither via code nor config for github-provider:${providerConfig.id}.`, + ); + } + + const taskRunner = + options.schedule ?? + options.scheduler!.createScheduledTaskRunner(providerConfig.schedule!); + return new GitHubEntityProvider( providerConfig, integration, options.logger, - options.schedule, + taskRunner, ); }); } @@ -88,14 +103,14 @@ export class GitHubEntityProvider implements EntityProvider { config: GitHubEntityProviderConfig, integration: GitHubIntegration, logger: Logger, - schedule: TaskRunner, + taskRunner: TaskRunner, ) { this.config = config; this.integration = integration.config; this.logger = logger.child({ target: this.getProviderName(), }); - this.scheduleFn = this.createScheduleFn(schedule); + this.scheduleFn = this.createScheduleFn(taskRunner); this.githubCredentialsProvider = SingleInstanceGithubCredentialsProvider.create(integration.config); } @@ -111,10 +126,10 @@ export class GitHubEntityProvider implements EntityProvider { return await this.scheduleFn(); } - private createScheduleFn(schedule: TaskRunner): () => Promise { + private createScheduleFn(taskRunner: TaskRunner): () => Promise { return async () => { const taskId = `${this.getProviderName()}:refresh`; - return schedule.run({ + return taskRunner.run({ id: taskId, fn: async () => { const logger = this.logger.child({ diff --git a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProviderConfig.test.ts b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProviderConfig.test.ts index 66a5463bf5..e1b3a6cfbf 100644 --- a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProviderConfig.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProviderConfig.test.ts @@ -15,6 +15,7 @@ */ import { ConfigReader } from '@backstage/config'; +import { Duration } from 'luxon'; import { readProviderConfigs } from './GitHubEntityProviderConfig'; describe('readProviderConfigs', () => { @@ -81,13 +82,22 @@ describe('readProviderConfigs', () => { organization: 'test-org1', host: 'ghe.internal.com', }, + providerWithSchedule: { + organization: 'test-org1', + schedule: { + frequency: 'PT30M', + timeout: { + minutes: 3, + }, + }, + }, }, }, }, }); const providerConfigs = readProviderConfigs(config); - expect(providerConfigs).toHaveLength(6); + expect(providerConfigs).toHaveLength(7); expect(providerConfigs[0]).toEqual({ id: 'providerOrganizationOnly', organization: 'test-org1', @@ -101,6 +111,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, }, + schedule: undefined, }); expect(providerConfigs[1]).toEqual({ id: 'providerCustomCatalogPath', @@ -115,6 +126,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, }, + schedule: undefined, }); expect(providerConfigs[2]).toEqual({ id: 'providerWithRepositoryFilter', @@ -129,6 +141,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, }, + schedule: undefined, }); expect(providerConfigs[3]).toEqual({ id: 'providerWithBranchFilter', @@ -143,6 +156,7 @@ describe('readProviderConfigs', () => { exclude: undefined, }, }, + schedule: undefined, }); expect(providerConfigs[4]).toEqual({ id: 'providerWithTopicFilter', @@ -157,6 +171,7 @@ describe('readProviderConfigs', () => { exclude: ['backstage-exclude'], }, }, + schedule: undefined, }); expect(providerConfigs[5]).toEqual({ id: 'providerWithHost', @@ -171,6 +186,27 @@ describe('readProviderConfigs', () => { exclude: undefined, }, }, + schedule: undefined, + }); + expect(providerConfigs[6]).toEqual({ + id: 'providerWithSchedule', + organization: 'test-org1', + catalogPath: '/catalog-info.yaml', + host: 'github.com', + filters: { + repository: undefined, + branch: undefined, + topic: { + include: undefined, + exclude: undefined, + }, + }, + schedule: { + frequency: Duration.fromISO('PT30M'), + timeout: { + minutes: 3, + }, + }, }); }); }); diff --git a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProviderConfig.ts b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProviderConfig.ts index d40b206751..6785d18984 100644 --- a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProviderConfig.ts +++ b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProviderConfig.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import { + readTaskScheduleDefinitionFromConfig, + TaskScheduleDefinition, +} from '@backstage/backend-tasks'; import { Config } from '@backstage/config'; const DEFAULT_CATALOG_PATH = '/catalog-info.yaml'; @@ -29,6 +33,7 @@ export type GitHubEntityProviderConfig = { branch?: string; topic?: GithubTopicFilters; }; + schedule?: TaskScheduleDefinition; }; export type GithubTopicFilters = { @@ -73,6 +78,10 @@ function readProviderConfig( 'filters.topic.exclude', ); + const schedule = config.has('schedule') + ? readTaskScheduleDefinitionFromConfig(config.getConfig('schedule')) + : undefined; + return { id, catalogPath, @@ -88,8 +97,10 @@ function readProviderConfig( exclude: topicFilterExclude, }, }, + schedule, }; } + /** * Compiles a RegExp while enforcing the pattern to contain * the start-of-line and end-of-line anchors. diff --git a/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.test.ts new file mode 100644 index 0000000000..d65eb98661 --- /dev/null +++ b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.test.ts @@ -0,0 +1,84 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getVoidLogger } from '@backstage/backend-common'; +import { + configServiceRef, + loggerServiceRef, + schedulerServiceRef, +} from '@backstage/backend-plugin-api'; +import { + PluginTaskScheduler, + TaskScheduleDefinition, +} from '@backstage/backend-tasks'; +import { startTestBackend } from '@backstage/backend-test-utils'; +import { ConfigReader } from '@backstage/config'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { Duration } from 'luxon'; +import { githubEntityProviderCatalogModule } from './GithubEntityProviderCatalogModule'; +import { GitHubEntityProvider } from '../providers/GitHubEntityProvider'; + +describe('githubEntityProviderCatalogModule', () => { + it('should register provider at the catalog extension point', async () => { + let addedProviders: Array | undefined; + let usedSchedule: TaskScheduleDefinition | undefined; + + const extensionPoint = { + addEntityProvider: (providers: any) => { + addedProviders = providers; + }, + }; + const runner = jest.fn(); + const scheduler = { + createScheduledTaskRunner: (schedule: TaskScheduleDefinition) => { + usedSchedule = schedule; + return runner; + }, + } as unknown as PluginTaskScheduler; + + const config = new ConfigReader({ + catalog: { + providers: { + github: { + organization: 'module-test', + schedule: { + frequency: 'P1M', + timeout: 'PT3M', + }, + }, + }, + }, + }); + + await startTestBackend({ + extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], + services: [ + [configServiceRef, config], + [loggerServiceRef, getVoidLogger()], + [schedulerServiceRef, scheduler], + ], + features: [githubEntityProviderCatalogModule()], + }); + + expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M')); + expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M')); + expect(addedProviders?.length).toEqual(1); + expect(addedProviders?.pop()?.getProviderName()).toEqual( + 'github-provider:default', + ); + expect(runner).not.toHaveBeenCalled(); + }); +}); diff --git a/plugins/catalog-backend-module-github/src/module.ts b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts similarity index 67% rename from plugins/catalog-backend-module-github/src/module.ts rename to plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts index 0391855618..c63e8ba7da 100644 --- a/plugins/catalog-backend-module-github/src/module.ts +++ b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts @@ -21,18 +21,8 @@ import { loggerServiceRef, schedulerServiceRef, } from '@backstage/backend-plugin-api'; -import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; -import { GitHubEntityProvider } from './providers/GitHubEntityProvider'; - -/** - * Options for {@link githubEntityProviderCatalogModule}. - * - * @alpha - */ -export type GithubEntityProviderCatalogModuleOptions = { - schedule?: TaskScheduleDefinition; -}; +import { GitHubEntityProvider } from '../providers/GitHubEntityProvider'; /** * Registers the GitHubEntityProvider with the catalog processing extension point. @@ -42,25 +32,19 @@ export type GithubEntityProviderCatalogModuleOptions = { export const githubEntityProviderCatalogModule = createBackendModule({ pluginId: 'catalog', moduleId: 'githubEntityProvider', - register(env, options?: GithubEntityProviderCatalogModuleOptions) { + register(env) { env.registerInit({ deps: { - config: configServiceRef, catalog: catalogProcessingExtensionPoint, + config: configServiceRef, logger: loggerServiceRef, scheduler: schedulerServiceRef, }, - async init({ config, catalog, logger, scheduler }) { - const scheduleDef = options?.schedule ?? { - frequency: { seconds: 600 }, - timeout: { seconds: 900 }, - initialDelay: { seconds: 3 }, - }; - + async init({ catalog, config, logger, scheduler }) { catalog.addEntityProvider( GitHubEntityProvider.fromConfig(config, { logger: loggerToWinstonLogger(logger), - schedule: scheduler.createScheduledTaskRunner(scheduleDef), + scheduler, }), ); }, diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index add7b604d3..aa3d389714 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + ## 0.1.8-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 510a4eb3be..60c16737c7 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.1.8-next.1", + "version": "0.1.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 305eed8686..b1a789fb17 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/types@1.0.0 + ## 0.5.4-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index eaa3929ade..b0587a0d7d 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend module that helps integrate towards LDAP", - "version": "0.5.4-next.1", + "version": "0.5.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 2da4607869..c90df48b93 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-tasks@0.3.6-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index d3ac35f743..9532cbff7a 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", - "version": "0.4.3-next.1", + "version": "0.4.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index d098727b3e..981f652bd0 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.2.0-next.2 + - @backstage/plugin-catalog-backend@1.5.0-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + ## 0.1.3-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index dded553b09..8465e232d0 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.1.3-next.1", + "version": "0.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index d3b24efb6f..4182d0acb3 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-catalog-backend +## 1.5.0-next.2 + +### Minor Changes + +- b2e6cb6acf: Added a new method `addLocationAnalyzers` to the `CatalogBuilder`. With this you can add location analyzers to your catalog. These analyzers will be used by the /analyze-location endpoint to decide if the provided URL contains any catalog-info.yaml files already or not. + + Moved the following types from this package to `@backstage/plugin-catalog-backend`. + + - AnalyzeLocationResponse + - AnalyzeLocationRequest + - AnalyzeLocationExistingEntity + - AnalyzeLocationGenerateEntity + - AnalyzeLocationEntityField + +- eb25f7e12d: The exported permission rules and the API of `createCatalogConditionalDecision` have changed to reflect the breaking changes made to the `PermissionRule` type. Note that all involved types are exported from `@backstage/plugin-catalog-backend/alpha` + +### Patch Changes + +- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` +- Updated dependencies + - @backstage/plugin-catalog-node@1.2.0-next.2 + - @backstage/plugin-catalog-common@1.0.7-next.2 + - @backstage/backend-common@0.15.2-next.2 + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-permission-node@0.7.0-next.2 + - @backstage/backend-plugin-api@0.1.3-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/config@1.0.3-next.2 + - @backstage/errors@1.1.2-next.2 + - @backstage/integration@1.3.2-next.2 + - @backstage/types@1.0.0 + - @backstage/plugin-scaffolder-common@1.2.1-next.2 + ## 1.4.1-next.1 ### Patch Changes diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index f18d396114..10b9afc291 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -5,6 +5,11 @@ ```ts /// +import { AnalyzeLocationEntityField as AnalyzeLocationEntityField_2 } from '@backstage/plugin-catalog-common'; +import { AnalyzeLocationExistingEntity as AnalyzeLocationExistingEntity_2 } from '@backstage/plugin-catalog-common'; +import { AnalyzeLocationGenerateEntity as AnalyzeLocationGenerateEntity_2 } from '@backstage/plugin-catalog-common'; +import { AnalyzeLocationRequest as AnalyzeLocationRequest_2 } from '@backstage/plugin-catalog-common'; +import { AnalyzeLocationResponse as AnalyzeLocationResponse_2 } from '@backstage/plugin-catalog-common'; import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; @@ -40,6 +45,7 @@ import { PermissionCondition } from '@backstage/plugin-permission-common'; import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { processingResult } from '@backstage/plugin-catalog-node'; @@ -51,39 +57,25 @@ import { TokenManager } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Validators } from '@backstage/catalog-model'; -// @public (undocumented) -export type AnalyzeLocationEntityField = { - field: string; - state: - | 'analysisSuggestedValue' - | 'analysisSuggestedNoValue' - | 'needsUserInput'; - value: string | null; - description: string; -}; +// @public @deprecated +export type AnalyzeLocationEntityField = AnalyzeLocationEntityField_2; -// @public -export type AnalyzeLocationExistingEntity = { - location: LocationSpec; - isRegistered: boolean; - entity: Entity; -}; +// @public @deprecated +export type AnalyzeLocationExistingEntity = AnalyzeLocationExistingEntity_2; -// @public -export type AnalyzeLocationGenerateEntity = { - entity: RecursivePartial; - fields: AnalyzeLocationEntityField[]; -}; +// @public @deprecated +export type AnalyzeLocationGenerateEntity = AnalyzeLocationGenerateEntity_2; + +// @public @deprecated (undocumented) +export type AnalyzeLocationRequest = AnalyzeLocationRequest_2; + +// @public @deprecated (undocumented) +export type AnalyzeLocationResponse = AnalyzeLocationResponse_2; // @public (undocumented) -export type AnalyzeLocationRequest = { - location: LocationSpec; -}; - -// @public (undocumented) -export type AnalyzeLocationResponse = { - existingEntityFiles: AnalyzeLocationExistingEntity[]; - generateEntities: AnalyzeLocationGenerateEntity[]; +export type AnalyzeOptions = { + url: string; + catalogFilename?: string; }; // @public (undocumented) @@ -133,6 +125,9 @@ export class CatalogBuilder { addEntityProvider( ...providers: Array> ): CatalogBuilder; + addLocationAnalyzers( + ...analyzers: Array> + ): CatalogBuilder; // @alpha addPermissionRules( ...permissionRules: Array< @@ -177,37 +172,52 @@ export const catalogConditions: Conditions<{ Entity, EntitiesSearchFilter, 'catalog-entity', - [annotation: string, value?: string | undefined] + { + value?: string | undefined; + annotation: string; + } >; hasLabel: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [label: string] + { + label: string; + } >; hasMetadata: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [key: string, value?: string | undefined] + { + value?: string | undefined; + key: string; + } >; hasSpec: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [key: string, value?: string | undefined] + { + value?: string | undefined; + key: string; + } >; isEntityKind: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [kinds: string[]] + { + kinds: string[]; + } >; isEntityOwner: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [claims: string[]] + { + claims: string[]; + } >; }>; @@ -221,8 +231,9 @@ export type CatalogEnvironment = { }; // @alpha -export type CatalogPermissionRule = - PermissionRule; +export type CatalogPermissionRule< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule; // @alpha export const catalogPlugin: (options?: undefined) => BackendFeature; @@ -280,12 +291,14 @@ export class CodeOwnersProcessor implements CatalogProcessor { export const createCatalogConditionalDecision: ( permission: ResourcePermission<'catalog-entity'>, conditions: PermissionCriteria< - PermissionCondition<'catalog-entity', unknown[]> + PermissionCondition<'catalog-entity', PermissionRuleParams> >, ) => ConditionalPolicyDecision; // @alpha -export const createCatalogPermissionRule: ( +export const createCatalogPermissionRule: < + TParams extends PermissionRuleParams = undefined, +>( rule: PermissionRule, ) => PermissionRule; @@ -448,37 +461,52 @@ export const permissionRules: { Entity, EntitiesSearchFilter, 'catalog-entity', - [annotation: string, value?: string | undefined] + { + value?: string | undefined; + annotation: string; + } >; hasLabel: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [label: string] + { + label: string; + } >; hasMetadata: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [key: string, value?: string | undefined] + { + value?: string | undefined; + key: string; + } >; hasSpec: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [key: string, value?: string | undefined] + { + value?: string | undefined; + key: string; + } >; isEntityKind: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [kinds: string[]] + { + kinds: string[]; + } >; isEntityOwner: PermissionRule< Entity, EntitiesSearchFilter, 'catalog-entity', - [claims: string[]] + { + claims: string[]; + } >; }; @@ -531,6 +559,14 @@ export type ProcessingIntervalFunction = () => number; export { processingResult }; +// @public (undocumented) +export type ScmLocationAnalyzer = { + supports(url: string): boolean; + analyze(options: AnalyzeOptions): Promise<{ + existing: AnalyzeLocationExistingEntity[]; + }>; +}; + // @public (undocumented) export class UrlReaderProcessor implements CatalogProcessor { constructor(options: { reader: UrlReader; logger: Logger }); diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 4d127a4d43..8ace08abcf 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "1.4.1-next.1", + "version": "1.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts index b84dff7de8..761a0f8c0a 100644 --- a/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts +++ b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts @@ -18,34 +18,32 @@ import { Logger } from 'winston'; import parseGitUrl from 'git-url-parse'; import { Entity } from '@backstage/catalog-model'; import { ScmIntegrationRegistry } from '@backstage/integration'; +import { LocationAnalyzer, ScmLocationAnalyzer } from './types'; import { AnalyzeLocationRequest, AnalyzeLocationResponse, - LocationAnalyzer, -} from './types'; +} from '@backstage/plugin-catalog-common'; export class RepoLocationAnalyzer implements LocationAnalyzer { private readonly logger: Logger; private readonly scmIntegrations: ScmIntegrationRegistry; + private readonly analyzers: ScmLocationAnalyzer[]; - constructor(logger: Logger, scmIntegrations: ScmIntegrationRegistry) { + constructor( + logger: Logger, + scmIntegrations: ScmIntegrationRegistry, + analyzers: ScmLocationAnalyzer[], + ) { this.logger = logger; this.scmIntegrations = scmIntegrations; + this.analyzers = analyzers; } async analyzeLocation( request: AnalyzeLocationRequest, ): Promise { - const { owner, name } = parseGitUrl(request.location.target); - const entity: Entity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: name, - }, - spec: { type: 'other', lifecycle: 'unknown' }, - }; - const integration = this.scmIntegrations.byUrl(request.location.target); + const { owner, name } = parseGitUrl(request.location.target); + let annotationPrefix; switch (integration?.type) { case 'azure': @@ -64,6 +62,33 @@ export class RepoLocationAnalyzer implements LocationAnalyzer { break; } + const analyzer = this.analyzers.find(a => + a.supports(request.location.target), + ); + if (analyzer) { + const analyzerResult = await analyzer.analyze({ + url: request.location.target, + }); + if (analyzerResult.existing.length > 0) { + this.logger.debug( + `entity for ${request.location.target} already exists.`, + ); + return { + existingEntityFiles: analyzerResult.existing, + generateEntities: [], + }; + } + } + + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: name, + }, + spec: { type: 'other', lifecycle: 'unknown' }, + }; + if (annotationPrefix) { entity.metadata.annotations = { [`${annotationPrefix}/project-slug`]: `${owner}/${name}`, diff --git a/plugins/catalog-backend/src/ingestion/index.ts b/plugins/catalog-backend/src/ingestion/index.ts index c97d029b5c..0b00809043 100644 --- a/plugins/catalog-backend/src/ingestion/index.ts +++ b/plugins/catalog-backend/src/ingestion/index.ts @@ -21,4 +21,6 @@ export type { AnalyzeLocationRequest, AnalyzeLocationResponse, LocationAnalyzer, + ScmLocationAnalyzer, + AnalyzeOptions, } from './types'; diff --git a/plugins/catalog-backend/src/ingestion/types.ts b/plugins/catalog-backend/src/ingestion/types.ts index 2602bd080f..78339b3b23 100644 --- a/plugins/catalog-backend/src/ingestion/types.ts +++ b/plugins/catalog-backend/src/ingestion/types.ts @@ -14,9 +14,57 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; -import { RecursivePartial } from '../util/RecursivePartial'; -import { LocationSpec } from '@backstage/plugin-catalog-node'; +import { + AnalyzeLocationRequest as NonDeprecatedAnalyzeLocationRequest, + AnalyzeLocationResponse as NonDeprecatedAnalyzeLocationResponse, + AnalyzeLocationExistingEntity as NonDeprecatedAnalyzeLocationExistingEntity, + AnalyzeLocationGenerateEntity as NonDeprecatedAnalyzeLocationGenerateEntity, + AnalyzeLocationEntityField as NonDeprecatedAnalyzeLocationEntityField, +} from '@backstage/plugin-catalog-common'; + +/** + * @public + * @deprecated use the same type from `@backstage/plugin-catalog-common` instead + */ +export type AnalyzeLocationRequest = NonDeprecatedAnalyzeLocationRequest; +/** + * @public + * @deprecated use the same type from `@backstage/plugin-catalog-common` instead + */ +export type AnalyzeLocationResponse = NonDeprecatedAnalyzeLocationResponse; + +/** + * If the folder pointed to already contained catalog info yaml files, they are + * read and emitted like this so that the frontend can inform the user that it + * located them and can make sure to register them as well if they weren't + * already + * @public + * @deprecated use the same type from `@backstage/plugin-catalog-common` instead + */ +export type AnalyzeLocationExistingEntity = + NonDeprecatedAnalyzeLocationExistingEntity; +/** + * This is some form of representation of what the analyzer could deduce. + * We should probably have a chat about how this can best be conveyed to + * the frontend. It'll probably contain a (possibly incomplete) entity, plus + * enough info for the frontend to know what form data to show to the user + * for overriding/completing the info. + * @public + * @deprecated use the same type from `@backstage/plugin-catalog-common` instead + */ +export type AnalyzeLocationGenerateEntity = + NonDeprecatedAnalyzeLocationGenerateEntity; + +/** + * + * This is where I get really vague. Something like this perhaps? Or it could be + * something like a json-schema that contains enough info for the frontend to + * be able to present a form and explanations + * @public + * @deprecated use the same type from `@backstage/plugin-catalog-common` instead + */ +export type AnalyzeLocationEntityField = + NonDeprecatedAnalyzeLocationEntityField; /** @public */ export type LocationAnalyzer = { @@ -30,71 +78,19 @@ export type LocationAnalyzer = { location: AnalyzeLocationRequest, ): Promise; }; - /** @public */ -export type AnalyzeLocationRequest = { - location: LocationSpec; +export type AnalyzeOptions = { + url: string; + catalogFilename?: string; }; /** @public */ -export type AnalyzeLocationResponse = { - existingEntityFiles: AnalyzeLocationExistingEntity[]; - generateEntities: AnalyzeLocationGenerateEntity[]; -}; - -/** - * If the folder pointed to already contained catalog info yaml files, they are - * read and emitted like this so that the frontend can inform the user that it - * located them and can make sure to register them as well if they weren't - * already - * @public - */ -export type AnalyzeLocationExistingEntity = { - location: LocationSpec; - isRegistered: boolean; - entity: Entity; -}; - -/** - * This is some form of representation of what the analyzer could deduce. - * We should probably have a chat about how this can best be conveyed to - * the frontend. It'll probably contain a (possibly incomplete) entity, plus - * enough info for the frontend to know what form data to show to the user - * for overriding/completing the info. - * @public - */ -export type AnalyzeLocationGenerateEntity = { - // Some form of partial representation of the entity - entity: RecursivePartial; - // Lists the suggestions that the user may want to override - fields: AnalyzeLocationEntityField[]; -}; - -// This is where I get really vague. Something like this perhaps? Or it could be -// something like a json-schema that contains enough info for the frontend to -// be able to present a form and explanations -/** @public */ -export type AnalyzeLocationEntityField = { - /** - * e.g. "spec.owner"? The frontend needs to know how to "inject" the field into the - * entity again if the user wants to change it - */ - field: string; - - /** The outcome of the analysis for this particular field */ - state: - | 'analysisSuggestedValue' - | 'analysisSuggestedNoValue' - | 'needsUserInput'; - - // If the analysis did suggest a value, this is where it would be. Not sure if we want - // to limit this to strings or if we want it to be any JsonValue - value: string | null; - /** - * A text to show to the user to inform about the choices made. Like, it could say - * "Found a CODEOWNERS file that covers this target, so we suggest leaving this - * field empty; which would currently make it owned by X" where X is taken from the - * codeowners file. - */ - description: string; +export type ScmLocationAnalyzer = { + /** The method that decides if this analyzer can work with the provided url */ + supports(url: string): boolean; + /** This function can return an array of already existing entities */ + analyze(options: AnalyzeOptions): Promise<{ + /** Existing entities in the analyzed location */ + existing: AnalyzeLocationExistingEntity[]; + }>; }; diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts index cb11add9ed..5b34c98ca6 100644 --- a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts +++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts @@ -41,7 +41,9 @@ describe('createPropertyRule', () => { name: 'test-component', }, }, - 'org.name', + { + key: 'org.name', + }, ), ).toBe(false); }); @@ -57,7 +59,9 @@ describe('createPropertyRule', () => { tags: [], }, }, - 'tags', + { + key: 'tags', + }, ), ).toBe(false); }); @@ -75,7 +79,9 @@ describe('createPropertyRule', () => { }, }, }, - 'org.name', + { + key: 'org.name', + }, ), ).toBe(true); }); @@ -91,7 +97,9 @@ describe('createPropertyRule', () => { tags: ['java'], }, }, - 'tags', + { + key: 'tags', + }, ), ).toBe(true); }); @@ -108,8 +116,10 @@ describe('createPropertyRule', () => { name: 'test-component', }, }, - 'org.name', - 'test-org', + { + key: 'org.name', + value: 'test-org', + }, ), ).toBe(false); }); @@ -127,8 +137,10 @@ describe('createPropertyRule', () => { }, }, }, - 'org.name', - 'test-org', + { + key: 'org.name', + value: 'test-org', + }, ), ).toBe(false); }); @@ -144,8 +156,10 @@ describe('createPropertyRule', () => { tags: ['java'], }, }, - 'tags', - 'python', + { + key: 'tags', + value: 'python', + }, ), ).toBe(false); }); @@ -163,8 +177,10 @@ describe('createPropertyRule', () => { }, }, }, - 'org.name', - 'test-org', + { + key: 'org.name', + value: 'test-org', + }, ), ).toBe(true); }); @@ -180,8 +196,10 @@ describe('createPropertyRule', () => { tags: ['java', 'java11'], }, }, - 'tags', - 'java', + { + key: 'tags', + value: 'java', + }, ), ).toBe(true); }); @@ -190,7 +208,11 @@ describe('createPropertyRule', () => { describe('toQuery', () => { it('returns an appropriate catalog-backend filter', () => { - expect(toQuery('backstage.io/test-component')).toEqual({ + expect( + toQuery({ + key: 'backstage.io/test-component', + }), + ).toEqual({ key: 'metadata.backstage.io/test-component', }); }); diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts index 57de5eb922..19a4423846 100644 --- a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts +++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts @@ -15,16 +15,25 @@ */ import { get } from 'lodash'; -import { Entity } from '@backstage/catalog-model'; import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; import { createCatalogPermissionRule } from './util'; +import { z } from 'zod'; export const createPropertyRule = (propertyType: 'metadata' | 'spec') => createCatalogPermissionRule({ name: `HAS_${propertyType.toUpperCase()}`, description: `Allow entities which have the specified ${propertyType} subfield.`, resourceType: RESOURCE_TYPE_CATALOG_ENTITY, - apply: (resource: Entity, key: string, value?: string) => { + paramsSchema: z.object({ + key: z + .string() + .describe(`Property within the entities ${propertyType} to match on`), + value: z + .string() + .optional() + .describe(`Value of the given property to match on`), + }), + apply: (resource, { key, value }) => { const foundValue = get(resource[propertyType], key); if (Array.isArray(foundValue)) { @@ -38,7 +47,7 @@ export const createPropertyRule = (propertyType: 'metadata' | 'spec') => } return !!foundValue; }, - toQuery: (key: string, value?: string) => ({ + toQuery: ({ key, value }) => ({ key: `${propertyType}.${key}`, ...(value !== undefined && { values: [value] }), }), diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts index 609114be3d..73fce20a71 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts @@ -31,7 +31,9 @@ describe('hasAnnotation permission rule', () => { }, }, }, - 'backstage.io/test-annotation', + { + annotation: 'backstage.io/test-annotation', + }, ), ).toEqual(false); }); @@ -46,7 +48,9 @@ describe('hasAnnotation permission rule', () => { name: 'test-component', }, }, - 'backstage.io/test-annotation', + { + annotation: 'backstage.io/test-annotation', + }, ), ).toEqual(false); expect( @@ -58,8 +62,10 @@ describe('hasAnnotation permission rule', () => { name: 'test-component', }, }, - 'backstage.io/test-annotation', - 'some value', + { + annotation: 'backstage.io/test-annotation', + value: 'some value', + }, ), ).toEqual(false); }); @@ -78,7 +84,9 @@ describe('hasAnnotation permission rule', () => { }, }, }, - 'backstage.io/test-annotation', + { + annotation: 'backstage.io/test-annotation', + }, ), ).toEqual(true); }); @@ -97,8 +105,10 @@ describe('hasAnnotation permission rule', () => { }, }, }, - 'backstage.io/test-annotation', - 'baz', + { + annotation: 'backstage.io/test-annotation', + value: 'baz', + }, ), ).toEqual(false); }); @@ -117,8 +127,10 @@ describe('hasAnnotation permission rule', () => { }, }, }, - 'backstage.io/test-annotation', - 'bar', + { + annotation: 'backstage.io/test-annotation', + value: 'bar', + }, ), ).toEqual(true); }); @@ -126,7 +138,11 @@ describe('hasAnnotation permission rule', () => { describe('toQuery', () => { it('returns an appropriate catalog-backend filter', () => { - expect(hasAnnotation.toQuery('backstage.io/test-annotation')).toEqual({ + expect( + hasAnnotation.toQuery({ + annotation: 'backstage.io/test-annotation', + }), + ).toEqual({ key: 'metadata.annotations.backstage.io/test-annotation', }); }); @@ -134,7 +150,10 @@ describe('hasAnnotation permission rule', () => { it('returns an appropriate catalog-backend filter with values', () => { expect( - hasAnnotation.toQuery('backstage.io/test-annotation', 'foo'), + hasAnnotation.toQuery({ + annotation: 'backstage.io/test-annotation', + value: 'foo', + }), ).toEqual({ key: 'metadata.annotations.backstage.io/test-annotation', values: ['foo'], diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts index 22dbd307a6..c24620f41c 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { z } from 'zod'; import { createCatalogPermissionRule } from './util'; /** @@ -31,12 +31,19 @@ export const hasAnnotation = createCatalogPermissionRule({ description: 'Allow entities which are annotated with the specified annotation', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, - apply: (resource: Entity, annotation: string, value?: string) => + paramsSchema: z.object({ + annotation: z.string().describe('Name of the annotation to match on'), + value: z + .string() + .optional() + .describe('Value of the annotation to match on'), + }), + apply: (resource, { annotation, value }) => !!resource.metadata.annotations?.hasOwnProperty(annotation) && (value === undefined ? true : resource.metadata.annotations?.[annotation] === value), - toQuery: (annotation: string, value?: string) => + toQuery: ({ annotation, value }) => value === undefined ? { key: `metadata.annotations.${annotation}`, diff --git a/plugins/catalog-backend/src/permissions/rules/hasLabel.test.ts b/plugins/catalog-backend/src/permissions/rules/hasLabel.test.ts index a1b9cb5ad0..8aa43402c5 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasLabel.test.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasLabel.test.ts @@ -31,7 +31,9 @@ describe('hasLabel permission rule', () => { }, }, }, - 'backstage.io/testlabel', + { + label: 'backstage.io/testlabel', + }, ), ).toEqual(false); }); @@ -46,7 +48,9 @@ describe('hasLabel permission rule', () => { name: 'test-component', }, }, - 'backstage.io/testlabel', + { + label: 'backstage.io/testlabel', + }, ), ).toEqual(false); }); @@ -65,7 +69,7 @@ describe('hasLabel permission rule', () => { }, }, }, - 'backstage.io/testlabel', + { label: 'backstage.io/testlabel' }, ), ).toEqual(true); }); @@ -73,7 +77,11 @@ describe('hasLabel permission rule', () => { describe('toQuery', () => { it('returns an appropriate catalog-backend filter', () => { - expect(hasLabel.toQuery('backstage.io/testlabel')).toEqual({ + expect( + hasLabel.toQuery({ + label: 'backstage.io/testlabel', + }), + ).toEqual({ key: 'metadata.labels.backstage.io/testlabel', }); }); diff --git a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts index 9f37cbfb59..376534ca6f 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { z } from 'zod'; import { createCatalogPermissionRule } from './util'; /** @@ -27,9 +27,12 @@ export const hasLabel = createCatalogPermissionRule({ name: 'HAS_LABEL', description: 'Allow entities which have the specified label metadata.', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, - apply: (resource: Entity, label: string) => + paramsSchema: z.object({ + label: z.string().describe('Name of the label to match one'), + }), + apply: (resource, { label }) => !!resource.metadata.labels?.hasOwnProperty(label), - toQuery: (label: string) => ({ + toQuery: ({ label }) => ({ key: `metadata.labels.${label}`, }), }); diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityKind.test.ts b/plugins/catalog-backend/src/permissions/rules/isEntityKind.test.ts index e11e102728..28983f6bec 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityKind.test.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityKind.test.ts @@ -27,7 +27,11 @@ describe('isEntityKind', () => { name: 'some-component', }, }; - expect(isEntityKind.apply(component, ['b'])).toBe(true); + expect( + isEntityKind.apply(component, { + kinds: ['b'], + }), + ).toBe(true); }); it('returns false when entity is not the correct kind', () => { @@ -38,13 +42,21 @@ describe('isEntityKind', () => { name: 'some-component', }, }; - expect(isEntityKind.apply(component, ['c'])).toBe(false); + expect( + isEntityKind.apply(component, { + kinds: ['c'], + }), + ).toBe(false); }); }); describe('toQuery', () => { it('returns an appropriate catalog-backend filter', () => { - expect(isEntityKind.toQuery(['b'])).toEqual({ + expect( + isEntityKind.toQuery({ + kinds: ['b'], + }), + ).toEqual({ key: 'kind', values: ['b'], }); diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts index 3bd600e8fe..eee7a790b2 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { z } from 'zod'; import { EntitiesSearchFilter } from '../../catalog/types'; import { createCatalogPermissionRule } from './util'; @@ -27,11 +27,16 @@ export const isEntityKind = createCatalogPermissionRule({ name: 'IS_ENTITY_KIND', description: 'Allow entities with the specified kind', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, - apply(resource: Entity, kinds: string[]) { + paramsSchema: z.object({ + kinds: z + .array(z.string()) + .describe('List of kinds to match at least one of'), + }), + apply(resource, { kinds }) { const resourceKind = resource.kind.toLocaleLowerCase('en-US'); return kinds.some(kind => kind.toLocaleLowerCase('en-US') === resourceKind); }, - toQuery(kinds: string[]): EntitiesSearchFilter { + toQuery({ kinds }): EntitiesSearchFilter { return { key: 'kind', values: kinds.map(kind => kind.toLocaleLowerCase('en-US')), diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts index 11304c768c..f09e484c32 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts @@ -33,9 +33,11 @@ describe('isEntityOwner', () => { }, ], }; - expect(isEntityOwner.apply(component, ['user:default/spiderman'])).toBe( - true, - ); + expect( + isEntityOwner.apply(component, { + claims: ['user:default/spiderman'], + }), + ).toBe(true); }); it('returns false when entity is not owned by the given user', () => { @@ -52,9 +54,11 @@ describe('isEntityOwner', () => { }, ], }; - expect(isEntityOwner.apply(component, ['user:default/spiderman'])).toBe( - false, - ); + expect( + isEntityOwner.apply(component, { + claims: ['user:default/spiderman'], + }), + ).toBe(false); }); it('returns false when entity does not have an owner', () => { @@ -65,15 +69,21 @@ describe('isEntityOwner', () => { name: 'some-component', }, }; - expect(isEntityOwner.apply(component, ['user:default/spiderman'])).toBe( - false, - ); + expect( + isEntityOwner.apply(component, { + claims: ['user:default/spiderman'], + }), + ).toBe(false); }); }); describe('toQuery', () => { it('returns an appropriate catalog-backend filter', () => { - expect(isEntityOwner.toQuery(['user:default/spiderman'])).toEqual({ + expect( + isEntityOwner.toQuery({ + claims: ['user:default/spiderman'], + }), + ).toEqual({ key: 'relations.ownedBy', values: ['user:default/spiderman'], }); diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts index 5403da2310..c3bfff5c2e 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { RELATION_OWNED_BY } from '@backstage/catalog-model'; import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { z } from 'zod'; import { createCatalogPermissionRule } from './util'; /** @@ -28,7 +29,14 @@ export const isEntityOwner = createCatalogPermissionRule({ name: 'IS_ENTITY_OWNER', description: 'Allow entities owned by the current user', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, - apply: (resource: Entity, claims: string[]) => { + paramsSchema: z.object({ + claims: z + .array(z.string()) + .describe( + `List of claims to match at least one on within ${RELATION_OWNED_BY}`, + ), + }), + apply: (resource, { claims }) => { if (!resource.relations) { return false; } @@ -37,7 +45,7 @@ export const isEntityOwner = createCatalogPermissionRule({ .filter(relation => relation.type === RELATION_OWNED_BY) .some(relation => claims.includes(relation.targetRef)); }, - toQuery: (claims: string[]) => ({ + toQuery: ({ claims }) => ({ key: 'relations.ownedBy', values: claims, }), diff --git a/plugins/catalog-backend/src/permissions/rules/util.ts b/plugins/catalog-backend/src/permissions/rules/util.ts index 36b351595d..ea25e115d2 100644 --- a/plugins/catalog-backend/src/permissions/rules/util.ts +++ b/plugins/catalog-backend/src/permissions/rules/util.ts @@ -16,6 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { makeCreatePermissionRule, PermissionRule, @@ -29,8 +30,9 @@ import { EntitiesSearchFilter } from '../../catalog/types'; * * @alpha */ -export type CatalogPermissionRule = - PermissionRule; +export type CatalogPermissionRule< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule; /** * Helper function for creating correctly-typed diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts index b15d1df4bb..66764dc89f 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts @@ -65,7 +65,7 @@ describe('AuthorizedEntitiesCatalog', () => { fakePermissionApi.authorizeConditional.mockResolvedValue([ { result: AuthorizeResult.CONDITIONAL, - conditions: { rule: 'IS_ENTITY_KIND', params: [['b']] }, + conditions: { rule: 'IS_ENTITY_KIND', params: { kinds: ['b'] } }, }, ]); const catalog = createCatalog(isEntityKind); @@ -117,7 +117,7 @@ describe('AuthorizedEntitiesCatalog', () => { fakePermissionApi.authorizeConditional.mockResolvedValue([ { result: AuthorizeResult.CONDITIONAL, - conditions: { rule: 'IS_ENTITY_KIND', params: [['b']] }, + conditions: { rule: 'IS_ENTITY_KIND', params: { kinds: ['b'] } }, }, ]); fakeCatalog.entities.mockResolvedValue({ entities: [] }); @@ -136,7 +136,7 @@ describe('AuthorizedEntitiesCatalog', () => { fakePermissionApi.authorizeConditional.mockResolvedValue([ { result: AuthorizeResult.CONDITIONAL, - conditions: { rule: 'IS_ENTITY_KIND', params: [['b']] }, + conditions: { rule: 'IS_ENTITY_KIND', params: { kinds: ['b'] } }, }, ]); fakeCatalog.entities.mockResolvedValue({ @@ -272,7 +272,7 @@ describe('AuthorizedEntitiesCatalog', () => { fakePermissionApi.authorizeConditional.mockResolvedValue([ { result: AuthorizeResult.CONDITIONAL, - conditions: { rule: 'IS_ENTITY_KIND', params: [['b']] }, + conditions: { rule: 'IS_ENTITY_KIND', params: { kinds: ['b'] } }, }, ]); const catalog = createCatalog(isEntityKind); diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index d47ace1454..d5bc7057dd 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -56,7 +56,7 @@ import { yamlPlaceholderResolver, } from '../modules/core/PlaceholderProcessor'; import { defaultEntityDataParser } from '../modules/util/parse'; -import { LocationAnalyzer } from '../ingestion/types'; +import { LocationAnalyzer, ScmLocationAnalyzer } from '../ingestion/types'; import { CatalogProcessingEngine } from '../processing'; import { DefaultProcessingDatabase } from '../database/DefaultProcessingDatabase'; import { applyDatabaseMigrations } from '../database/migrations'; @@ -115,6 +115,10 @@ export type CatalogEnvironment = { * after the processors' pre-processing steps. All policies are given the * chance to inspect the entity, and all of them have to pass in order for * the entity to be considered valid from an overall point of view. + * - Location analyzers can be added. These are responsible for analyzing + * repositories when onboarding them into the catalog, by finding + * catalog-info.yaml files and other artifacts that can help automatically + * register or create catalog data on the user's behalf. * - Placeholder resolvers can be replaced or added. These run on the raw * structured data between the parsing and pre-processing steps, to replace * dollar-prefixed entries with their actual values (like $file). @@ -135,6 +139,7 @@ export class CatalogBuilder { private fieldFormatValidators: Partial; private entityProviders: EntityProvider[]; private processors: CatalogProcessor[]; + private locationAnalyzers: ScmLocationAnalyzer[]; private processorsReplace: boolean; private parser: CatalogProcessorParser | undefined; private onProcessingError?: (event: { @@ -165,6 +170,7 @@ export class CatalogBuilder { this.fieldFormatValidators = {}; this.entityProviders = []; this.processors = []; + this.locationAnalyzers = []; this.processorsReplace = false; this.parser = undefined; this.permissionRules = Object.values(catalogPermissionRules); @@ -335,6 +341,21 @@ export class CatalogBuilder { ]; } + /** + * Adds Location Analyzers. These are responsible for analyzing + * repositories when onboarding them into the catalog, by finding + * catalog-info.yaml files and other artifacts that can help automatically + * register or create catalog data on the user's behalf. + * + * @param locationAnalyzers - One or more location analyzers + */ + addLocationAnalyzers( + ...analyzers: Array> + ): CatalogBuilder { + this.locationAnalyzers.push(...analyzers.flat()); + return this; + } + /** * Sets up the catalog to use a custom parser for entity data. * @@ -478,7 +499,8 @@ export class CatalogBuilder { ); const locationAnalyzer = - this.locationAnalyzer ?? new RepoLocationAnalyzer(logger, integrations); + this.locationAnalyzer ?? + new RepoLocationAnalyzer(logger, integrations, this.locationAnalyzers); const locationService = new AuthorizedLocationService( new DefaultLocationService(locationStore, orchestrator, { allowedLocationTypes: this.allowedLocationType, diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 16a36eb8c4..f383df7364 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -36,6 +36,7 @@ import { } from '@backstage/plugin-permission-node'; import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; import { CatalogProcessingOrchestrator } from '../processing/types'; +import { z } from 'zod'; describe('createRouter readonly disabled', () => { let entitiesCatalog: jest.Mocked; @@ -695,6 +696,9 @@ describe('NextRouter permissioning', () => { name: 'FAKE_RULE', description: 'fake rule', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, + paramsSchema: z.object({ + foo: z.string(), + }), apply: () => true, toQuery: () => ({ key: '', values: [] }), }); @@ -758,7 +762,9 @@ describe('NextRouter permissioning', () => { conditions: { rule: 'FAKE_RULE', resourceType: 'catalog-entity', - params: ['user:default/spiderman'], + params: { + foo: 'user:default/spiderman', + }, }, }, ], diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index 0002231bab..5267519c33 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -229,9 +229,15 @@ export async function createRouter( router.post('/analyze-location', async (req, res) => { const body = await validateRequestBody( req, - z.object({ location: locationInput }), + z.object({ + location: locationInput, + catalogFilename: z.string().optional(), + }), ); - const schema = z.object({ location: locationInput }); + const schema = z.object({ + location: locationInput, + catalogFilename: z.string().optional(), + }); const output = await locationAnalyzer.analyzeLocation(schema.parse(body)); res.status(200).json(output); }); diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index 04fb82c760..f1a54baa1f 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog-common +## 1.0.7-next.2 + +### Patch Changes + +- 823acaa88b: Moved the following types from `@backstage/plugin-catalog-backend` to this package. + + - AnalyzeLocationResponse + - AnalyzeLocationRequest + - AnalyzeLocationExistingEntity + - AnalyzeLocationGenerateEntity + - AnalyzeLocationEntityField + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.0-next.2 + - @backstage/plugin-search-common@1.1.0-next.2 + - @backstage/catalog-model@1.1.2-next.2 + ## 1.0.7-next.1 ### Patch Changes diff --git a/plugins/catalog-common/api-report.md b/plugins/catalog-common/api-report.md index b7eaf99d8b..1bef626c79 100644 --- a/plugins/catalog-common/api-report.md +++ b/plugins/catalog-common/api-report.md @@ -4,9 +4,46 @@ ```ts import { BasicPermission } from '@backstage/plugin-permission-common'; +import { Entity } from '@backstage/catalog-model'; import { IndexableDocument } from '@backstage/plugin-search-common'; import { ResourcePermission } from '@backstage/plugin-permission-common'; +// @public (undocumented) +export type AnalyzeLocationEntityField = { + field: string; + state: + | 'analysisSuggestedValue' + | 'analysisSuggestedNoValue' + | 'needsUserInput'; + value: string | null; + description: string; +}; + +// @public +export type AnalyzeLocationExistingEntity = { + location: LocationSpec; + isRegistered: boolean; + entity: Entity; +}; + +// @public +export type AnalyzeLocationGenerateEntity = { + entity: RecursivePartial; + fields: AnalyzeLocationEntityField[]; +}; + +// @public (undocumented) +export type AnalyzeLocationRequest = { + location: LocationSpec; + catalogFilename?: string; +}; + +// @public (undocumented) +export type AnalyzeLocationResponse = { + existingEntityFiles: AnalyzeLocationExistingEntity[]; + generateEntities: AnalyzeLocationGenerateEntity[]; +}; + // @alpha export const catalogEntityCreatePermission: BasicPermission; @@ -55,6 +92,13 @@ export const catalogPermissions: ( | ResourcePermission<'catalog-entity'> )[]; +// @public +export type LocationSpec = { + type: string; + target: string; + presence?: 'optional' | 'required'; +}; + // @alpha export const RESOURCE_TYPE_CATALOG_ENTITY = 'catalog-entity'; ``` diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 5be665b7d6..981adff43a 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-common", "description": "Common functionalities for the catalog plugin", - "version": "1.0.7-next.1", + "version": "1.0.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,6 +33,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { + "@backstage/catalog-model": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-search-common": "workspace:^" }, diff --git a/plugins/catalog-common/src/common.ts b/plugins/catalog-common/src/common.ts new file mode 100644 index 0000000000..c926a94b28 --- /dev/null +++ b/plugins/catalog-common/src/common.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +/** + * Holds the entity location information. + * + * @remarks + * + * `presence` flag: when using repo importer plugin, location is being created before the component yaml file is merged to the main branch. + * This flag is then set to indicate that the file can be not present. + * default value: 'required'. + * + * @public + */ +export type LocationSpec = { + type: string; + target: string; + presence?: 'optional' | 'required'; +}; diff --git a/plugins/catalog-common/src/index.ts b/plugins/catalog-common/src/index.ts index 614948e56c..95bd65bc92 100644 --- a/plugins/catalog-common/src/index.ts +++ b/plugins/catalog-common/src/index.ts @@ -35,3 +35,5 @@ export { export type { CatalogEntityPermission } from './permissions'; export * from './search'; +export * from './ingestion'; +export type { LocationSpec } from './common'; diff --git a/plugins/catalog-common/src/ingestion/LocationAnalyzer.ts b/plugins/catalog-common/src/ingestion/LocationAnalyzer.ts new file mode 100644 index 0000000000..08ae5ef0cb --- /dev/null +++ b/plugins/catalog-common/src/ingestion/LocationAnalyzer.ts @@ -0,0 +1,88 @@ +/* + * 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 { LocationSpec } from '../common'; +import { Entity } from '@backstage/catalog-model'; +import { RecursivePartial } from './RecursivePartial'; + +/** @public */ +export type AnalyzeLocationRequest = { + location: LocationSpec; + catalogFilename?: string; +}; + +/** @public */ +export type AnalyzeLocationResponse = { + existingEntityFiles: AnalyzeLocationExistingEntity[]; + generateEntities: AnalyzeLocationGenerateEntity[]; +}; + +/** + * If the folder pointed to already contained catalog info yaml files, they are + * read and emitted like this so that the frontend can inform the user that it + * located them and can make sure to register them as well if they weren't + * already + * @public + */ +export type AnalyzeLocationExistingEntity = { + location: LocationSpec; + isRegistered: boolean; + entity: Entity; +}; + +/** + * This is some form of representation of what the analyzer could deduce. + * We should probably have a chat about how this can best be conveyed to + * the frontend. It'll probably contain a (possibly incomplete) entity, plus + * enough info for the frontend to know what form data to show to the user + * for overriding/completing the info. + * @public + */ +export type AnalyzeLocationGenerateEntity = { + // Some form of partial representation of the entity + entity: RecursivePartial; + // Lists the suggestions that the user may want to override + fields: AnalyzeLocationEntityField[]; +}; + +// This is where I get really vague. Something like this perhaps? Or it could be +// something like a json-schema that contains enough info for the frontend to +// be able to present a form and explanations +/** @public */ +export type AnalyzeLocationEntityField = { + /** + * e.g. "spec.owner"? The frontend needs to know how to "inject" the field into the + * entity again if the user wants to change it + */ + field: string; + + /** The outcome of the analysis for this particular field */ + state: + | 'analysisSuggestedValue' + | 'analysisSuggestedNoValue' + | 'needsUserInput'; + + // If the analysis did suggest a value, this is where it would be. Not sure if we want + // to limit this to strings or if we want it to be any JsonValue + value: string | null; + /** + * A text to show to the user to inform about the choices made. Like, it could say + * "Found a CODEOWNERS file that covers this target, so we suggest leaving this + * field empty; which would currently make it owned by X" where X is taken from the + * codeowners file. + */ + description: string; +}; diff --git a/plugins/catalog-common/src/ingestion/RecursivePartial.test.ts b/plugins/catalog-common/src/ingestion/RecursivePartial.test.ts new file mode 100644 index 0000000000..ab8d50534e --- /dev/null +++ b/plugins/catalog-common/src/ingestion/RecursivePartial.test.ts @@ -0,0 +1,31 @@ +/* + * 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 { RecursivePartial } from './RecursivePartial'; + +describe('RecursivePartial', () => { + it('is recursive', () => { + type X = { + required: { + required: string; + }; + }; + const x: RecursivePartial = { + required: {}, + }; + expect(x).toEqual({ required: {} }); + }); +}); diff --git a/plugins/catalog-common/src/ingestion/RecursivePartial.ts b/plugins/catalog-common/src/ingestion/RecursivePartial.ts new file mode 100644 index 0000000000..c452836f34 --- /dev/null +++ b/plugins/catalog-common/src/ingestion/RecursivePartial.ts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +/** + * Makes all keys of an entire hierarchy optional. + * @ignore + */ +export type RecursivePartial = { + [P in keyof T]?: T[P] extends (infer U)[] + ? RecursivePartial[] + : T[P] extends object + ? RecursivePartial + : T[P]; +}; diff --git a/plugins/catalog-common/src/ingestion/index.ts b/plugins/catalog-common/src/ingestion/index.ts new file mode 100644 index 0000000000..aced124bb4 --- /dev/null +++ b/plugins/catalog-common/src/ingestion/index.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +export type { + AnalyzeLocationResponse, + AnalyzeLocationRequest, + AnalyzeLocationExistingEntity, + AnalyzeLocationGenerateEntity, + AnalyzeLocationEntityField, +} from './LocationAnalyzer'; diff --git a/plugins/catalog-customized/CHANGELOG.md b/plugins/catalog-customized/CHANGELOG.md index 8ba2f88dce..b7542abb38 100644 --- a/plugins/catalog-customized/CHANGELOG.md +++ b/plugins/catalog-customized/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/plugin-catalog-customized +## 0.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.2.0-next.2 + ## 0.0.3-next.1 ### Patch Changes diff --git a/plugins/catalog-customized/package.json b/plugins/catalog-customized/package.json index ddd80bee43..82452a97fc 100644 --- a/plugins/catalog-customized/package.json +++ b/plugins/catalog-customized/package.json @@ -1,7 +1,7 @@ { "name": "@internal/plugin-catalog-customized", "description": "The internal Backstage Customizable plugin for browsing the Backstage catalog", - "version": "0.0.3-next.1", + "version": "0.0.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 724a4bf1a2..6eb03b86b8 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-graph +## 0.2.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.2.0-next.2 + - @backstage/catalog-client@1.1.1-next.2 + - @backstage/catalog-model@1.1.2-next.2 + - @backstage/core-components@0.11.2-next.2 + - @backstage/core-plugin-api@1.0.7-next.2 + - @backstage/theme@0.2.16 + ## 0.2.22-next.1 ### Patch Changes diff --git a/plugins/catalog-graph/api-report.md b/plugins/catalog-graph/api-report.md index ed4ca2a2c9..95f497fe95 100644 --- a/plugins/catalog-graph/api-report.md +++ b/plugins/catalog-graph/api-report.md @@ -30,6 +30,7 @@ export const CatalogGraphPage: (props: { mergeRelations?: boolean | undefined; direction?: Direction | undefined; showFilters?: boolean | undefined; + curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; } | undefined; }) => JSX.Element; @@ -120,6 +121,7 @@ export const EntityRelationsGraph: (props: { renderLabel?: | DependencyGraphTypes.RenderLabelFunction | undefined; + curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; }) => JSX.Element; // @public diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 8fd71845c2..cc4a598380 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.22-next.1", + "version": "0.2.22-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx index 8e59c127d9..a6a6c2a711 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx @@ -40,6 +40,7 @@ import { EntityRelationsGraph, RelationPairs, } from '../EntityRelationsGraph'; +import { CurveFilter } from './CurveFilter'; import { DirectionFilter } from './DirectionFilter'; import { MaxDepthFilter } from './MaxDepthFilter'; import { SelectedKindsFilter } from './SelectedKindsFilter'; @@ -110,6 +111,7 @@ export const CatalogGraphPage = (props: { mergeRelations?: boolean; direction?: Direction; showFilters?: boolean; + curve?: 'curveStepBefore' | 'curveMonotoneX'; }; }) => { const { relationPairs = ALL_RELATION_PAIRS, initialState } = props; @@ -130,6 +132,8 @@ export const CatalogGraphPage = (props: { setMergeRelations, direction, setDirection, + curve, + setCurve, rootEntityNames, setRootEntityNames, showFilters, @@ -201,6 +205,7 @@ export const CatalogGraphPage = (props: { relationPairs={relationPairs} /> + diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.test.tsx new file mode 100644 index 0000000000..0be0fca66b --- /dev/null +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.test.tsx @@ -0,0 +1,47 @@ +/* + * 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. + */ +import { render, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { CurveFilter } from './CurveFilter'; + +describe('', () => { + test('should display current curve label', () => { + const onChange = jest.fn(); + const { getByText } = render( + , + ); + + expect(getByText('Monotone X')).toBeInTheDocument(); + }); + + test('should select an alternative curve factory', async () => { + const onChange = jest.fn(); + const { getByText, getByTestId } = render( + , + ); + + expect(getByText('Step Before')).toBeInTheDocument(); + + await userEvent.click(getByTestId('select')); + await userEvent.click(getByText('Monotone X')); + + await waitFor(() => { + expect(getByText('Monotone X')).toBeInTheDocument(); + expect(onChange).toHaveBeenCalledWith('curveMonotoneX'); + }); + }); +}); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.tsx new file mode 100644 index 0000000000..6cda334cf1 --- /dev/null +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.tsx @@ -0,0 +1,49 @@ +/* + * 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. + */ +import { Select } from '@backstage/core-components'; +import { Box } from '@material-ui/core'; +import React, { useCallback } from 'react'; + +type Curve = 'curveStepBefore' | 'curveMonotoneX'; +const CURVE_DISPLAY_NAMES: Record = { + curveMonotoneX: 'Monotone X', + curveStepBefore: 'Step Before', +}; + +export type Props = { + value: Curve; + onChange: (value: 'curveStepBefore' | 'curveMonotoneX') => void; +}; + +const curves: Array = ['curveMonotoneX', 'curveStepBefore']; + +export const CurveFilter = ({ value, onChange }: Props) => { + const handleChange = useCallback(v => onChange(v as Curve), [onChange]); + + return ( + +