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:
@@ -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.
|
||||
@@ -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"
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
@@ -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}`;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -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,
|
||||
|
||||
@@ -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] };
|
||||
}
|
||||
|
||||
@@ -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:^"
|
||||
|
||||
Reference in New Issue
Block a user