Merge pull request #19616 from awanlin/topic/refactor-annotation-values
Refactored annotation values
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-azure-devops': patch
|
||||
---
|
||||
|
||||
Consolidated getting the annotation values into a single function to help with future changes
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
EntityAzurePullRequestsContent,
|
||||
isAzureDevOpsAvailable,
|
||||
isAzurePipelinesAvailable,
|
||||
EntityAzureReadmeCard,
|
||||
} from '@backstage/plugin-azure-devops';
|
||||
import {
|
||||
isOctopusDeployAvailable,
|
||||
@@ -415,6 +416,14 @@ const overviewContent = (
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isAzureDevOpsAvailable}>
|
||||
<Grid item md={6}>
|
||||
<EntityAzureReadmeCard />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
<Grid item md={2}>
|
||||
<InfoCard title="Rate this entity">
|
||||
<LikeDislikeButtons />
|
||||
|
||||
+2
-2
@@ -16,14 +16,14 @@
|
||||
|
||||
import { BuildTable } from '../BuildTable/BuildTable';
|
||||
import React from 'react';
|
||||
import { getAnnotationFromEntity } from '../../utils/getAnnotationFromEntity';
|
||||
import { getAnnotationValuesFromEntity } from '../../utils/getAnnotationValuesFromEntity';
|
||||
import { useBuildRuns } from '../../hooks/useBuildRuns';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
|
||||
export const EntityPageAzurePipelines = (props: { defaultLimit?: number }) => {
|
||||
const { entity } = useEntity();
|
||||
|
||||
const { project, repo, definition } = getAnnotationFromEntity(entity);
|
||||
const { project, repo, definition } = getAnnotationValuesFromEntity(entity);
|
||||
|
||||
const { items, loading, error } = useBuildRuns(
|
||||
project,
|
||||
|
||||
@@ -23,11 +23,9 @@ import {
|
||||
ErrorPanel,
|
||||
} from '@backstage/core-components';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { useProjectRepoFromEntity } from '../../hooks';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import React from 'react';
|
||||
import { azureDevOpsApiRef } from '../../api';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
|
||||
import { useReadme } from '../../hooks';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
readMe: {
|
||||
@@ -85,18 +83,9 @@ const ReadmeCardError = ({ error }: ErrorProps) => {
|
||||
|
||||
export const ReadmeCard = (props: Props) => {
|
||||
const classes = useStyles();
|
||||
const api = useApi(azureDevOpsApiRef);
|
||||
const { entity } = useEntity();
|
||||
const { project, repo } = useProjectRepoFromEntity(entity);
|
||||
|
||||
const { loading, error, value } = useAsync(
|
||||
() =>
|
||||
api.getReadme({
|
||||
project,
|
||||
repo,
|
||||
}),
|
||||
[api, project, repo, entity],
|
||||
);
|
||||
const { loading, error, item: value } = useReadme(entity);
|
||||
|
||||
if (loading) {
|
||||
return <Progress />;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
export const AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION =
|
||||
'dev.azure.com/build-definition';
|
||||
export const AZURE_DEVOPS_HOST_ORG_ANNOTATION = 'dev.azure.com/host-org';
|
||||
export const AZURE_DEVOPS_PROJECT_ANNOTATION = 'dev.azure.com/project';
|
||||
export const AZURE_DEVOPS_REPO_ANNOTATION = 'dev.azure.com/project-repo';
|
||||
export const AZURE_DEVOPS_DEFAULT_TOP: number = 10;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
export * from './useAllTeams';
|
||||
export * from './useDashboardPullRequests';
|
||||
export * from './useProjectRepoFromEntity';
|
||||
export * from './usePullRequests';
|
||||
export * from './useRepoBuilds';
|
||||
export * from './useUserEmail';
|
||||
export * from './useUserTeamIds';
|
||||
export * from './useReadme';
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { useGitTags } from './useGitTags';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { GitTag } from '@backstage/plugin-azure-devops-common';
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { AzureDevOpsApi, azureDevOpsApiRef } from '../api';
|
||||
|
||||
describe('useGitTags', () => {
|
||||
const azureDevOpsApiMock = {
|
||||
getGitTags: jest.fn(),
|
||||
};
|
||||
const azureDevOpsApi =
|
||||
azureDevOpsApiMock as Partial<AzureDevOpsApi> as AzureDevOpsApi;
|
||||
|
||||
const Wrapper = (props: { children?: React.ReactNode }) => (
|
||||
<TestApiProvider apis={[[azureDevOpsApiRef, azureDevOpsApi]]}>
|
||||
{props.children}
|
||||
</TestApiProvider>
|
||||
);
|
||||
|
||||
it('should provide an array of GitTag', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'projectName/repoName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const tags: GitTag[] = [
|
||||
{
|
||||
objectId: 'tag-1',
|
||||
peeledObjectId: 'tag-1',
|
||||
name: 'tag-1',
|
||||
createdBy: 'awanlin',
|
||||
link: 'https://dev.azure.com/org/project/repo',
|
||||
commitLink: 'https://dev.azure.com/org/project/repo/commit-sha-1',
|
||||
},
|
||||
{
|
||||
objectId: 'tag-2',
|
||||
peeledObjectId: 'tag-2',
|
||||
name: 'tag-2',
|
||||
createdBy: 'awanlin',
|
||||
link: 'https://dev.azure.com/org/project/repo',
|
||||
commitLink: 'https://dev.azure.com/org/project/repo/commit-sha-2',
|
||||
},
|
||||
{
|
||||
objectId: 'tag-3',
|
||||
peeledObjectId: 'tag-3',
|
||||
name: 'tag-3',
|
||||
createdBy: 'awanlin',
|
||||
link: 'https://dev.azure.com/org/project/repo',
|
||||
commitLink: 'https://dev.azure.com/org/project/repo/commit-sha-3',
|
||||
},
|
||||
];
|
||||
azureDevOpsApiMock.getGitTags.mockResolvedValue({ items: tags });
|
||||
const { result } = renderHook(() => useGitTags(entity), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
expect(result.current.loading).toEqual(true);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current).toEqual({
|
||||
error: undefined,
|
||||
items: tags,
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return throw when annotation missing', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
renderHook(() => useGitTags(entity), {
|
||||
wrapper: Wrapper,
|
||||
}),
|
||||
).toThrow('Value for annotation "dev.azure.com/project" was not found');
|
||||
});
|
||||
|
||||
it('should return throw when annotation invalid', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'fake',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
renderHook(() => useGitTags(entity), {
|
||||
wrapper: Wrapper,
|
||||
}),
|
||||
).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: <project-name>/<repo-name>, found: "fake"',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -20,7 +20,7 @@ import { Entity } from '@backstage/catalog-model';
|
||||
import { azureDevOpsApiRef } from '../api';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { useProjectRepoFromEntity } from './useProjectRepoFromEntity';
|
||||
import { getAnnotationValuesFromEntity } from '../utils';
|
||||
|
||||
export function useGitTags(entity: Entity): {
|
||||
items?: GitTag[];
|
||||
@@ -28,10 +28,10 @@ export function useGitTags(entity: Entity): {
|
||||
error?: Error;
|
||||
} {
|
||||
const api = useApi(azureDevOpsApiRef);
|
||||
const { project, repo } = useProjectRepoFromEntity(entity);
|
||||
const { project, repo } = getAnnotationValuesFromEntity(entity);
|
||||
|
||||
const { value, loading, error } = useAsync(() => {
|
||||
return api.getGitTags(project, repo);
|
||||
const { value, loading, error } = useAsync(async () => {
|
||||
return await api.getGitTags(project, repo as string);
|
||||
}, [api, project, repo]);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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 { Entity } from '@backstage/catalog-model';
|
||||
import { AZURE_DEVOPS_REPO_ANNOTATION } from '../constants';
|
||||
|
||||
export function useProjectRepoFromEntity(entity: Entity): {
|
||||
project: string;
|
||||
repo: string;
|
||||
} {
|
||||
const [project, repo] = (
|
||||
entity.metadata.annotations?.[AZURE_DEVOPS_REPO_ANNOTATION] ?? ''
|
||||
).split('/');
|
||||
|
||||
if (!project && !repo) {
|
||||
throw new Error(
|
||||
'Value for annotation dev.azure.com/project-repo was not in the correct format: <project-name>/<repo-name>',
|
||||
);
|
||||
}
|
||||
|
||||
if (!project) {
|
||||
throw new Error(
|
||||
'Project Name for annotation dev.azure.com/project-repo was not found; expected format is: <project-name>/<repo-name>',
|
||||
);
|
||||
}
|
||||
|
||||
if (!repo) {
|
||||
throw new Error(
|
||||
'Repo Name for annotation dev.azure.com/project-repo was not found; expected format is: <project-name>/<repo-name>',
|
||||
);
|
||||
}
|
||||
|
||||
return { project, repo };
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { PullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { AzureDevOpsApi, azureDevOpsApiRef } from '../api';
|
||||
import { usePullRequests } from './usePullRequests';
|
||||
|
||||
describe('usePullRequests', () => {
|
||||
const azureDevOpsApiMock = {
|
||||
getPullRequests: jest.fn(),
|
||||
};
|
||||
const azureDevOpsApi =
|
||||
azureDevOpsApiMock as Partial<AzureDevOpsApi> as AzureDevOpsApi;
|
||||
|
||||
const Wrapper = (props: { children?: React.ReactNode }) => (
|
||||
<TestApiProvider apis={[[azureDevOpsApiRef, azureDevOpsApi]]}>
|
||||
{props.children}
|
||||
</TestApiProvider>
|
||||
);
|
||||
|
||||
it('should provide an array of PullRequest', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'projectName/repoName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const pullRequests: PullRequest[] = [
|
||||
{
|
||||
pullRequestId: 1,
|
||||
repoName: 'repo',
|
||||
title: 'title-1',
|
||||
createdBy: 'awanlin',
|
||||
link: 'https://dev.azure.com/org/project/repo',
|
||||
},
|
||||
{
|
||||
pullRequestId: 2,
|
||||
repoName: 'repo',
|
||||
title: 'title-2',
|
||||
createdBy: 'awanlin',
|
||||
link: 'https://dev.azure.com/org/project/repo',
|
||||
},
|
||||
{
|
||||
pullRequestId: 3,
|
||||
repoName: 'repo',
|
||||
title: 'title-3',
|
||||
createdBy: 'awanlin',
|
||||
link: 'https://dev.azure.com/org/project/repo',
|
||||
},
|
||||
];
|
||||
azureDevOpsApiMock.getPullRequests.mockResolvedValue({
|
||||
items: pullRequests,
|
||||
});
|
||||
const { result } = renderHook(() => usePullRequests(entity), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
expect(result.current.loading).toEqual(true);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current).toEqual({
|
||||
error: undefined,
|
||||
items: pullRequests,
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return throw when annotation missing', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
renderHook(() => usePullRequests(entity), {
|
||||
wrapper: Wrapper,
|
||||
}),
|
||||
).toThrow('Value for annotation "dev.azure.com/project" was not found');
|
||||
});
|
||||
|
||||
it('should return throw when annotation invalid', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'fake',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
renderHook(() => usePullRequests(entity), {
|
||||
wrapper: Wrapper,
|
||||
}),
|
||||
).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: <project-name>/<repo-name>, found: "fake"',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -25,7 +25,7 @@ import { Entity } from '@backstage/catalog-model';
|
||||
import { azureDevOpsApiRef } from '../api';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { useProjectRepoFromEntity } from './useProjectRepoFromEntity';
|
||||
import { getAnnotationValuesFromEntity } from '../utils';
|
||||
|
||||
export function usePullRequests(
|
||||
entity: Entity,
|
||||
@@ -44,10 +44,10 @@ export function usePullRequests(
|
||||
};
|
||||
|
||||
const api = useApi(azureDevOpsApiRef);
|
||||
const { project, repo } = useProjectRepoFromEntity(entity);
|
||||
const { project, repo } = getAnnotationValuesFromEntity(entity);
|
||||
|
||||
const { value, loading, error } = useAsync(() => {
|
||||
return api.getPullRequests(project, repo, options);
|
||||
const { value, loading, error } = useAsync(async () => {
|
||||
return await api.getPullRequests(project, repo as string, options);
|
||||
}, [api, project, repo, top, status]);
|
||||
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { Readme } from '@backstage/plugin-azure-devops-common';
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { AzureDevOpsApi, azureDevOpsApiRef } from '../api';
|
||||
import { useReadme } from './useReadme';
|
||||
|
||||
describe('useReadme', () => {
|
||||
const azureDevOpsApiMock = {
|
||||
getReadme: jest.fn(),
|
||||
};
|
||||
const azureDevOpsApi =
|
||||
azureDevOpsApiMock as Partial<AzureDevOpsApi> as AzureDevOpsApi;
|
||||
|
||||
const Wrapper = (props: { children?: React.ReactNode }) => (
|
||||
<TestApiProvider apis={[[azureDevOpsApiRef, azureDevOpsApi]]}>
|
||||
{props.children}
|
||||
</TestApiProvider>
|
||||
);
|
||||
|
||||
it('should provide a Readme', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'projectName/repoName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const readme: Readme = {
|
||||
url: 'https://dev.azure.com/org/project/repo',
|
||||
content: 'This is some fake README content',
|
||||
};
|
||||
azureDevOpsApiMock.getReadme.mockResolvedValue({
|
||||
item: readme,
|
||||
});
|
||||
const { result } = renderHook(() => useReadme(entity), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
expect(result.current.loading).toEqual(true);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.item).toEqual({
|
||||
item: readme,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return throw when annotation missing', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
renderHook(() => useReadme(entity), {
|
||||
wrapper: Wrapper,
|
||||
}),
|
||||
).toThrow('Value for annotation "dev.azure.com/project" was not found');
|
||||
});
|
||||
|
||||
it('should return throw when annotation invalid', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'fake',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
renderHook(() => useReadme(entity), {
|
||||
wrapper: Wrapper,
|
||||
}),
|
||||
).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: <project-name>/<repo-name>, found: "fake"',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 { Readme } from '@backstage/plugin-azure-devops-common';
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { azureDevOpsApiRef } from '../api';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { getAnnotationValuesFromEntity } from '../utils';
|
||||
|
||||
export function useReadme(entity: Entity): {
|
||||
item?: Readme;
|
||||
loading: boolean;
|
||||
error?: Error;
|
||||
} {
|
||||
const api = useApi(azureDevOpsApiRef);
|
||||
const { project, repo } = getAnnotationValuesFromEntity(entity);
|
||||
|
||||
const { value, loading, error } = useAsync(async () => {
|
||||
return await api.getReadme({ project, repo: repo as string });
|
||||
}, [api, project, repo]);
|
||||
|
||||
return {
|
||||
item: value,
|
||||
loading,
|
||||
error,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { RepoBuild } from '@backstage/plugin-azure-devops-common';
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { AzureDevOpsApi, azureDevOpsApiRef } from '../api';
|
||||
import { useRepoBuilds } from './useRepoBuilds';
|
||||
|
||||
describe('useRepoBuilds', () => {
|
||||
const azureDevOpsApiMock = {
|
||||
getRepoBuilds: jest.fn(),
|
||||
};
|
||||
const azureDevOpsApi =
|
||||
azureDevOpsApiMock as Partial<AzureDevOpsApi> as AzureDevOpsApi;
|
||||
|
||||
const Wrapper = (props: { children?: React.ReactNode }) => (
|
||||
<TestApiProvider apis={[[azureDevOpsApiRef, azureDevOpsApi]]}>
|
||||
{props.children}
|
||||
</TestApiProvider>
|
||||
);
|
||||
|
||||
it('should provide an array of RepoBuild', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'projectName/repoName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const repoBuilds: RepoBuild[] = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'title-1',
|
||||
source: 'awanlin',
|
||||
link: 'https://dev.azure.com/org/project/repo',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'title-2',
|
||||
source: 'awanlin',
|
||||
link: 'https://dev.azure.com/org/project/repo',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'title-3',
|
||||
source: 'awanlin',
|
||||
link: 'https://dev.azure.com/org/project/repo',
|
||||
},
|
||||
];
|
||||
azureDevOpsApiMock.getRepoBuilds.mockResolvedValue({
|
||||
items: repoBuilds,
|
||||
});
|
||||
const { result } = renderHook(() => useRepoBuilds(entity), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
expect(result.current.loading).toEqual(true);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current).toEqual({
|
||||
error: undefined,
|
||||
items: repoBuilds,
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return throw when annotation missing', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
renderHook(() => useRepoBuilds(entity), {
|
||||
wrapper: Wrapper,
|
||||
}),
|
||||
).toThrow('Value for annotation "dev.azure.com/project" was not found');
|
||||
});
|
||||
|
||||
it('should return throw when annotation invalid', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'fake',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
renderHook(() => useRepoBuilds(entity), {
|
||||
wrapper: Wrapper,
|
||||
}),
|
||||
).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: <project-name>/<repo-name>, found: "fake"',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -24,7 +24,7 @@ import { Entity } from '@backstage/catalog-model';
|
||||
import { azureDevOpsApiRef } from '../api';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { useProjectRepoFromEntity } from './useProjectRepoFromEntity';
|
||||
import { getAnnotationValuesFromEntity } from '../utils';
|
||||
|
||||
export function useRepoBuilds(
|
||||
entity: Entity,
|
||||
@@ -40,10 +40,10 @@ export function useRepoBuilds(
|
||||
};
|
||||
|
||||
const api = useApi(azureDevOpsApiRef);
|
||||
const { project, repo } = useProjectRepoFromEntity(entity);
|
||||
const { project, repo } = getAnnotationValuesFromEntity(entity);
|
||||
|
||||
const { value, loading, error } = useAsync(() => {
|
||||
return api.getRepoBuilds(project, repo, options);
|
||||
const { value, loading, error } = useAsync(async () => {
|
||||
return await api.getRepoBuilds(project, repo as string, options);
|
||||
}, [api, project, repo, entity]);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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 {
|
||||
AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION,
|
||||
AZURE_DEVOPS_PROJECT_ANNOTATION,
|
||||
AZURE_DEVOPS_REPO_ANNOTATION,
|
||||
} from '../constants';
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
export function getAnnotationFromEntity(entity: Entity): {
|
||||
project: string;
|
||||
repo?: string;
|
||||
definition?: string;
|
||||
} {
|
||||
const annotation =
|
||||
entity.metadata.annotations?.[AZURE_DEVOPS_REPO_ANNOTATION];
|
||||
if (annotation) {
|
||||
const { project, repo } = getProjectRepo(annotation);
|
||||
const definition = undefined;
|
||||
return { project, repo, definition };
|
||||
}
|
||||
|
||||
const project =
|
||||
entity.metadata.annotations?.[AZURE_DEVOPS_PROJECT_ANNOTATION];
|
||||
if (!project) {
|
||||
throw new Error('Value for annotation dev.azure.com/project was not found');
|
||||
}
|
||||
|
||||
const definition =
|
||||
entity.metadata.annotations?.[AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION];
|
||||
if (!definition) {
|
||||
throw new Error(
|
||||
'Value for annotation dev.azure.com/build-definition was not found',
|
||||
);
|
||||
}
|
||||
|
||||
const repo = undefined;
|
||||
return { project, repo, definition };
|
||||
}
|
||||
|
||||
function getProjectRepo(annotation: string): {
|
||||
project: string;
|
||||
repo: string;
|
||||
} {
|
||||
const [project, repo] = annotation.split('/');
|
||||
|
||||
if (!project && !repo) {
|
||||
throw new Error(
|
||||
'Value for annotation dev.azure.com/project-repo was not in the correct format: <project-name>/<repo-name>',
|
||||
);
|
||||
}
|
||||
|
||||
return { project, repo };
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* 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 { Entity } from '@backstage/catalog-model';
|
||||
import { getAnnotationValuesFromEntity } from './getAnnotationValuesFromEntity';
|
||||
|
||||
describe('getAnnotationValuesFromEntity', () => {
|
||||
describe('with valid project-repo annotation', () => {
|
||||
it('should return project and repo', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'projectName/repoName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const values = getAnnotationValuesFromEntity(entity);
|
||||
expect(values).toEqual({
|
||||
project: 'projectName',
|
||||
repo: 'repoName',
|
||||
definition: undefined,
|
||||
host: undefined,
|
||||
org: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with invalid project-repo annotation', () => {
|
||||
it('should throw incorrect format error', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'project',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const test = () => {
|
||||
return getAnnotationValuesFromEntity(entity);
|
||||
};
|
||||
|
||||
expect(test).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: <project-name>/<repo-name>, found: "project"',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with project-repo annotation missing project', () => {
|
||||
it('should throw missing project error', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': '/repo',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const test = () => {
|
||||
return getAnnotationValuesFromEntity(entity);
|
||||
};
|
||||
|
||||
expect(test).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: <project-name>/<repo-name>, found: "/repo"',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with project-repo annotation missing repo', () => {
|
||||
it('should throw missing repo error', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'project/',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const test = () => {
|
||||
return getAnnotationValuesFromEntity(entity);
|
||||
};
|
||||
|
||||
expect(test).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: <project-name>/<repo-name>, found: "project/"',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with valid project and build-definition annotations', () => {
|
||||
it('should return project and definition', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-build-definition',
|
||||
annotations: {
|
||||
'dev.azure.com/project': 'projectName',
|
||||
'dev.azure.com/build-definition': 'buildDefinitionName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const values = getAnnotationValuesFromEntity(entity);
|
||||
expect(values).toEqual({
|
||||
project: 'projectName',
|
||||
repo: undefined,
|
||||
definition: 'buildDefinitionName',
|
||||
host: undefined,
|
||||
org: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with only project annotation', () => {
|
||||
it('should should throw annotation not found error', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project',
|
||||
annotations: {
|
||||
'dev.azure.com/project': 'projectName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const test = () => {
|
||||
return getAnnotationValuesFromEntity(entity);
|
||||
};
|
||||
|
||||
expect(test).toThrow(
|
||||
'Value for annotation "dev.azure.com/build-definition" was not found',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with only build-definition annotation', () => {
|
||||
it('should should throw annotation not found error', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'build-definition',
|
||||
annotations: {
|
||||
'dev.azure.com/build-definition': 'buildDefinitionName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const test = () => {
|
||||
return getAnnotationValuesFromEntity(entity);
|
||||
};
|
||||
|
||||
expect(test).toThrow(
|
||||
'Value for annotation "dev.azure.com/project" was not found',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with valid project-repo and host-org annotations', () => {
|
||||
it('should return project, repo, host, and org', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-repo',
|
||||
annotations: {
|
||||
'dev.azure.com/project-repo': 'projectName/repoName',
|
||||
'dev.azure.com/host-org': 'hostName/organizationName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const values = getAnnotationValuesFromEntity(entity);
|
||||
expect(values).toEqual({
|
||||
project: 'projectName',
|
||||
repo: 'repoName',
|
||||
definition: undefined,
|
||||
host: 'hostName',
|
||||
org: 'organizationName',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with valid project, build-definition, and host-org annotations', () => {
|
||||
it('should return project, definition, host and org', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'project-build-definition',
|
||||
annotations: {
|
||||
'dev.azure.com/project': 'projectName',
|
||||
'dev.azure.com/build-definition': 'buildDefinitionName',
|
||||
'dev.azure.com/host-org': 'hostName/organizationName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const values = getAnnotationValuesFromEntity(entity);
|
||||
expect(values).toEqual({
|
||||
project: 'projectName',
|
||||
repo: undefined,
|
||||
definition: 'buildDefinitionName',
|
||||
host: 'hostName',
|
||||
org: 'organizationName',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with invalid host-org annotation', () => {
|
||||
it('should throw incorrect format error', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'host-org',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': 'host',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const test = () => {
|
||||
return getAnnotationValuesFromEntity(entity);
|
||||
};
|
||||
|
||||
expect(test).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/host-org"; expected format is: <host-name>/<organization-name>, found: "host"',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with host-org annotation missing host', () => {
|
||||
it('should throw missing project error', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'host-org',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': '/org',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const test = () => {
|
||||
return getAnnotationValuesFromEntity(entity);
|
||||
};
|
||||
|
||||
expect(test).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/host-org"; expected format is: <host-name>/<organization-name>, found: "/org"',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with host-org annotation missing org', () => {
|
||||
it('should throw missing repo error', () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'host-org',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': 'host/',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const test = () => {
|
||||
return getAnnotationValuesFromEntity(entity);
|
||||
};
|
||||
|
||||
expect(test).toThrow(
|
||||
'Invalid value for annotation "dev.azure.com/host-org"; expected format is: <host-name>/<organization-name>, found: "host/"',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 {
|
||||
AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION,
|
||||
AZURE_DEVOPS_HOST_ORG_ANNOTATION,
|
||||
AZURE_DEVOPS_PROJECT_ANNOTATION,
|
||||
AZURE_DEVOPS_REPO_ANNOTATION,
|
||||
} from '../constants';
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
export function getAnnotationValuesFromEntity(entity: Entity): {
|
||||
project: string;
|
||||
repo?: string;
|
||||
definition?: string;
|
||||
host?: string;
|
||||
org?: string;
|
||||
} {
|
||||
const { host, org } = getHostOrg(entity.metadata.annotations);
|
||||
|
||||
const projectRepoValues = getProjectRepo(entity.metadata.annotations);
|
||||
if (projectRepoValues.project && projectRepoValues.repo) {
|
||||
return {
|
||||
project: projectRepoValues.project,
|
||||
repo: projectRepoValues.repo,
|
||||
host,
|
||||
org,
|
||||
};
|
||||
}
|
||||
|
||||
const project =
|
||||
entity.metadata.annotations?.[AZURE_DEVOPS_PROJECT_ANNOTATION];
|
||||
if (!project) {
|
||||
throw new Error(
|
||||
`Value for annotation "${AZURE_DEVOPS_PROJECT_ANNOTATION}" was not found`,
|
||||
);
|
||||
}
|
||||
|
||||
const definition =
|
||||
entity.metadata.annotations?.[AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION];
|
||||
if (!definition) {
|
||||
throw new Error(
|
||||
`Value for annotation "${AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION}" was not found`,
|
||||
);
|
||||
}
|
||||
return { project, definition, host, org };
|
||||
}
|
||||
|
||||
function getProjectRepo(annotations?: Record<string, string>): {
|
||||
project?: string;
|
||||
repo?: string;
|
||||
} {
|
||||
const annotation = annotations?.[AZURE_DEVOPS_REPO_ANNOTATION];
|
||||
if (!annotation) {
|
||||
return { project: undefined, repo: undefined };
|
||||
}
|
||||
|
||||
if (annotation.includes('/')) {
|
||||
const [project, repo] = annotation.split('/');
|
||||
if (project && repo) {
|
||||
return { project, repo };
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Invalid value for annotation "${AZURE_DEVOPS_REPO_ANNOTATION}"; expected format is: <project-name>/<repo-name>, found: "${annotation}"`,
|
||||
);
|
||||
}
|
||||
|
||||
function getHostOrg(annotations?: Record<string, string>): {
|
||||
host?: string;
|
||||
org?: string;
|
||||
} {
|
||||
const annotation = annotations?.[AZURE_DEVOPS_HOST_ORG_ANNOTATION];
|
||||
if (!annotation) {
|
||||
return { host: undefined, org: undefined };
|
||||
}
|
||||
|
||||
if (annotation.includes('/')) {
|
||||
const [host, org] = annotation.split('/');
|
||||
if (host && org) {
|
||||
return { host, org };
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Invalid value for annotation "${AZURE_DEVOPS_HOST_ORG_ANNOTATION}"; expected format is: <host-name>/<organization-name>, found: "${annotation}"`,
|
||||
);
|
||||
}
|
||||
@@ -17,4 +17,4 @@
|
||||
export * from './arrayHas';
|
||||
export * from './equalsIgnoreCase';
|
||||
export * from './getDurationFromDates';
|
||||
export * from './getAnnotationFromEntity';
|
||||
export * from './getAnnotationValuesFromEntity';
|
||||
|
||||
Reference in New Issue
Block a user