Refactored annotation values
Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com>
This commit is contained in:
committed by
Andre Wanlin
parent
5001ce8873
commit
361bb34d8e
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-azure-devops': patch
|
||||
---
|
||||
|
||||
Consolidated getting the annotation values into a single function to help with future changes
|
||||
+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,11 @@ 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 { getAnnotationValuesFromEntity } from '../../utils';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
readMe: {
|
||||
@@ -87,16 +87,14 @@ export const ReadmeCard = (props: Props) => {
|
||||
const classes = useStyles();
|
||||
const api = useApi(azureDevOpsApiRef);
|
||||
const { entity } = useEntity();
|
||||
const { project, repo } = useProjectRepoFromEntity(entity);
|
||||
const { project, repo } = getAnnotationValuesFromEntity(entity);
|
||||
|
||||
const { loading, error, value } = useAsync(
|
||||
() =>
|
||||
api.getReadme({
|
||||
project,
|
||||
repo,
|
||||
}),
|
||||
[api, project, repo, entity],
|
||||
);
|
||||
const { loading, error, value } = useAsync(async () => {
|
||||
if (repo) {
|
||||
return await api.getReadme({ project, repo });
|
||||
}
|
||||
return undefined;
|
||||
}, [api, project, repo, entity]);
|
||||
|
||||
if (loading) {
|
||||
return <Progress />;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
export const AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION =
|
||||
'dev.azure.com/build-definition';
|
||||
export const AZURE_DEVOPS_ORGANIZATION_ANNOTATION =
|
||||
'dev.azure.com/organization';
|
||||
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,7 +16,6 @@
|
||||
|
||||
export * from './useAllTeams';
|
||||
export * from './useDashboardPullRequests';
|
||||
export * from './useProjectRepoFromEntity';
|
||||
export * from './usePullRequests';
|
||||
export * from './useRepoBuilds';
|
||||
export * from './useUserEmail';
|
||||
|
||||
@@ -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,13 @@ 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 () => {
|
||||
if (repo) {
|
||||
return await api.getGitTags(project, repo);
|
||||
}
|
||||
return undefined;
|
||||
}, [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 };
|
||||
}
|
||||
@@ -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,13 @@ 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 () => {
|
||||
if (repo) {
|
||||
return await api.getPullRequests(project, repo, options);
|
||||
}
|
||||
return undefined;
|
||||
}, [api, project, repo, top, status]);
|
||||
|
||||
return {
|
||||
|
||||
@@ -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,13 @@ 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 () => {
|
||||
if (repo) {
|
||||
return await api.getRepoBuilds(project, repo, options);
|
||||
}
|
||||
return undefined;
|
||||
}, [api, project, repo, entity]);
|
||||
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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 { project, repo, definition, org } =
|
||||
getAnnotationValuesFromEntity(entity);
|
||||
expect(project).toEqual('projectName');
|
||||
expect(repo).toEqual('repoName');
|
||||
expect(definition).toEqual(undefined);
|
||||
expect(org).toEqual(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(
|
||||
'Value for annotation dev.azure.com/project-repo was not in the correct format: <project-name>/<repo-name>',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
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(
|
||||
'Project Name for annotation dev.azure.com/project-repo was not found; expected format is: <project-name>/<repo-name>',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
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(
|
||||
'Repo Name for annotation dev.azure.com/project-repo was not found; expected format is: <project-name>/<repo-name>',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
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 { project, repo, definition, org } =
|
||||
getAnnotationValuesFromEntity(entity);
|
||||
expect(project).toEqual('projectName');
|
||||
expect(repo).toEqual(undefined);
|
||||
expect(definition).toEqual('buildDefinitionName');
|
||||
expect(org).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with only project annotation', () => {
|
||||
it('should return project and definition', () => {
|
||||
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 return project and definition', () => {
|
||||
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 org annotations', () => {
|
||||
it('should return project, repo, 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/organization': 'organizationName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const { project, repo, definition, org } =
|
||||
getAnnotationValuesFromEntity(entity);
|
||||
expect(project).toEqual('projectName');
|
||||
expect(repo).toEqual('repoName');
|
||||
expect(definition).toEqual(undefined);
|
||||
expect(org).toEqual('organizationName');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with valid project, build-definition, and org annotations', () => {
|
||||
it('should return project, definition, 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/organization': 'organizationName',
|
||||
},
|
||||
},
|
||||
};
|
||||
const { project, repo, definition, org } =
|
||||
getAnnotationValuesFromEntity(entity);
|
||||
expect(project).toEqual('projectName');
|
||||
expect(repo).toEqual(undefined);
|
||||
expect(definition).toEqual('buildDefinitionName');
|
||||
expect(org).toEqual('organizationName');
|
||||
});
|
||||
});
|
||||
});
|
||||
+23
-6
@@ -16,23 +16,28 @@
|
||||
|
||||
import {
|
||||
AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION,
|
||||
AZURE_DEVOPS_ORGANIZATION_ANNOTATION,
|
||||
AZURE_DEVOPS_PROJECT_ANNOTATION,
|
||||
AZURE_DEVOPS_REPO_ANNOTATION,
|
||||
} from '../constants';
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
export function getAnnotationFromEntity(entity: Entity): {
|
||||
export function getAnnotationValuesFromEntity(entity: Entity): {
|
||||
project: string;
|
||||
repo?: string;
|
||||
definition?: string;
|
||||
org?: string;
|
||||
} {
|
||||
const org =
|
||||
entity.metadata.annotations?.[AZURE_DEVOPS_ORGANIZATION_ANNOTATION];
|
||||
|
||||
const annotation =
|
||||
entity.metadata.annotations?.[AZURE_DEVOPS_REPO_ANNOTATION];
|
||||
if (annotation) {
|
||||
const { project, repo } = getProjectRepo(annotation);
|
||||
const definition = undefined;
|
||||
return { project, repo, definition };
|
||||
return { project, repo, definition, org };
|
||||
}
|
||||
|
||||
const project =
|
||||
@@ -50,20 +55,32 @@ export function getAnnotationFromEntity(entity: Entity): {
|
||||
}
|
||||
|
||||
const repo = undefined;
|
||||
return { project, repo, definition };
|
||||
return { project, repo, definition, org };
|
||||
}
|
||||
|
||||
function getProjectRepo(annotation: string): {
|
||||
project: string;
|
||||
repo: string;
|
||||
} {
|
||||
const [project, repo] = annotation.split('/');
|
||||
|
||||
if (!project && !repo) {
|
||||
if (!annotation.includes('/')) {
|
||||
throw new Error(
|
||||
'Value for annotation dev.azure.com/project-repo was not in the correct format: <project-name>/<repo-name>',
|
||||
);
|
||||
}
|
||||
|
||||
const [project, repo] = annotation.split('/');
|
||||
|
||||
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 };
|
||||
}
|
||||
@@ -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