Merge branch 'backstage:master' into feat/retry-in-useentity

This commit is contained in:
Yousif Al-Raheem
2021-07-21 12:20:52 +02:00
committed by GitHub
21 changed files with 215 additions and 99 deletions
+12 -1
View File
@@ -346,6 +346,16 @@ export interface RouterOptions {
providerFactories?: ProviderFactories;
}
// Warning: (ae-missing-release-tag) "TokenIssuer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export type TokenIssuer = {
issueToken(params: TokenParams): Promise<string>;
listPublicKeys(): Promise<{
keys: AnyJWK[];
}>;
};
// Warning: (ae-missing-release-tag) "verifyNonce" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -366,9 +376,10 @@ export type WebMessageResponse =
// Warnings were encountered during analysis:
//
// src/identity/types.d.ts:25:5 - (ae-forgotten-export) The symbol "TokenParams" needs to be exported by the entry point index.d.ts
// src/identity/types.d.ts:31:9 - (ae-forgotten-export) The symbol "AnyJWK" needs to be exported by the entry point index.d.ts
// src/providers/google/provider.d.ts:36:5 - (ae-forgotten-export) The symbol "AuthHandler" needs to be exported by the entry point index.d.ts
// src/providers/types.d.ts:105:5 - (ae-forgotten-export) The symbol "AuthProviderConfig" needs to be exported by the entry point index.d.ts
// src/providers/types.d.ts:108:5 - (ae-forgotten-export) The symbol "TokenIssuer" needs to be exported by the entry point index.d.ts
// src/providers/types.d.ts:111:5 - (ae-forgotten-export) The symbol "ExperimentalIdentityResolver" needs to be exported by the entry point index.d.ts
// src/providers/types.d.ts:128:8 - (tsdoc-missing-deprecation-message) The @deprecated block must include a deprecation message, e.g. describing the recommended alternative
+1
View File
@@ -16,6 +16,7 @@
export * from './service/router';
export { IdentityClient } from './identity';
export type { TokenIssuer } from './identity';
export * from './providers';
// flow package provides 2 functions
@@ -14,12 +14,12 @@
* limitations under the License.
*/
import { Grid, Typography } from '@material-ui/core';
import { Chip, Grid, Typography } from '@material-ui/core';
import React from 'react';
import { ImportStepper } from './ImportStepper';
import { StepperProviderOpts } from './ImportStepper/defaults';
import { ConfigApi, configApiRef, useApi } from '@backstage/core-plugin-api';
import { configApiRef, useApi } from '@backstage/core-plugin-api';
import {
Content,
ContentHeader,
@@ -29,30 +29,12 @@ import {
SupportButton,
} from '@backstage/core-components';
function repositories(configApi: ConfigApi): string[] {
const integrations = configApi.getConfig('integrations');
const repos = [];
if (integrations.has('github')) {
repos.push('GitHub');
}
if (integrations.has('bitbucket')) {
repos.push('Bitbucket');
}
if (integrations.has('gitlab')) {
repos.push('GitLab');
}
if (integrations.has('azure')) {
repos.push('Azure');
}
return repos;
}
export const ImportComponentPage = (opts: StepperProviderOpts) => {
const configApi = useApi(configApiRef);
const appTitle = configApi.getOptional('app.title') || 'Backstage';
const repos = repositories(configApi);
const repositoryString = repos.join(', ').replace(/, (\w*)$/, ' or $1');
const integrations = configApi.getConfig('integrations');
const hasGithubIntegration = integrations.has('github');
return (
<Page themeId="home">
@@ -76,7 +58,8 @@ export const ImportComponentPage = (opts: StepperProviderOpts) => {
}}
>
<Typography variant="body2" paragraph>
Enter the URL to your SCM repository to add it to {appTitle}.
Enter the URL to your source code repository to add it to{' '}
{appTitle}.
</Typography>
<Typography variant="h6">
Link to an existing entity file
@@ -91,10 +74,11 @@ export const ImportComponentPage = (opts: StepperProviderOpts) => {
The wizard analyzes the file, previews the entities, and adds
them to the {appTitle} catalog.
</Typography>
{repos.length > 0 && (
{hasGithubIntegration && (
<>
<Typography variant="h6">
Link to a {repositoryString} repository
Link to a repository{' '}
<Chip label="GitHub only" variant="outlined" size="small" />
</Typography>
<Typography
variant="subtitle2"
@@ -7,6 +7,7 @@
import { ApiRef } from '@backstage/core-plugin-api';
import { BackstagePlugin } from '@backstage/core-plugin-api';
import { default as React_2 } from 'react';
import { RouteRef } from '@backstage/core-plugin-api';
// Warning: (ae-forgotten-export) The symbol "GitReleaseApi" needs to be exported by the entry point index.d.ts
+60 -16
View File
@@ -16,7 +16,7 @@
import React from 'react';
import { createDevApp } from '@backstage/dev-utils';
import { Box, Typography } from '@material-ui/core';
import { Box, Button, Typography } from '@material-ui/core';
import { gitReleaseManagerPlugin, GitReleaseManagerPage } from '../src/plugin';
import { InfoCardPlus } from '../src/components/InfoCardPlus';
@@ -44,10 +44,16 @@ createDevApp()
<Box padding={4}>
<InfoCardPlus>
<Typography variant="h4">Dev notes</Typography>
<Typography>
Configure plugin statically by passing props to the
`GitHubReleaseManagerPage` component
</Typography>
<Typography variant="body2">
Note that the static configuration points towards private
repositories and will thus not work for everyone.
</Typography>
</InfoCardPlus>
<GitReleaseManagerPage
@@ -67,8 +73,10 @@ createDevApp()
<Box padding={4}>
<InfoCardPlus>
<Typography variant="h4">Dev notes</Typography>
<Typography>Each feature can be omitted</Typography>
<Typography>Success callbacks can also be added</Typography>
<Typography>
Each feature can be individually omitted as well as have success
callback attached to them
</Typography>
</InfoCardPlus>
<GitReleaseManagerPage
@@ -79,22 +87,12 @@ createDevApp()
}}
features={{
createRc: {
onSuccess: ({
comparisonUrl,
createdTag,
gitReleaseName,
gitReleaseUrl,
previousTag,
}) => {
onSuccess: args => {
// eslint-disable-next-line no-console
console.log(
'Custom success callback for Create RC',
comparisonUrl,
createdTag,
gitReleaseName,
gitReleaseUrl,
previousTag,
'Custom success callback for Create RC with the following args',
);
console.log(JSON.stringify(args, null, 2)); // eslint-disable-line no-console
},
},
promoteRc: {
@@ -108,4 +106,50 @@ createDevApp()
</Box>
),
})
.addPage({
title: 'Custom',
path: '/custom',
element: (
<Box padding={4}>
<InfoCardPlus>
<Typography variant="h4">Dev notes</Typography>
<Typography>
The custom feature's return value can either be a React Element or
an array of React Elements.
</Typography>
</InfoCardPlus>
<GitReleaseManagerPage
project={{
owner: 'eengervall-playground',
repo: 'playground-semver',
versioningStrategy: 'semver',
}}
features={{
custom: {
factory: args => {
return (
<InfoCardPlus>
<Typography variant="h4">I'm a custom feature</Typography>
<Button
variant="contained"
color="primary"
onClick={() => {
console.log(`Here's my args 🚀`); // eslint-disable-line no-console
console.log(JSON.stringify(args, null, 2)); // eslint-disable-line no-console
}}
>
View the arguments for this feature in the console by
pressing this button
</Button>
</InfoCardPlus>
);
},
},
}}
/>
</Box>
),
})
.render();
+3 -2
View File
@@ -28,12 +28,13 @@
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.45",
"@octokit/rest": "^18.5.3",
"@types/react": "^16.9",
"luxon": "^1.26.0",
"qs": "^6.10.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router": "6.0.0-beta.0",
"react-use": "^17.2.4",
"react": "^16.13.1",
"recharts": "^1.8.5"
},
"devDependencies": {
@@ -42,8 +43,8 @@
"@backstage/dev-utils": "^0.2.2",
"@backstage/test-utils": "^0.1.14",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/react-hooks": "^3.4.2",
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^13.1.8",
"@types/jest": "^26.0.7",
"@types/node": "^14.14.32",
@@ -18,12 +18,14 @@ import React from 'react';
import { useAsync } from 'react-use';
import { Alert } from '@material-ui/lab';
import { Box } from '@material-ui/core';
import { useApi } from '@backstage/core-plugin-api';
import { ContentHeader, Progress } from '@backstage/core-components';
import {
ComponentConfig,
ComponentConfigCreateRc,
ComponentConfigPatch,
ComponentConfigPromoteRc,
CreateRcOnSuccessArgs,
PatchOnSuccessArgs,
PromoteRcOnSuccessArgs,
} from './types/types';
import { Features } from './features/Features';
import { gitReleaseManagerApiRef } from './api/serviceApiRef';
@@ -33,18 +35,33 @@ import { ProjectContext, Project } from './contexts/ProjectContext';
import { RepoDetailsForm } from './features/RepoDetailsForm/RepoDetailsForm';
import { useQueryHandler } from './hooks/useQueryHandler';
import { UserContext } from './contexts/UserContext';
import { useApi } from '@backstage/core-plugin-api';
import { ContentHeader, Progress } from '@backstage/core-components';
import {
GetBranchResult,
GetLatestReleaseResult,
GetRepositoryResult,
} from './api/GitReleaseClient';
interface GitReleaseManagerProps {
project?: Omit<Project, 'isProvidedViaProps'>;
features?: {
info?: Pick<ComponentConfig<void>, 'omit'>;
stats?: Pick<ComponentConfig<void>, 'omit'>;
createRc?: ComponentConfigCreateRc;
promoteRc?: ComponentConfigPromoteRc;
patch?: ComponentConfigPatch;
createRc?: ComponentConfig<CreateRcOnSuccessArgs>;
promoteRc?: ComponentConfig<PromoteRcOnSuccessArgs>;
patch?: ComponentConfig<PatchOnSuccessArgs>;
custom?: {
factory: ({
latestRelease,
project,
releaseBranch,
repository,
}: {
latestRelease: GetLatestReleaseResult['latestRelease'] | null;
project: Project;
releaseBranch: GetBranchResult['branch'] | null;
repository: GetRepositoryResult['repository'];
}) => React.ReactElement | React.ReactElement[];
};
};
}
@@ -31,7 +31,7 @@ import {
GetLatestReleaseResult,
GetRepositoryResult,
} from '../../api/GitReleaseClient';
import { ComponentConfigCreateRc } from '../../types/types';
import { ComponentConfig, CreateRcOnSuccessArgs } from '../../types/types';
import { Differ } from '../../components/Differ';
import { getReleaseCandidateGitInfo } from '../../helpers/getReleaseCandidateGitInfo';
import { InfoCardPlus } from '../../components/InfoCardPlus';
@@ -45,7 +45,7 @@ interface CreateReleaseCandidateProps {
defaultBranch: GetRepositoryResult['repository']['defaultBranch'];
latestRelease: GetLatestReleaseResult['latestRelease'];
releaseBranch: GetBranchResult['branch'] | null;
onSuccess?: ComponentConfigCreateRc['onSuccess'];
onSuccess?: ComponentConfig<CreateRcOnSuccessArgs>['onSuccess'];
}
const InfoCardPlusWrapper = ({ children }: { children: React.ReactNode }) => {
@@ -21,7 +21,11 @@ import {
GetRepositoryResult,
} from '../../../api/GitReleaseClient';
import { CardHook, ComponentConfigCreateRc } from '../../../types/types';
import {
CardHook,
ComponentConfig,
CreateRcOnSuccessArgs,
} from '../../../types/types';
import { getReleaseCandidateGitInfo } from '../../../helpers/getReleaseCandidateGitInfo';
import { gitReleaseManagerApiRef } from '../../../api/serviceApiRef';
import { GitReleaseManagerError } from '../../../errors/GitReleaseManagerError';
@@ -31,12 +35,12 @@ import { useResponseSteps } from '../../../hooks/useResponseSteps';
import { useUserContext } from '../../../contexts/UserContext';
import { useApi } from '@backstage/core-plugin-api';
interface UseCreateReleaseCandidate {
export interface UseCreateReleaseCandidate {
defaultBranch: GetRepositoryResult['repository']['defaultBranch'];
latestRelease: GetLatestReleaseResult['latestRelease'];
releaseCandidateGitInfo: ReturnType<typeof getReleaseCandidateGitInfo>;
project: Project;
onSuccess?: ComponentConfigCreateRc['onSuccess'];
onSuccess?: ComponentConfig<CreateRcOnSuccessArgs>['onSuccess'];
}
export function useCreateReleaseCandidate({
@@ -266,6 +270,12 @@ export function useCreateReleaseCandidate({
try {
await onSuccess({
input: {
defaultBranch,
latestRelease,
releaseCandidateGitInfo,
project,
},
comparisonUrl: getComparisonRes.value.htmlUrl,
createdTag: createReleaseRes.value.tagName,
gitReleaseName: createReleaseRes.value.name,
@@ -142,6 +142,14 @@ export function Features({
onSuccess={features?.patch?.onSuccess}
/>
)}
{features?.custom?.factory &&
features.custom.factory({
latestRelease: gitBatchInfo.value.latestRelease,
project,
releaseBranch: gitBatchInfo.value.releaseBranch,
repository: gitBatchInfo.value.repository,
})}
</ErrorBoundary>
</RefetchContext.Provider>
);
@@ -22,7 +22,7 @@ import {
GetBranchResult,
GetLatestReleaseResult,
} from '../../api/GitReleaseClient';
import { ComponentConfigPatch } from '../../types/types';
import { ComponentConfig, PatchOnSuccessArgs } from '../../types/types';
import { getBumpedTag } from '../../helpers/getBumpedTag';
import { InfoCardPlus } from '../../components/InfoCardPlus';
import { NoLatestRelease } from '../../components/NoLatestRelease';
@@ -32,7 +32,7 @@ import { useProjectContext } from '../../contexts/ProjectContext';
interface PatchProps {
latestRelease: GetLatestReleaseResult['latestRelease'];
releaseBranch: GetBranchResult['branch'] | null;
onSuccess?: ComponentConfigPatch['onSuccess'];
onSuccess?: ComponentConfig<PatchOnSuccessArgs>['onSuccess'];
}
export const Patch = ({
@@ -38,7 +38,7 @@ import {
GetLatestReleaseResult,
} from '../../api/GitReleaseClient';
import { CalverTagParts } from '../../helpers/tagParts/getCalverTagParts';
import { ComponentConfigPatch } from '../../types/types';
import { ComponentConfig, PatchOnSuccessArgs } from '../../types/types';
import { Differ } from '../../components/Differ';
import { getPatchCommitSuffix } from './helpers/getPatchCommitSuffix';
import { gitReleaseManagerApiRef } from '../../api/serviceApiRef';
@@ -56,7 +56,7 @@ interface PatchBodyProps {
bumpedTag: string;
latestRelease: NonNullable<GetLatestReleaseResult['latestRelease']>;
releaseBranch: GetBranchResult['branch'];
onSuccess?: ComponentConfigPatch['onSuccess'];
onSuccess?: ComponentConfig<PatchOnSuccessArgs>['onSuccess'];
tagParts: NonNullable<CalverTagParts | SemverTagParts>;
}
@@ -22,7 +22,11 @@ import {
} from '../../../api/GitReleaseClient';
import { CalverTagParts } from '../../../helpers/tagParts/getCalverTagParts';
import { ComponentConfigPatch, CardHook } from '../../../types/types';
import {
CardHook,
ComponentConfig,
PatchOnSuccessArgs,
} from '../../../types/types';
import { getPatchCommitSuffix } from '../helpers/getPatchCommitSuffix';
import { gitReleaseManagerApiRef } from '../../../api/serviceApiRef';
import { Project } from '../../../contexts/ProjectContext';
@@ -32,12 +36,12 @@ import { useResponseSteps } from '../../../hooks/useResponseSteps';
import { useUserContext } from '../../../contexts/UserContext';
import { useApi } from '@backstage/core-plugin-api';
interface Patch {
export interface UsePatch {
bumpedTag: string;
latestRelease: NonNullable<GetLatestReleaseResult['latestRelease']>;
project: Project;
tagParts: NonNullable<CalverTagParts | SemverTagParts>;
onSuccess?: ComponentConfigPatch['onSuccess'];
onSuccess?: ComponentConfig<PatchOnSuccessArgs>['onSuccess'];
}
// Inspiration: https://stackoverflow.com/questions/53859199/how-to-cherry-pick-through-githubs-api
@@ -47,7 +51,7 @@ export function usePatch({
project,
tagParts,
onSuccess,
}: Patch): CardHook<GetRecentCommitsResultSingle> {
}: UsePatch): CardHook<GetRecentCommitsResultSingle> {
const pluginApiClient = useApi(gitReleaseManagerApiRef);
const { user } = useUserContext();
const {
@@ -337,13 +341,19 @@ ${selectedPatchCommit.commit.message}`,
try {
await onSuccess?.({
updatedReleaseUrl: updatedReleaseRes.value.htmlUrl,
updatedReleaseName: updatedReleaseRes.value.name,
previousTag: latestRelease.tagName,
patchedTag: updatedReleaseRes.value.tagName,
patchCommitUrl: releaseBranchRes.value.selectedPatchCommit.htmlUrl,
input: {
bumpedTag,
latestRelease,
project,
tagParts,
},
patchCommitMessage:
releaseBranchRes.value.selectedPatchCommit.commit.message,
patchCommitUrl: releaseBranchRes.value.selectedPatchCommit.htmlUrl,
patchedTag: updatedReleaseRes.value.tagName,
previousTag: latestRelease.tagName,
updatedReleaseName: updatedReleaseRes.value.name,
updatedReleaseUrl: updatedReleaseRes.value.htmlUrl,
});
} catch (error) {
asyncCatcher(error);
@@ -18,7 +18,7 @@ import React from 'react';
import { Alert, AlertTitle } from '@material-ui/lab';
import { Box, Typography } from '@material-ui/core';
import { ComponentConfigPromoteRc } from '../../types/types';
import { ComponentConfig, PromoteRcOnSuccessArgs } from '../../types/types';
import { GetLatestReleaseResult } from '../../api/GitReleaseClient';
import { InfoCardPlus } from '../../components/InfoCardPlus';
import { NoLatestRelease } from '../../components/NoLatestRelease';
@@ -27,7 +27,7 @@ import { TEST_IDS } from '../../test-helpers/test-ids';
interface PromoteRcProps {
latestRelease: GetLatestReleaseResult['latestRelease'];
onSuccess?: ComponentConfigPromoteRc['onSuccess'];
onSuccess?: ComponentConfig<PromoteRcOnSuccessArgs>['onSuccess'];
}
export const PromoteRc = ({ latestRelease, onSuccess }: PromoteRcProps) => {
@@ -17,7 +17,7 @@
import React from 'react';
import { Button, Typography, Box } from '@material-ui/core';
import { ComponentConfigPromoteRc } from '../../types/types';
import { ComponentConfig, PromoteRcOnSuccessArgs } from '../../types/types';
import { Differ } from '../../components/Differ';
import { GetLatestReleaseResult } from '../../api/GitReleaseClient';
import { ResponseStepDialog } from '../../components/ResponseStepDialog/ResponseStepDialog';
@@ -26,7 +26,7 @@ import { usePromoteRc } from './hooks/usePromoteRc';
interface PromoteRcBodyProps {
rcRelease: NonNullable<GetLatestReleaseResult['latestRelease']>;
onSuccess?: ComponentConfigPromoteRc['onSuccess'];
onSuccess?: ComponentConfig<PromoteRcOnSuccessArgs>['onSuccess'];
}
export const PromoteRcBody = ({ rcRelease, onSuccess }: PromoteRcBodyProps) => {
@@ -16,7 +16,11 @@
import { useState, useEffect } from 'react';
import { useAsync, useAsyncFn } from 'react-use';
import { CardHook, ComponentConfigPromoteRc } from '../../../types/types';
import {
CardHook,
ComponentConfig,
PromoteRcOnSuccessArgs,
} from '../../../types/types';
import { GetLatestReleaseResult } from '../../../api/GitReleaseClient';
import { gitReleaseManagerApiRef } from '../../../api/serviceApiRef';
@@ -27,17 +31,17 @@ import { useResponseSteps } from '../../../hooks/useResponseSteps';
import { useUserContext } from '../../../contexts/UserContext';
import { useApi } from '@backstage/core-plugin-api';
interface PromoteRc {
export interface UsePromoteRc {
rcRelease: NonNullable<GetLatestReleaseResult['latestRelease']>;
releaseVersion: string;
onSuccess?: ComponentConfigPromoteRc['onSuccess'];
onSuccess?: ComponentConfig<PromoteRcOnSuccessArgs>['onSuccess'];
}
export function usePromoteRc({
rcRelease,
releaseVersion,
onSuccess,
}: PromoteRc): CardHook<void> {
}: UsePromoteRc): CardHook<void> {
const pluginApiClient = useApi(gitReleaseManagerApiRef);
const { user } = useUserContext();
const { project } = useProjectContext();
@@ -170,12 +174,16 @@ export function usePromoteRc({
try {
await onSuccess?.({
gitReleaseUrl: promotedReleaseRes.value.htmlUrl,
input: {
rcRelease,
releaseVersion,
},
gitReleaseName: promotedReleaseRes.value.name,
previousTagUrl: rcRelease.htmlUrl,
gitReleaseUrl: promotedReleaseRes.value.htmlUrl,
previousTag: rcRelease.tagName,
updatedTagUrl: promotedReleaseRes.value.htmlUrl,
previousTagUrl: rcRelease.htmlUrl,
updatedTag: promotedReleaseRes.value.tagName,
updatedTagUrl: promotedReleaseRes.value.htmlUrl,
});
} catch (error) {
asyncCatcher(error);
+15 -11
View File
@@ -14,21 +14,26 @@
* limitations under the License.
*/
export type ComponentConfig<Args> = {
import { UseCreateReleaseCandidate } from '../features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate';
import { UsePatch } from '../features/Patch/hooks/usePatch';
import { UsePromoteRc } from '../features/PromoteRc/hooks/usePromoteRc';
export type ComponentConfig<OnSuccessArgs> = {
omit?: boolean;
onSuccess?: (args: Args) => Promise<void> | void;
onSuccess?: (args: OnSuccessArgs) => Promise<void> | void;
};
interface CreateRcOnSuccessArgs {
gitReleaseUrl: string;
gitReleaseName: string | null;
export interface CreateRcOnSuccessArgs {
input: Omit<UseCreateReleaseCandidate, 'onSuccess'>;
comparisonUrl: string;
previousTag?: string;
createdTag: string;
gitReleaseName: string | null;
gitReleaseUrl: string;
previousTag?: string;
}
export type ComponentConfigCreateRc = ComponentConfig<CreateRcOnSuccessArgs>;
interface PromoteRcOnSuccessArgs {
export interface PromoteRcOnSuccessArgs {
input: Omit<UsePromoteRc, 'onSuccess'>;
gitReleaseUrl: string;
gitReleaseName: string | null;
previousTagUrl: string;
@@ -36,9 +41,9 @@ interface PromoteRcOnSuccessArgs {
updatedTagUrl: string;
updatedTag: string;
}
export type ComponentConfigPromoteRc = ComponentConfig<PromoteRcOnSuccessArgs>;
interface PatchOnSuccessArgs {
export interface PatchOnSuccessArgs {
input: Omit<UsePatch, 'onSuccess'>;
updatedReleaseUrl: string;
updatedReleaseName: string | null;
previousTag: string;
@@ -46,7 +51,6 @@ interface PatchOnSuccessArgs {
patchCommitUrl: string;
patchCommitMessage: string;
}
export type ComponentConfigPatch = ComponentConfig<PatchOnSuccessArgs>;
export interface ResponseStep {
message: string | React.ReactNode;