Pretty most files
Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>
This commit is contained in:
@@ -1,88 +1,113 @@
|
||||
import { createApiRef, DiscoveryApi, IdentityApi } from "@backstage/core-plugin-api";
|
||||
/*
|
||||
* Copyright 2023 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 {
|
||||
createApiRef,
|
||||
DiscoveryApi,
|
||||
IdentityApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
export type OctopusProgression = {
|
||||
Environments: OctopusEnvironment[];
|
||||
Releases: OctopusReleaseProgression[];
|
||||
}
|
||||
Environments: OctopusEnvironment[];
|
||||
Releases: OctopusReleaseProgression[];
|
||||
};
|
||||
|
||||
export type OctopusEnvironment = {
|
||||
Id: string,
|
||||
Name: string
|
||||
}
|
||||
Id: string;
|
||||
Name: string;
|
||||
};
|
||||
|
||||
export type OctopusReleaseProgression = {
|
||||
Release: OctopusRelease
|
||||
Deployments: { [key: string]: OctopusDeployment[] }
|
||||
}
|
||||
Release: OctopusRelease;
|
||||
Deployments: { [key: string]: OctopusDeployment[] };
|
||||
};
|
||||
|
||||
export type OctopusRelease = {
|
||||
Id: string
|
||||
Version: string
|
||||
}
|
||||
Id: string;
|
||||
Version: string;
|
||||
};
|
||||
|
||||
export type OctopusDeployment = {
|
||||
State: string
|
||||
}
|
||||
State: string;
|
||||
};
|
||||
|
||||
export const octopusDeployApiRef = createApiRef<OctopusDeployApi>({
|
||||
id: 'plugin.octopusdeploy.service'
|
||||
id: 'plugin.octopusdeploy.service',
|
||||
});
|
||||
|
||||
const DEFAULT_PROXY_PATH_BASE = '/octopus-deploy';
|
||||
|
||||
type Options = {
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi
|
||||
/**
|
||||
* Path to use for requests via the proxy, defaults to /octopus-deploy
|
||||
*/
|
||||
proxyPathBase?: string
|
||||
}
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi;
|
||||
/**
|
||||
* Path to use for requests via the proxy, defaults to /octopus-deploy
|
||||
*/
|
||||
proxyPathBase?: string;
|
||||
};
|
||||
|
||||
export interface OctopusDeployApi {
|
||||
getReleaseProgression(projectId: string, releaseHistoryCount: number): Promise<OctopusProgression>;
|
||||
getReleaseProgression(
|
||||
projectId: string,
|
||||
releaseHistoryCount: number,
|
||||
): Promise<OctopusProgression>;
|
||||
}
|
||||
|
||||
export class OctopusDeployClient implements OctopusDeployApi {
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
private readonly identityApi: IdentityApi;
|
||||
private readonly proxyPathBase: string;
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
private readonly identityApi: IdentityApi;
|
||||
private readonly proxyPathBase: string;
|
||||
|
||||
constructor(options: Options) {
|
||||
this.discoveryApi = options.discoveryApi;
|
||||
this.identityApi = options.identityApi;
|
||||
this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE;
|
||||
constructor(options: Options) {
|
||||
this.discoveryApi = options.discoveryApi;
|
||||
this.identityApi = options.identityApi;
|
||||
this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE;
|
||||
}
|
||||
|
||||
async getReleaseProgression(
|
||||
projectId: string,
|
||||
releaseHistoryCount: number,
|
||||
): Promise<OctopusProgression> {
|
||||
const url = await this.getApiUrl(projectId, releaseHistoryCount);
|
||||
|
||||
const { token: idToken } = await this.identityApi.getCredentials();
|
||||
const response = await fetch(url, {
|
||||
headers: idToken ? { Authorization: `Bearer ${idToken}` } : {},
|
||||
});
|
||||
|
||||
let responseJson;
|
||||
|
||||
try {
|
||||
responseJson = await response.json();
|
||||
} catch (e) {
|
||||
responseJson = { releases: [] };
|
||||
}
|
||||
|
||||
async getReleaseProgression(projectId: string, releaseHistoryCount: number): Promise<OctopusProgression> {
|
||||
const url = await this.getApiUrl(projectId, releaseHistoryCount);
|
||||
|
||||
const { token: idToken } = await this.identityApi.getCredentials();
|
||||
const response = await fetch(url, {
|
||||
headers: idToken ? { Authorization: `Bearer ${idToken}` } : {},
|
||||
});
|
||||
|
||||
let responseJson;
|
||||
|
||||
try {
|
||||
responseJson = await response.json();
|
||||
} catch (e) {
|
||||
responseJson = { releases: [] };
|
||||
}
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`Error communicating with Octopus Deploy: ${
|
||||
responseJson?.error?.title || response.statusText
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
return responseJson;
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`Error communicating with Octopus Deploy: ${
|
||||
responseJson?.error?.title || response.statusText
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
private async getApiUrl(projectId: string, releaseHistoryCount: number) {
|
||||
const proxyUrl = await this.discoveryApi.getBaseUrl('proxy');
|
||||
return `${proxyUrl}${this.proxyPathBase}/projects/${projectId}/progression?releaseHistoryCount=${releaseHistoryCount}`;
|
||||
}
|
||||
}
|
||||
return responseJson;
|
||||
}
|
||||
|
||||
private async getApiUrl(projectId: string, releaseHistoryCount: number) {
|
||||
const proxyUrl = await this.discoveryApi.getBaseUrl('proxy');
|
||||
return `${proxyUrl}${this.proxyPathBase}/projects/${projectId}/progression?releaseHistoryCount=${releaseHistoryCount}`;
|
||||
}
|
||||
}
|
||||
|
||||
+30
-5
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2023 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 { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { useReleases } from '../../hooks/useReleases';
|
||||
import { getAnnotationFromEntity } from '../../utils/getAnnotationFromEntity';
|
||||
@@ -5,11 +20,21 @@ import React from 'react';
|
||||
import { ReleaseTable } from '../ReleaseTable';
|
||||
|
||||
export const EntityPageOctopusDeploy = (props: { defaultLimit?: number }) => {
|
||||
const { entity } = useEntity();
|
||||
const { entity } = useEntity();
|
||||
|
||||
const projectId = getAnnotationFromEntity(entity);
|
||||
const projectId = getAnnotationFromEntity(entity);
|
||||
|
||||
const { environments, releases, loading, error } = useReleases(projectId, props.defaultLimit ?? 3);
|
||||
const { environments, releases, loading, error } = useReleases(
|
||||
projectId,
|
||||
props.defaultLimit ?? 3,
|
||||
);
|
||||
|
||||
return <ReleaseTable environments={environments} releases={releases} loading={loading} error={error} />;
|
||||
}
|
||||
return (
|
||||
<ReleaseTable
|
||||
environments={environments}
|
||||
releases={releases}
|
||||
loading={loading}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1 +1,16 @@
|
||||
export { EntityPageOctopusDeploy } from './EntityPageOctopusDeploy';
|
||||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
export { EntityPageOctopusDeploy } from './EntityPageOctopusDeploy';
|
||||
|
||||
@@ -1 +1,16 @@
|
||||
export { ReleaseTable } from './ReleaseTable';
|
||||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
export { ReleaseTable } from './ReleaseTable';
|
||||
|
||||
@@ -1 +1,16 @@
|
||||
export const OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION = 'octopus.com/project-id';
|
||||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
export const OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION = 'octopus.com/project-id';
|
||||
|
||||
@@ -1,26 +1,45 @@
|
||||
import { useApi } from "@backstage/core-plugin-api";
|
||||
import useAsync from "react-use/lib/useAsync";
|
||||
import { octopusDeployApiRef, OctopusEnvironment, OctopusReleaseProgression } from "../api";
|
||||
/*
|
||||
* Copyright 2023 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 { useApi } from '@backstage/core-plugin-api';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import {
|
||||
octopusDeployApiRef,
|
||||
OctopusEnvironment,
|
||||
OctopusReleaseProgression,
|
||||
} from '../api';
|
||||
|
||||
export function useReleases(
|
||||
projectId: string,
|
||||
releaseHistoryCount: number
|
||||
projectId: string,
|
||||
releaseHistoryCount: number,
|
||||
): {
|
||||
environments?: OctopusEnvironment[],
|
||||
releases?: OctopusReleaseProgression[]
|
||||
loading: boolean;
|
||||
error?: Error;
|
||||
environments?: OctopusEnvironment[];
|
||||
releases?: OctopusReleaseProgression[];
|
||||
loading: boolean;
|
||||
error?: Error;
|
||||
} {
|
||||
const api = useApi(octopusDeployApiRef);
|
||||
|
||||
const { value, loading, error } = useAsync(() => {
|
||||
return api.getReleaseProgression(projectId, releaseHistoryCount);
|
||||
}, [ api, projectId, releaseHistoryCount ]);
|
||||
const api = useApi(octopusDeployApiRef);
|
||||
|
||||
return {
|
||||
environments: value?.Environments,
|
||||
releases: value?.Releases,
|
||||
loading,
|
||||
error
|
||||
};
|
||||
}
|
||||
const { value, loading, error } = useAsync(() => {
|
||||
return api.getReleaseProgression(projectId, releaseHistoryCount);
|
||||
}, [api, projectId, releaseHistoryCount]);
|
||||
|
||||
return {
|
||||
environments: value?.Environments,
|
||||
releases: value?.Releases,
|
||||
loading,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
import {
|
||||
OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION
|
||||
} from './constants';
|
||||
import {
|
||||
octopusDeployEntityContentRouteRef
|
||||
} from './routes';
|
||||
/*
|
||||
* Copyright 2023 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 { OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION } from './constants';
|
||||
import { octopusDeployEntityContentRouteRef } from './routes';
|
||||
|
||||
import { OctopusDeployClient, octopusDeployApiRef } from './api';
|
||||
|
||||
import { createApiFactory, createPlugin, createRoutableExtension, discoveryApiRef, identityApiRef } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
createApiFactory,
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
discoveryApiRef,
|
||||
identityApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
@@ -21,9 +38,10 @@ export const octopusDeployPlugin = createPlugin({
|
||||
createApiFactory({
|
||||
api: octopusDeployApiRef,
|
||||
deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef },
|
||||
factory: ({ discoveryApi, identityApi }) => new OctopusDeployClient({ discoveryApi, identityApi })
|
||||
})
|
||||
]
|
||||
factory: ({ discoveryApi, identityApi }) =>
|
||||
new OctopusDeployClient({ discoveryApi, identityApi }),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
/*
|
||||
@@ -42,8 +60,8 @@ export const EntityOctopusDeployContent = octopusDeployPlugin.provide(
|
||||
name: 'EntityOctopusDeployContent',
|
||||
component: () =>
|
||||
import('./components/EntityPageOctopusDeploy').then(
|
||||
m => m.EntityPageOctopusDeploy
|
||||
m => m.EntityPageOctopusDeploy,
|
||||
),
|
||||
mountPoint: octopusDeployEntityContentRouteRef
|
||||
})
|
||||
)
|
||||
mountPoint: octopusDeployEntityContentRouteRef,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
/*
|
||||
* Copyright 2023 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 { createRouteRef } from '@backstage/core-plugin-api';
|
||||
|
||||
export const octopusDeployEntityContentRouteRef = createRouteRef({
|
||||
id: 'octopus-deploy-entity-content'
|
||||
})
|
||||
id: 'octopus-deploy-entity-content',
|
||||
});
|
||||
|
||||
@@ -1,14 +1,30 @@
|
||||
import {
|
||||
OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION
|
||||
} from '../constants';
|
||||
/*
|
||||
* Copyright 2023 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 { OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION } from '../constants';
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
export function getAnnotationFromEntity(entity: Entity): string {
|
||||
const annotation = entity.metadata.annotations?.[OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION];
|
||||
if (!annotation) {
|
||||
throw new Error('Value for annotation octopus.com/project-id was not found');
|
||||
}
|
||||
|
||||
return annotation;
|
||||
}
|
||||
const annotation =
|
||||
entity.metadata.annotations?.[OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION];
|
||||
if (!annotation) {
|
||||
throw new Error(
|
||||
'Value for annotation octopus.com/project-id was not found',
|
||||
);
|
||||
}
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user