diff --git a/.scripts/humanitec.mjs b/.scripts/humanitec.mjs index 2112df4895..e7a10e3d9c 100644 --- a/.scripts/humanitec.mjs +++ b/.scripts/humanitec.mjs @@ -95,7 +95,7 @@ function* cloneEnvironment({ newEnvName }) { body: JSON.stringify({ active: true, artefacts_filter: [artefactsFilter], - match_ref: `refs/heads/${newEnvName}/merge`, + match_ref: `refs/heads/${newEnvName.startsWith('pr') ? newEnvName.slice(2) : newEnvName}/merge`, type: 'update', }), }); diff --git a/app-config.production.yaml b/app-config.production.yaml index b6d4cfe550..1494ae1434 100644 --- a/app-config.production.yaml +++ b/app-config.production.yaml @@ -41,8 +41,12 @@ catalog: locations: - type: url target: https://github.com/thefrontside/playhouse/blob/main/catalog-info.yaml - - type: url - target: https://github.com/thefrontside/playhouse/blob/main/templates/standard-microservice/template.yaml + - type: file + target: ../../templates/standard-microservice/template.yaml + rules: + - allow: [Template] + - type: file + target: ../../templates/echo-repo-with-auth/template.yaml rules: - allow: [Template] diff --git a/app-config.yaml b/app-config.yaml index 6f1f7f027e..7fd83f985e 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -96,6 +96,10 @@ catalog: target: ../../templates/standard-microservice/template.yaml rules: - allow: [Template] + - type: file + target: ../../templates/echo-repo-with-auth/template.yaml + rules: + - allow: [Template] humanitec: orgId: the-frontside-software-inc diff --git a/packages/app/package.json b/packages/app/package.json index 700853c383..0721cdae51 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -28,8 +28,8 @@ "@backstage/plugin-search-react": "^1.4.0", "@backstage/plugin-tech-radar": "^0.6.0", "@backstage/plugin-techdocs": "^1.4.3", - "@backstage/plugin-techdocs-react": "^1.1.2", "@backstage/plugin-techdocs-module-addons-contrib": "^1.0.9", + "@backstage/plugin-techdocs-react": "^1.1.2", "@backstage/plugin-user-settings": "^0.6.2", "@backstage/theme": "^0.2.16", "@frontside/backstage-plugin-effection-inspector": "^0.1.5", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index fc7b8354a3..d464a17402 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -12,6 +12,8 @@ import { } from '@backstage/plugin-catalog-import'; import { ScaffolderPage, scaffolderPlugin } from '@backstage/plugin-scaffolder'; import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha'; +import { ScaffolderFieldExtensions } from '@backstage/plugin-scaffolder-react'; +import { allFieldExtensions } from './scaffolder'; import { SearchPage } from '@backstage/plugin-search'; import { TechRadarPage } from '@backstage/plugin-tech-radar'; import { @@ -105,7 +107,13 @@ const routes = ( path="/create/legacy" element={} /> - } /> + } > + + {allFieldExtensions.map(Component => ( + + ))} + + } /> ) => { + const { uiSchema, onChange, rawErrors } = props; + const uiOptions = useMemo(() => uiSchema?.['ui:options'] ?? {}, [uiSchema]); + + const requestUserCredentials = + uiOptions?.requestUserCredentials && + typeof uiOptions?.requestUserCredentials === 'object' + ? (uiOptions?.requestUserCredentials as RequestUserCredentials) + : undefined; + + const token = useAuth({ + url: 'https://github.com', + requestUserCredentials, + }); + + return ( + 0}> + owner/repo + onChange(e.target?.value)} + /> + + {`The owner/repo combination to read metadata, e.g. thefrontside/playhouse${ + token ? `, using the token ending with ${token?.slice(-5)}` : '' + }`} + + + ); +}; + +export const validateOwnerRepoCombination = ( + value: string, + validation: { addError: (arg0: string) => void }, +) => { + const parts = value?.split('/'); + + if (parts?.length !== 2) { + validation.addError(`Needs an owner/project format.`); + } +}; diff --git a/packages/app/src/scaffolder/GithubAuth/extensions.ts b/packages/app/src/scaffolder/GithubAuth/extensions.ts new file mode 100644 index 0000000000..2e804a2d90 --- /dev/null +++ b/packages/app/src/scaffolder/GithubAuth/extensions.ts @@ -0,0 +1,23 @@ +// packages/app/src/scaffolder/ValidateKebabCase/extensions.ts + +/* + This is where the magic happens and creates the custom field extension. + + Note that if you're writing extensions part of a separate plugin, + then please use `scaffolderPlugin.provide` from there instead and export it part of your `plugin.ts` rather than re-using the `scaffolder.plugin`. +*/ + +import { scaffolderPlugin } from '@backstage/plugin-scaffolder'; +import { createScaffolderFieldExtension } from '@backstage/plugin-scaffolder-react'; +import { + GithubAuth, + validateOwnerRepoCombination, +} from './GithubAuthExtension'; + +export const GithubAuthFieldExtension = scaffolderPlugin.provide( + createScaffolderFieldExtension({ + name: 'GithubAuth', + component: GithubAuth, + validation: validateOwnerRepoCombination, + }), +); diff --git a/packages/app/src/scaffolder/GithubAuth/index.ts b/packages/app/src/scaffolder/GithubAuth/index.ts new file mode 100644 index 0000000000..cffb1f8da7 --- /dev/null +++ b/packages/app/src/scaffolder/GithubAuth/index.ts @@ -0,0 +1,3 @@ +// packages/app/src/scaffolder/ValidateKebabCase/index.ts + +export { GithubAuthFieldExtension } from './extensions'; diff --git a/packages/app/src/scaffolder/GithubQuery/GithubQueryExtension.tsx b/packages/app/src/scaffolder/GithubQuery/GithubQueryExtension.tsx new file mode 100644 index 0000000000..2e97793e6c --- /dev/null +++ b/packages/app/src/scaffolder/GithubQuery/GithubQueryExtension.tsx @@ -0,0 +1,79 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import React, { useCallback, useMemo, useState } from 'react'; +import FormControl from '@material-ui/core/FormControl'; +import FormHelperText from '@material-ui/core/FormHelperText'; +import Input from '@material-ui/core/Input'; +import InputLabel from '@material-ui/core/InputLabel'; +import { FieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react'; + +import Autocomplete from '@material-ui/lab/Autocomplete'; +import { TextField } from '@material-ui/core'; +import { + useGithubApi, + RequestUserCredentials, +} from 'scaffolder-frontend-auth'; + +export const GithubQuery = (props: FieldExtensionComponentProps) => { + const { uiSchema, onChange, rawErrors, formData, required } = props; + const [ownerInput, setOwnerInput] = useState('thefrontside'); + const [owner, setOwner] = useState('thefrontside'); + const uiOptions = useMemo(() => uiSchema?.['ui:options'] ?? {}, [uiSchema]); + + const requestUserCredentials = + uiOptions?.requestUserCredentials && + typeof uiOptions?.requestUserCredentials === 'object' + ? (uiOptions?.requestUserCredentials as RequestUserCredentials) + : undefined; + + const { value, loading } = useGithubApi({ + requestUserCredentials, + queryUrl: `orgs/${owner}/repos`, + }); + + const onSelect = useCallback( + (_: any, selectValue: string | null) => { + onChange(selectValue ?? undefined); + }, + [onChange], + ); + + return ( + <> + 0}> + organization + setOwnerInput(e.target?.value)} + onBlur={() => setOwner(ownerInput)} + /> + + The owner to query a list of repositories + + + 0 && !formData}> + repo.name) ?? []} + autoSelect + renderInput={params => ( + + )} + /> + + + ); +}; diff --git a/packages/app/src/scaffolder/GithubQuery/extensions.ts b/packages/app/src/scaffolder/GithubQuery/extensions.ts new file mode 100644 index 0000000000..2909717c1d --- /dev/null +++ b/packages/app/src/scaffolder/GithubQuery/extensions.ts @@ -0,0 +1,19 @@ +// packages/app/src/scaffolder/ValidateKebabCase/extensions.ts + +/* + This is where the magic happens and creates the custom field extension. + + Note that if you're writing extensions part of a separate plugin, + then please use `scaffolderPlugin.provide` from there instead and export it part of your `plugin.ts` rather than re-using the `scaffolder.plugin`. +*/ + +import { scaffolderPlugin } from '@backstage/plugin-scaffolder'; +import { createScaffolderFieldExtension } from '@backstage/plugin-scaffolder-react'; +import { GithubQuery } from './GithubQueryExtension'; + +export const GithubQueryFieldExtension = scaffolderPlugin.provide( + createScaffolderFieldExtension({ + name: 'GithubQuery', + component: GithubQuery, + }), +); diff --git a/packages/app/src/scaffolder/GithubQuery/index.ts b/packages/app/src/scaffolder/GithubQuery/index.ts new file mode 100644 index 0000000000..4a585e9c00 --- /dev/null +++ b/packages/app/src/scaffolder/GithubQuery/index.ts @@ -0,0 +1,3 @@ +// packages/app/src/scaffolder/ValidateKebabCase/index.ts + +export { GithubQueryFieldExtension } from './extensions'; diff --git a/packages/app/src/scaffolder/index.ts b/packages/app/src/scaffolder/index.ts new file mode 100644 index 0000000000..66a761c7d7 --- /dev/null +++ b/packages/app/src/scaffolder/index.ts @@ -0,0 +1,7 @@ +import { GithubAuthFieldExtension } from './GithubAuth'; +import { GithubQueryFieldExtension } from './GithubQuery'; + +export const allFieldExtensions = [ + GithubAuthFieldExtension, + GithubQueryFieldExtension, +]; diff --git a/plugins/scaffolder-frontend-auth/.eslintrc.js b/plugins/scaffolder-frontend-auth/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/scaffolder-frontend-auth/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/scaffolder-frontend-auth/README.md b/plugins/scaffolder-frontend-auth/README.md new file mode 100644 index 0000000000..ce7cae159a --- /dev/null +++ b/plugins/scaffolder-frontend-auth/README.md @@ -0,0 +1,7 @@ +# scaffolder-frontend-auth + +_This package was created through the Backstage CLI_. + +## About + +This plugin is not currently published, and intended as an experimentation in hooks to grab a token and use it in a fetch call within a scaffolder workflow. diff --git a/plugins/scaffolder-frontend-auth/package.json b/plugins/scaffolder-frontend-auth/package.json new file mode 100644 index 0000000000..3fbf2cb0e2 --- /dev/null +++ b/plugins/scaffolder-frontend-auth/package.json @@ -0,0 +1,41 @@ +{ + "name": "scaffolder-frontend-auth", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": true, + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "files": [ + "dist" + ], + "backstage": { + "role": "web-library" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/core-plugin-api": "^1.3.0", + "@backstage/integration-react": "^1.1.9", + "@backstage/plugin-scaffolder-react": "^1.0.1", + "react-use": "^17.4.0" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "^0.22.1", + "@testing-library/jest-dom": "^5.10.1" + } +} diff --git a/plugins/scaffolder-frontend-auth/src/hooks/useAuth.tsx b/plugins/scaffolder-frontend-auth/src/hooks/useAuth.tsx new file mode 100644 index 0000000000..786d2bcf05 --- /dev/null +++ b/plugins/scaffolder-frontend-auth/src/hooks/useAuth.tsx @@ -0,0 +1,46 @@ +import { useState } from 'react'; +import { useApi } from '@backstage/core-plugin-api'; +import { scmAuthApiRef } from '@backstage/integration-react'; +import { useTemplateSecrets } from '@backstage/plugin-scaffolder-react'; +import useDebounce from 'react-use/lib/useDebounce'; + +export type RequestUserCredentials = { + additionalScopes: Record; + secretsKey: string; +}; + +export const useAuth = ({ + requestUserCredentials, + url, +}: { + requestUserCredentials?: RequestUserCredentials; + url?: string; +} = {}) => { + const schAuthApi = useApi(scmAuthApiRef); + const { setSecrets } = useTemplateSecrets(); + const [localToken, setToken] = useState(); + + useDebounce( + async () => { + if (!requestUserCredentials || !url) return; + + const { token } = await schAuthApi.getCredentials({ + url, + additionalScope: { + repoWrite: true, + ...(requestUserCredentials?.additionalScopes + ? { customScopes: requestUserCredentials.additionalScopes } + : {}), + }, + }); + + if (requestUserCredentials?.secretsKey) + setSecrets({ [requestUserCredentials.secretsKey]: token }); + setToken(token); + }, + 500, + [localToken, requestUserCredentials], + ); + + return localToken ? localToken : undefined; +}; diff --git a/plugins/scaffolder-frontend-auth/src/hooks/useGithubApi.tsx b/plugins/scaffolder-frontend-auth/src/hooks/useGithubApi.tsx new file mode 100644 index 0000000000..9297866368 --- /dev/null +++ b/plugins/scaffolder-frontend-auth/src/hooks/useGithubApi.tsx @@ -0,0 +1,45 @@ +import useAsync from 'react-use/lib/useAsync'; +import { useAuth } from './useAuth'; + +export type RequestUserCredentials = { + additionalScopes: Record; + secretsKey: string; +}; + +export const useGithubApi = ({ + requestUserCredentials, + queryUrl, + method = 'GET', +}: { + requestUserCredentials?: RequestUserCredentials; + queryUrl: string; + method?: 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' | 'DELETE'; +}) => { + const token = useAuth({ url: 'https://github.com', requestUserCredentials }); + + const { value, loading, error } = useAsync(async (): Promise => { + if (token) { + const response = await fetch( + `https://api.github.com/${ + queryUrl.startsWith('/') ? queryUrl.slice(1) : queryUrl + }`, + { + method, + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${token}`, + }, + }, + ); + + if (!response.ok) { + throw new Error(`unable to fetch from ${queryUrl}`); + } + + return response.json(); + } + return undefined; + }, [token]); + + return { value, loading, error }; +}; diff --git a/plugins/scaffolder-frontend-auth/src/index.ts b/plugins/scaffolder-frontend-auth/src/index.ts new file mode 100644 index 0000000000..59f8233d5f --- /dev/null +++ b/plugins/scaffolder-frontend-auth/src/index.ts @@ -0,0 +1,2 @@ +export { useAuth, type RequestUserCredentials } from './hooks/useAuth'; +export { useGithubApi } from './hooks/useGithubApi'; diff --git a/plugins/scaffolder-frontend-auth/src/setupTests.ts b/plugins/scaffolder-frontend-auth/src/setupTests.ts new file mode 100644 index 0000000000..7b0828bfa8 --- /dev/null +++ b/plugins/scaffolder-frontend-auth/src/setupTests.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom'; diff --git a/templates/echo-repo-with-auth/template.yaml b/templates/echo-repo-with-auth/template.yaml new file mode 100644 index 0000000000..9769d01eac --- /dev/null +++ b/templates/echo-repo-with-auth/template.yaml @@ -0,0 +1,74 @@ +apiVersion: scaffolder.backstage.io/v1beta3 +kind: Template +metadata: + name: echo-repo-with-auth + title: Echo Repo With Auth + description: A test template for working with the custom auth hook +spec: + owner: john@example.com + type: service + parameters: + - title: Github Custom Auth + required: + - customRepoUrl + properties: + customRepoUrl: # creating github repo and for registering catalog component + title: Repository + type: string + ui:field: GithubAuth + ui:options: + requestUserCredentials: + secretsKey: USER_CUSTOM_OAUTH_TOKEN + additionalScopes: + github: + - workflow + allowedHosts: + - github.com + - title: Github Auth And Query + required: + - customQueried + properties: + customQueried: # creating github repo and for registering catalog component + title: Repository + type: string + ui:field: GithubQuery + ui:options: + requestUserCredentials: + additionalScopes: + github: + - workflow + allowedHosts: + - github.com + - title: RepoUrlPicker + required: + - builtInRepoUrl + properties: + builtInRepoUrl: # creating github repo and for registering catalog component + title: Repository + type: string + ui:field: RepoUrlPicker + ui:options: + # https://backstage.io/docs/features/software-templates/writing-templates#using-the-users-oauth-token + requestUserCredentials: + secretsKey: USER_BUILTIN_OAUTH_TOKEN + additionalScopes: + github: + - workflow + allowedHosts: + - github.com + + steps: + - name: Read Environment + id: environment + action: backend:get-environment + + output: + links: + - title: Repository Custom + url: ${{ parameters.customRepoUrl }} # link to the remote repository + - title: Repository Queried + url: ${{ parameters.customQueried }} # link to the remote repository + - title: Repository Built-In + url: ${{ parameters.builtInRepoUrl }} # link to the remote repository + - title: Environment Org ID + url: ${{ steps['environment'].output.orgId }} # link to the remote repository diff --git a/yarn.lock b/yarn.lock index 57b79a1976..f53ae277cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3014,6 +3014,15 @@ "@backstage/errors" "^1.1.4" cross-fetch "^3.1.5" +"@backstage/catalog-client@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@backstage/catalog-client/-/catalog-client-1.3.1.tgz#625ce4da098bc3d3e9cdfad4152f53df2ab39d20" + integrity sha512-3RtkQ1z79Rm2USsuNtsEKKd2IZvgqZSQg0u7ohpB8NAJSgQ3VloyWpVPIrS9PUBOCj7oktS//HWD5d0LHm9cvw== + dependencies: + "@backstage/catalog-model" "^1.2.0" + "@backstage/errors" "^1.1.4" + cross-fetch "^3.1.5" + "@backstage/catalog-model@^0.0.0-nightly-20230202023026": version "0.0.0-nightly-20230202023026" resolved "https://registry.yarnpkg.com/@backstage/catalog-model/-/catalog-model-0.0.0-nightly-20230202023026.tgz#fd9b871c7d2fcc41134d2067f1fe4dc18a756706" @@ -3053,6 +3062,19 @@ lodash "^4.17.21" uuid "^8.0.0" +"@backstage/catalog-model@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@backstage/catalog-model/-/catalog-model-1.2.0.tgz#ff72246e5b5bbbbd82a7e876db7761ecc25f1d5c" + integrity sha512-4IRHcj4d2DdB/atB6D1IJgGF8JwGGW3BMwH+qNjh0y8TQ/ou3UnoZWBHhHJGSkkuPLVXofk+XLqddWugZ0aKQw== + dependencies: + "@backstage/config" "^1.0.6" + "@backstage/errors" "^1.1.4" + "@backstage/types" "^1.0.2" + ajv "^8.10.0" + json-schema "^0.4.0" + lodash "^4.17.21" + uuid "^8.0.0" + "@backstage/cli-common@^0.1.11": version "0.1.11" resolved "https://registry.yarnpkg.com/@backstage/cli-common/-/cli-common-0.1.11.tgz#9d8fd8cbe83e21ad3d207edecb3c3df3024a35a8" @@ -3333,6 +3355,49 @@ zen-observable "^0.10.0" zod "~3.18.0" +"@backstage/core-components@^0.12.4": + version "0.12.4" + resolved "https://registry.yarnpkg.com/@backstage/core-components/-/core-components-0.12.4.tgz#86933ef16b67d7f73d49c1e21edb6edf6a2b07cb" + integrity sha512-AdQQcjFQX4YpX2wH3N6vS8sfnvQ9npft4L1EymHMgtWQyjmN+6vkpe7PNr1XPwLA7rELcBe2aqNqN3oRHzRiBQ== + dependencies: + "@backstage/config" "^1.0.6" + "@backstage/core-plugin-api" "^1.4.0" + "@backstage/errors" "^1.1.4" + "@backstage/theme" "^0.2.17" + "@backstage/version-bridge" "^1.0.3" + "@material-table/core" "^3.1.0" + "@material-ui/core" "^4.12.2" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.57" + "@react-hookz/web" "^20.0.0" + "@types/react-sparklines" "^1.7.0" + "@types/react-text-truncate" "^0.14.0" + ansi-regex "^6.0.1" + classnames "^2.2.6" + d3-selection "^3.0.0" + d3-shape "^3.0.0" + d3-zoom "^3.0.0" + dagre "^0.8.5" + history "^5.0.0" + immer "^9.0.1" + lodash "^4.17.21" + pluralize "^8.0.0" + prop-types "^15.7.2" + qs "^6.9.4" + rc-progress "3.4.1" + react-helmet "6.1.0" + react-hook-form "^7.12.2" + react-markdown "^8.0.0" + react-sparklines "^1.7.0" + react-syntax-highlighter "^15.4.5" + react-text-truncate "^0.19.0" + react-use "^17.3.2" + react-virtualized-auto-sizer "^1.0.6" + react-window "^1.8.6" + remark-gfm "^3.0.1" + zen-observable "^0.10.0" + zod "~3.18.0" + "@backstage/core-plugin-api@^0.0.0-nightly-20230214023046": version "0.0.0-nightly-20230214023046" resolved "https://registry.yarnpkg.com/@backstage/core-plugin-api/-/core-plugin-api-0.0.0-nightly-20230214023046.tgz#7234b1055c3f7b96e326a345421a2db09ce0180c" @@ -3357,6 +3422,18 @@ prop-types "^15.7.2" zen-observable "^0.10.0" +"@backstage/core-plugin-api@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@backstage/core-plugin-api/-/core-plugin-api-1.4.0.tgz#15ba4a5f1d892810ce75f3ba6b28851b1e15e780" + integrity sha512-GmQ7jEfV/SmVVYgxo99/FEjBTQNiL5H7jWtgAnwR+pht0UVY3WynW3optASbg76OSc+EpIkNIEXsU2LrMPJDeg== + dependencies: + "@backstage/config" "^1.0.6" + "@backstage/types" "^1.0.2" + "@backstage/version-bridge" "^1.0.3" + history "^5.0.0" + prop-types "^15.7.2" + zen-observable "^0.10.0" + "@backstage/dev-utils@^1.0.11", "@backstage/dev-utils@^1.0.9": version "1.0.11" resolved "https://registry.yarnpkg.com/@backstage/dev-utils/-/dev-utils-1.0.11.tgz#7a32d1e43c6c48d0b5bca3941044cdebd8c338e8" @@ -3647,6 +3724,15 @@ "@backstage/plugin-permission-common" "^0.7.3" "@backstage/plugin-search-common" "^1.2.1" +"@backstage/plugin-catalog-common@^1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@backstage/plugin-catalog-common/-/plugin-catalog-common-1.0.11.tgz#09cbc0c58e902d20cc37208ce8a0161d72bad846" + integrity sha512-aw6J3n93FR8vX5lu8UWTppeTMkf9tb+gLHpQKMRcBVi0ZwY7VfXrVpT/gCDxILY3xtTX03m8mVDcb/BButrccA== + dependencies: + "@backstage/catalog-model" "^1.2.0" + "@backstage/plugin-permission-common" "^0.7.3" + "@backstage/plugin-search-common" "^1.2.1" + "@backstage/plugin-catalog-graph@^0.2.26": version "0.2.26" resolved "https://registry.yarnpkg.com/@backstage/plugin-catalog-graph/-/plugin-catalog-graph-0.2.26.tgz#9f4e79b88dfee1ab178a6207721653f1447c77d6" @@ -3792,6 +3878,35 @@ yaml "^2.0.0" zen-observable "^0.10.0" +"@backstage/plugin-catalog-react@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@backstage/plugin-catalog-react/-/plugin-catalog-react-1.3.0.tgz#13bac4048f68fba37c5d3d9263712fa904f05f17" + integrity sha512-TF3wwUFQBUwv7G3CCuNPT1QAP1SRG0RjBIo9gDpOtvGRTe7yQj8xp0/z8uoUXyBcy+pkstMvrdVqHV0gHkStqg== + dependencies: + "@backstage/catalog-client" "^1.3.1" + "@backstage/catalog-model" "^1.2.0" + "@backstage/core-components" "^0.12.4" + "@backstage/core-plugin-api" "^1.4.0" + "@backstage/errors" "^1.1.4" + "@backstage/integration" "^1.4.2" + "@backstage/plugin-catalog-common" "^1.0.11" + "@backstage/plugin-permission-common" "^0.7.3" + "@backstage/plugin-permission-react" "^0.4.10" + "@backstage/theme" "^0.2.17" + "@backstage/types" "^1.0.2" + "@backstage/version-bridge" "^1.0.3" + "@material-ui/core" "^4.12.2" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.57" + classnames "^2.2.6" + jwt-decode "^3.1.0" + lodash "^4.17.21" + material-ui-popup-state "^1.9.3" + qs "^6.9.4" + react-use "^17.2.4" + yaml "^2.0.0" + zen-observable "^0.10.0" + "@backstage/plugin-catalog@^1.7.2": version "1.7.2" resolved "https://registry.yarnpkg.com/@backstage/plugin-catalog/-/plugin-catalog-1.7.2.tgz#d04de701c698d8129464a151f11d975c50549434" @@ -3918,6 +4033,18 @@ react-use "^17.2.4" swr "^2.0.0" +"@backstage/plugin-permission-react@^0.4.10": + version "0.4.10" + resolved "https://registry.yarnpkg.com/@backstage/plugin-permission-react/-/plugin-permission-react-0.4.10.tgz#2bd2c9806083d1bf238e26b61ce380b829211a2c" + integrity sha512-pVhwsU4S5Z01YLGS6c8omDSws/EoubULLkIZKwr81eaFubSIi7B9tBBENc1eEzjea3c71ZK3atW5Mutj1AH6sA== + dependencies: + "@backstage/config" "^1.0.6" + "@backstage/core-plugin-api" "^1.4.0" + "@backstage/plugin-permission-common" "^0.7.3" + cross-fetch "^3.1.5" + react-use "^17.2.4" + swr "^2.0.0" + "@backstage/plugin-permission-react@^0.4.9": version "0.4.9" resolved "https://registry.yarnpkg.com/@backstage/plugin-permission-react/-/plugin-permission-react-0.4.9.tgz#02e2d47e07e60092292a98620ad186c5d37aaf2a" @@ -4024,6 +4151,14 @@ "@backstage/catalog-model" "^1.1.5" "@backstage/types" "^1.0.2" +"@backstage/plugin-scaffolder-common@^1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@backstage/plugin-scaffolder-common/-/plugin-scaffolder-common-1.2.5.tgz#97a1dca821fe45a1a58c8995c0265ca5343805c2" + integrity sha512-vPsZ4YYGIPWXYQHucxlqTQNGVfl4EOTvUoIPS7pPi95ccYJDAGSCi2ASmJfJslwuZUAqQ+45EFNRPQz+v/XsSw== + dependencies: + "@backstage/catalog-model" "^1.2.0" + "@backstage/types" "^1.0.2" + "@backstage/plugin-scaffolder-react@0.0.0-nightly-20230202023026": version "0.0.0-nightly-20230202023026" resolved "https://registry.yarnpkg.com/@backstage/plugin-scaffolder-react/-/plugin-scaffolder-react-0.0.0-nightly-20230202023026.tgz#ff5d3e4f1dfe80b503773aaa94797d5e6ff1e095" @@ -4129,6 +4264,41 @@ zod "~3.18.0" zod-to-json-schema "~3.18.0" +"@backstage/plugin-scaffolder-react@^1.0.1": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@backstage/plugin-scaffolder-react/-/plugin-scaffolder-react-1.1.0.tgz#158251a4fe132be3f1b6c55cb777f2a3ee819f1f" + integrity sha512-WN3n8HnE3BbApr4QHtFA0XrfmC3G2VYTW2ii4QFWigrQMd6ePutQ595rN47yB71tMfiUhemiMnrC/XWr0CwxqA== + dependencies: + "@backstage/catalog-client" "^1.3.1" + "@backstage/catalog-model" "^1.2.0" + "@backstage/core-components" "^0.12.4" + "@backstage/core-plugin-api" "^1.4.0" + "@backstage/errors" "^1.1.4" + "@backstage/plugin-catalog-react" "^1.3.0" + "@backstage/plugin-scaffolder-common" "^1.2.5" + "@backstage/theme" "^0.2.17" + "@backstage/types" "^1.0.2" + "@backstage/version-bridge" "^1.0.3" + "@material-ui/core" "^4.12.2" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.57" + "@rjsf/core" "^3.2.1" + "@rjsf/core-v5" "npm:@rjsf/core@5.1.0" + "@rjsf/material-ui" "^3.2.1" + "@rjsf/material-ui-v5" "npm:@rjsf/material-ui@5.1.0" + "@rjsf/utils" "5.1.0" + "@rjsf/validator-ajv8" "5.1.0" + "@types/json-schema" "^7.0.9" + classnames "^2.2.6" + json-schema "^0.4.0" + json-schema-library "^7.3.9" + lodash "^4.17.21" + qs "^6.9.4" + react-use "^17.2.4" + zen-observable "^0.10.0" + zod "~3.18.0" + zod-to-json-schema "~3.18.0" + "@backstage/plugin-scaffolder@0.0.0-nightly-20230208023037": version "0.0.0-nightly-20230208023037" resolved "https://registry.yarnpkg.com/@backstage/plugin-scaffolder/-/plugin-scaffolder-0.0.0-nightly-20230208023037.tgz#d9f212d477508d6281161457e513f6303dbcb9af" @@ -4479,6 +4649,13 @@ dependencies: "@material-ui/core" "^4.12.2" +"@backstage/theme@^0.2.17": + version "0.2.17" + resolved "https://registry.yarnpkg.com/@backstage/theme/-/theme-0.2.17.tgz#89f6900f4cdb5bef838ebb1e71b0d5d582fe8ecc" + integrity sha512-ztCcMG61E31aYsAxCaCYpaPjFAk0no7Hb2zeiF6TlIpJiw5iCr0dSq42IWETmugk1piVTzv2t/diyjoi50Ll7Q== + dependencies: + "@material-ui/core" "^4.12.2" + "@backstage/types@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@backstage/types/-/types-1.0.2.tgz#a12cdc7c1ec7e0d99cb2e30903b9dfd97c1050c9" @@ -9435,9 +9612,9 @@ integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== "@types/react-dom@*", "@types/react-dom@<18.0.0", "@types/react-dom@^17", "@types/react-dom@^18.0.0": - version "17.0.18" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.18.tgz#8f7af38f5d9b42f79162eea7492e5a1caff70dc2" - integrity sha512-rLVtIfbwyur2iFKykP2w0pl/1unw26b5td16d5xMgp7/yjTHomkyxPYChFoCr/FtEX1lN9wY6lFj1qvKdS5kDw== + version "17.0.19" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.19.tgz#36feef3aa35d045cacd5ed60fe0eef5272f19492" + integrity sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ== dependencies: "@types/react" "^17" @@ -22278,7 +22455,7 @@ react-universal-interface@^0.6.2: resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw== -react-use@^17.2.4, react-use@^17.3.2: +react-use@^17.2.4, react-use@^17.3.2, react-use@^17.4.0: version "17.4.0" resolved "https://registry.yarnpkg.com/react-use/-/react-use-17.4.0.tgz#cefef258b0a6c534a5c8021c2528ac6e1a4cdc6d" integrity sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q==