-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new test template with custom field extensions using the new hooks
- Loading branch information
Showing
12 changed files
with
306 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
packages/app/src/scaffolder/GithubAuth/GithubAuthExtension.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import React, { 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'; | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
import { useAuth, RequestUserCredentials } from 'scaffolder-frontend-auth'; | ||
|
||
export const GithubAuth = (props: FieldExtensionComponentProps<string>) => { | ||
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 ( | ||
<FormControl margin="normal" required error={rawErrors?.length > 0}> | ||
<InputLabel htmlFor="ownerWithRepo">owner/repo</InputLabel> | ||
<Input | ||
id="ownerWithRepo" | ||
aria-describedby="ownerRepoField" | ||
onChange={e => onChange(e.target?.value)} | ||
/> | ||
<FormHelperText id="ownerRepoField"> | ||
{`The owner/repo combination to read metadata, e.g. thefrontside/playhouse${ | ||
token ? `, using the token ending with ${token?.slice(-5)}` : '' | ||
}`} | ||
</FormHelperText> | ||
</FormControl> | ||
); | ||
}; | ||
|
||
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.`); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// packages/app/src/scaffolder/ValidateKebabCase/index.ts | ||
|
||
export { GithubAuthFieldExtension } from './extensions'; |
92 changes: 92 additions & 0 deletions
92
packages/app/src/scaffolder/GithubQuery/GithubQueryExtension.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
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'; | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
import Autocomplete from '@material-ui/lab/Autocomplete'; | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
import { TextField } from '@material-ui/core'; | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
import { | ||
useFetchWithAuth, | ||
RequestUserCredentials, | ||
} from 'scaffolder-frontend-auth'; | ||
|
||
export const GithubQuery = (props: FieldExtensionComponentProps<string>) => { | ||
const { uiSchema, onChange, rawErrors, formData, required } = props; | ||
const [ownerInput, setOwnerInput] = useState<string>('thefrontside'); | ||
const [owner, setOwner] = useState<string>('thefrontside'); | ||
const uiOptions = useMemo(() => uiSchema?.['ui:options'] ?? {}, [uiSchema]); | ||
|
||
const requestUserCredentials = | ||
uiOptions?.requestUserCredentials && | ||
typeof uiOptions?.requestUserCredentials === 'object' | ||
? (uiOptions?.requestUserCredentials as RequestUserCredentials) | ||
: undefined; | ||
|
||
const { value, loading, error } = useFetchWithAuth({ | ||
url: 'https://github.com', | ||
requestUserCredentials, | ||
fetchOpts: { | ||
url: `https://api.github.com/orgs/${owner}/repos`, | ||
options: { | ||
headers: { | ||
Accept: 'application/vnd.github+json', | ||
Authorization: 'Bearer ', | ||
// this isn't allowed so *shrugs* | ||
// per_page: '100', | ||
}, | ||
}, | ||
headersRequiringToken: ['Authorization'], | ||
}, | ||
}); | ||
|
||
const onSelect = useCallback( | ||
(_: any, selectValue: string | null) => { | ||
onChange(selectValue ?? undefined); | ||
}, | ||
[onChange], | ||
); | ||
|
||
return ( | ||
<> | ||
<FormControl margin="normal" required error={rawErrors?.length > 0}> | ||
<InputLabel htmlFor="owner">organization</InputLabel> | ||
<Input | ||
id="owner" | ||
aria-describedby="ownerField" | ||
value={ownerInput} | ||
onChange={e => setOwnerInput(e.target?.value)} | ||
onBlur={() => setOwner(ownerInput)} | ||
/> | ||
<FormHelperText id="ownerField"> | ||
The owner to query a list of repositories | ||
</FormHelperText> | ||
</FormControl> | ||
<FormControl margin="normal" error={rawErrors?.length > 0 && !formData}> | ||
<Autocomplete | ||
value={(formData as string) || ''} | ||
loading={loading} | ||
onChange={onSelect} | ||
options={value?.map((repo: { name: string }) => repo.name) ?? []} | ||
autoSelect | ||
renderInput={params => ( | ||
<TextField | ||
{...params} | ||
margin="dense" | ||
FormHelperTextProps={{ | ||
margin: 'dense', | ||
style: { marginLeft: 0 }, | ||
}} | ||
variant="outlined" | ||
required={required} | ||
InputProps={params.InputProps} | ||
/> | ||
)} | ||
/> | ||
</FormControl> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// packages/app/src/scaffolder/ValidateKebabCase/index.ts | ||
|
||
export { GithubQueryFieldExtension } from './extensions'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { GithubAuthFieldExtension } from './GithubAuth'; | ||
import { GithubQueryFieldExtension } from './GithubQuery'; | ||
|
||
export const allFieldExtensions = [ | ||
GithubAuthFieldExtension, | ||
GithubQueryFieldExtension, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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: [email protected] | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9434,13 +9434,20 @@ | |
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" | ||
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== | ||
|
||
"@types/react-dom@*", "@types/react-dom@<18.0.0", "@types/react-dom@^17", "@types/react-dom@^18.0.0": | ||
"@types/react-dom@*", "@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== | ||
dependencies: | ||
"@types/react" "^17" | ||
|
||
"@types/react-dom@^18.0.0": | ||
version "18.0.10" | ||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.10.tgz#3b66dec56aa0f16a6cc26da9e9ca96c35c0b4352" | ||
integrity sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg== | ||
dependencies: | ||
"@types/react" "*" | ||
|
||
"@types/react-redux@^7.1.20": | ||
version "7.1.24" | ||
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.24.tgz#6caaff1603aba17b27d20f8ad073e4c077e975c0" | ||
|
@@ -15564,11 +15571,21 @@ graphql-ws@^5.4.1: | |
resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.9.1.tgz#9c0fa48ceb695d61d574ed3ab21b426729e87f2d" | ||
integrity sha512-mL/SWGBwIT9Meq0NlfS55yXXTOeWPMbK7bZBEZhFu46bcGk1coTx2Sdtzxdk+9yHWngD+Fk1PZDWaAutQa9tpw== | ||
|
||
graphql@*, [email protected], "graphql@^15.0.0 || ^16.0.0", graphql@^15.5.0, graphql@^15.5.1, graphql@^16.0.0, graphql@^16.3.0, graphql@^16.5.0, graphql@^16.6.0: | ||
graphql@*, "graphql@^15.0.0 || ^16.0.0", graphql@^16.0.0, graphql@^16.3.0, graphql@^16.5.0, graphql@^16.6.0: | ||
version "16.6.0" | ||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" | ||
integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== | ||
|
||
[email protected]: | ||
version "16.5.0" | ||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85" | ||
integrity sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA== | ||
|
||
graphql@^15.5.0, graphql@^15.5.1: | ||
version "15.8.0" | ||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" | ||
integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== | ||
|
||
gtoken@^6.0.0: | ||
version "6.1.0" | ||
resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-6.1.0.tgz#62938c679b364662ce21077858e0db3cfe025363" | ||
|
@@ -22278,7 +22295,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== | ||
|