diff --git a/.changeset/red-cheetahs-invite.md b/.changeset/red-cheetahs-invite.md new file mode 100644 index 0000000000..ef1711c761 --- /dev/null +++ b/.changeset/red-cheetahs-invite.md @@ -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. diff --git a/packages/app/package.json b/packages/app/package.json index 74a41993d3..df626c16ba 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -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:^", diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index d2f6fbe109..026544ab26 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -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 = ( + + + + ; + getReleaseProgression(opts: { + projectReference: ProjectReference; + releaseHistoryCount: number; + }): Promise; } // @public (undocumented) @@ -42,10 +42,10 @@ export class OctopusDeployClient implements OctopusDeployApi { proxyPathBase?: string; }); // (undocumented) - getReleaseProgression( - projectId: string, - releaseHistoryCount: number, - ): Promise; + getReleaseProgression(opts: { + projectReference: ProjectReference; + releaseHistoryCount: number; + }): Promise; } // @public (undocumented) @@ -82,5 +82,11 @@ export type OctopusReleaseProgression = { }; }; +// @public (undocumented) +export type ProjectReference = { + projectId: string; + spaceId?: string; +}; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/octopus-deploy/src/api/index.ts b/plugins/octopus-deploy/src/api/index.ts index 9cba49d6c0..0364bed269 100644 --- a/plugins/octopus-deploy/src/api/index.ts +++ b/plugins/octopus-deploy/src/api/index.ts @@ -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; + getReleaseProgression(opts: { + projectReference: ProjectReference; + releaseHistoryCount: number; + }): Promise; } /** @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 { - const url = await this.getApiUrl(projectId, releaseHistoryCount); + async getReleaseProgression(opts: { + projectReference: ProjectReference; + releaseHistoryCount: number; + }): Promise { + 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}`; } } diff --git a/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx index de28edb9e0..21080cb408 100644 --- a/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx +++ b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx @@ -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 ( diff --git a/plugins/octopus-deploy/src/hooks/useReleases.ts b/plugins/octopus-deploy/src/hooks/useReleases.ts index 742ce78dca..671a0a7e7f 100644 --- a/plugins/octopus-deploy/src/hooks/useReleases.ts +++ b/plugins/octopus-deploy/src/hooks/useReleases.ts @@ -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, diff --git a/plugins/octopus-deploy/src/index.ts b/plugins/octopus-deploy/src/index.ts index e3264efaf0..2b39431606 100644 --- a/plugins/octopus-deploy/src/index.ts +++ b/plugins/octopus-deploy/src/index.ts @@ -21,4 +21,6 @@ export { export * from './api'; +export type { ProjectReference } from './utils/getAnnotationFromEntity'; + export { OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION } from './constants'; diff --git a/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts b/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts index e59a32235f..80ebaab76a 100644 --- a/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts +++ b/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts @@ -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] }; } diff --git a/yarn.lock b/yarn.lock index 0cd30db248..b27a6f4274 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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:^"