Merge pull request #17422 from rr-wfm/feature/octopus-spaces-support

Add support for spaces to the Octopus Deploy plugin
This commit is contained in:
Fredrik Adelöw
2023-05-02 14:12:05 +02:00
committed by GitHub
11 changed files with 96 additions and 30 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-octopus-deploy': minor
---
Added support for Octopus Deploy spaces. The octopus.com/project-id annotation can now (optionally) be prefixed by a space identifier, for example. Spaces-1/Projects-102.
Also note that some of this plugins exported API's have changed to accommodate this change, changing from separate arguments to a single object.
+1
View File
@@ -47,6 +47,7 @@
"@backstage/plugin-microsoft-calendar": "workspace:^",
"@backstage/plugin-newrelic": "workspace:^",
"@backstage/plugin-newrelic-dashboard": "workspace:^",
"@backstage/plugin-octopus-deploy": "workspace:^",
"@backstage/plugin-org": "workspace:^",
"@backstage/plugin-pagerduty": "workspace:^",
"@backstage/plugin-permission-react": "workspace:^",
@@ -41,6 +41,10 @@ import {
isAzureDevOpsAvailable,
isAzurePipelinesAvailable,
} from '@backstage/plugin-azure-devops';
import {
isOctopusDeployAvailable,
EntityOctopusDeployContent,
} from '@backstage/plugin-octopus-deploy';
import { EntityBadgesDialog } from '@backstage/plugin-badges';
import {
EntityAboutCard,
@@ -262,6 +266,10 @@ export const cicdContent = (
<EntityAzurePipelinesContent defaultLimit={25} />
</EntitySwitch.Case>
<EntitySwitch.Case if={isOctopusDeployAvailable}>
<EntityOctopusDeployContent defaultLimit={25} />
</EntitySwitch.Case>
<EntitySwitch.Case>
<EmptyState
title="No CI/CD available for this entity"
+18 -2
View File
@@ -42,7 +42,7 @@ const cicdContent = (
)
```
3. Add `octopus.com/project-id` annotation in catalog descriptor file
3. Add `octopus.com/project-id` annotation in the catalog descriptor file.
To obtain a projects ID you will have to query the Octopus API. In the future we'll add support for using a projects slug as well.
@@ -58,4 +58,20 @@ spec:
type: service
```
All set , you will be able to see the plugin in action!
If your project is not part of the default space you can add the space ID to the annotation as a prefix. For example:
```
// catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
# ...
annotations:
octopus.com/project-id: Spaces-2/Projects-102
spec:
type: service
```
You can get the ID of the space from the URL in the Octopus Deploy UI.
All set, you will be able to see the plugin in action!
+14 -8
View File
@@ -25,10 +25,10 @@ export const OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION = 'octopus.com/project-id';
// @public (undocumented)
export interface OctopusDeployApi {
// (undocumented)
getReleaseProgression(
projectId: string,
releaseHistoryCount: number,
): Promise<OctopusProgression>;
getReleaseProgression(opts: {
projectReference: ProjectReference;
releaseHistoryCount: number;
}): Promise<OctopusProgression>;
}
// @public (undocumented)
@@ -42,10 +42,10 @@ export class OctopusDeployClient implements OctopusDeployApi {
proxyPathBase?: string;
});
// (undocumented)
getReleaseProgression(
projectId: string,
releaseHistoryCount: number,
): Promise<OctopusProgression>;
getReleaseProgression(opts: {
projectReference: ProjectReference;
releaseHistoryCount: number;
}): Promise<OctopusProgression>;
}
// @public (undocumented)
@@ -82,5 +82,11 @@ export type OctopusReleaseProgression = {
};
};
// @public (undocumented)
export type ProjectReference = {
projectId: string;
spaceId?: string;
};
// (No @packageDocumentation comment for this package)
```
+24 -12
View File
@@ -18,6 +18,7 @@ import {
DiscoveryApi,
FetchApi,
} from '@backstage/core-plugin-api';
import { ProjectReference } from '../utils/getAnnotationFromEntity';
/** @public */
export type OctopusProgression = {
@@ -57,10 +58,10 @@ const DEFAULT_PROXY_PATH_BASE = '/octopus-deploy';
/** @public */
export interface OctopusDeployApi {
getReleaseProgression(
projectId: string,
releaseHistoryCount: number,
): Promise<OctopusProgression>;
getReleaseProgression(opts: {
projectReference: ProjectReference;
releaseHistoryCount: number;
}): Promise<OctopusProgression>;
}
/** @public */
@@ -79,11 +80,11 @@ export class OctopusDeployClient implements OctopusDeployApi {
this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE;
}
async getReleaseProgression(
projectId: string,
releaseHistoryCount: number,
): Promise<OctopusProgression> {
const url = await this.getApiUrl(projectId, releaseHistoryCount);
async getReleaseProgression(opts: {
projectReference: ProjectReference;
releaseHistoryCount: number;
}): Promise<OctopusProgression> {
const url = await this.getApiUrl(opts);
const response = await this.fetchApi.fetch(url);
@@ -106,13 +107,24 @@ export class OctopusDeployClient implements OctopusDeployApi {
return responseJson;
}
private async getApiUrl(projectId: string, releaseHistoryCount: number) {
private async getApiUrl(opts: {
projectReference: ProjectReference;
releaseHistoryCount: number;
}) {
const proxyUrl = await this.discoveryApi.getBaseUrl('proxy');
const queryParameters = new URLSearchParams({
releaseHistoryCount: releaseHistoryCount.toString(),
releaseHistoryCount: opts.releaseHistoryCount.toString(),
});
if (opts.projectReference.spaceId !== undefined) {
return `${proxyUrl}${this.proxyPathBase}/${encodeURIComponent(
opts.projectReference.spaceId,
)}/projects/${encodeURIComponent(
opts.projectReference.projectId,
)}/progression?${queryParameters}`;
}
return `${proxyUrl}${this.proxyPathBase}/projects/${encodeURIComponent(
projectId,
opts.projectReference.projectId,
)}/progression?${queryParameters}`;
}
}
@@ -15,18 +15,19 @@
*/
import { useEntity } from '@backstage/plugin-catalog-react';
import { useReleases } from '../../hooks/useReleases';
import { getAnnotationFromEntity } from '../../utils/getAnnotationFromEntity';
import { getProjectReferenceAnnotationFromEntity } from '../../utils/getAnnotationFromEntity';
import React from 'react';
import { ReleaseTable } from '../ReleaseTable';
export const EntityPageOctopusDeploy = (props: { defaultLimit?: number }) => {
const { entity } = useEntity();
const projectId = getAnnotationFromEntity(entity);
const projectReference = getProjectReferenceAnnotationFromEntity(entity);
const { environments, releases, loading, error } = useReleases(
projectId,
projectReference.projectId,
props.defaultLimit ?? 3,
projectReference.spaceId,
);
return (
@@ -24,6 +24,7 @@ import {
export function useReleases(
projectId: string,
releaseHistoryCount: number,
spaceId?: string,
): {
environments?: OctopusEnvironment[];
releases?: OctopusReleaseProgression[];
@@ -33,8 +34,11 @@ export function useReleases(
const api = useApi(octopusDeployApiRef);
const { value, loading, error } = useAsync(() => {
return api.getReleaseProgression(projectId, releaseHistoryCount);
}, [api, projectId, releaseHistoryCount]);
return api.getReleaseProgression({
projectReference: { projectId, spaceId },
releaseHistoryCount,
});
}, [api, projectId, spaceId, releaseHistoryCount]);
return {
environments: value?.Environments,
+2
View File
@@ -21,4 +21,6 @@ export {
export * from './api';
export type { ProjectReference } from './utils/getAnnotationFromEntity';
export { OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION } from './constants';
@@ -17,7 +17,12 @@ import { OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION } from '../constants';
import { Entity } from '@backstage/catalog-model';
export function getAnnotationFromEntity(entity: Entity): string {
/** @public */
export type ProjectReference = { projectId: string; spaceId?: string };
export function getProjectReferenceAnnotationFromEntity(
entity: Entity,
): ProjectReference {
const annotation =
entity.metadata.annotations?.[OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION];
if (!annotation) {
@@ -26,5 +31,9 @@ export function getAnnotationFromEntity(entity: Entity): string {
);
}
return annotation;
const referencedProject = annotation.split('/', 2);
if (referencedProject.length === 2) {
return { projectId: referencedProject[1], spaceId: referencedProject[0] };
}
return { projectId: referencedProject[0] };
}
+2 -1
View File
@@ -7508,7 +7508,7 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/plugin-octopus-deploy@workspace:plugins/octopus-deploy":
"@backstage/plugin-octopus-deploy@workspace:^, @backstage/plugin-octopus-deploy@workspace:plugins/octopus-deploy":
version: 0.0.0-use.local
resolution: "@backstage/plugin-octopus-deploy@workspace:plugins/octopus-deploy"
dependencies:
@@ -23583,6 +23583,7 @@ __metadata:
"@backstage/plugin-microsoft-calendar": "workspace:^"
"@backstage/plugin-newrelic": "workspace:^"
"@backstage/plugin-newrelic-dashboard": "workspace:^"
"@backstage/plugin-octopus-deploy": "workspace:^"
"@backstage/plugin-org": "workspace:^"
"@backstage/plugin-pagerduty": "workspace:^"
"@backstage/plugin-permission-react": "workspace:^"