initial changes
Signed-off-by: Andre Wanlin <awanlin@spotify.com> Signed-off-by: Andre Wanlin <awanlin@spotify.com> Signed-off-by: Andre Wanlin <awanlin@spotify.com> Signed-off-by: Andre Wanlin <awanlin@spotify.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-azure-devops-backend': patch
|
||||
'@backstage/plugin-azure-devops-common': patch
|
||||
'@backstage/plugin-azure-devops': patch
|
||||
---
|
||||
|
||||
Introduced new `AzureDevOpsAnnotatorProcessor` that adds the needed annotations automatically. Also, moved constants to common package so they can be shared more easily
|
||||
@@ -89,6 +89,29 @@ In your `packages/backend/src/index.ts` make the following changes:
|
||||
backend.start();
|
||||
```
|
||||
|
||||
## Processor
|
||||
|
||||
The Azure DevOps backend plugin includes the `AzureDevOpsAnnotatorProcessor` which will automatically add the needed annotations for you. Here's how to install it:
|
||||
|
||||
```diff
|
||||
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
|
||||
import { ScaffolderEntitiesProcessor } from '@backstage/plugin-catalog-backend-module-scaffolder-entity-model';
|
||||
import { Router } from 'express';
|
||||
import { PluginEnvironment } from '../types';
|
||||
+ import { AzureDevOpsAnnotatorProcessor } from '@backstage/plugin-azure-devops-backend';
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
builder.addProcessor(new ScaffolderEntitiesProcessor());
|
||||
+ builder.addProcessor(AzureDevOpsAnnotatorProcessor.fromConfig(env.config));
|
||||
const { processingEngine, router } = await builder.build();
|
||||
await processingEngine.start();
|
||||
return router;
|
||||
}
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
- [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/azure-devops)
|
||||
|
||||
@@ -7,21 +7,44 @@ import { BackendFeature } from '@backstage/backend-plugin-api';
|
||||
import { Build } from 'azure-devops-node-api/interfaces/BuildInterfaces';
|
||||
import { BuildDefinitionReference } from 'azure-devops-node-api/interfaces/BuildInterfaces';
|
||||
import { BuildRun } from '@backstage/plugin-azure-devops-common';
|
||||
import { CatalogProcessor } from '@backstage/plugin-catalog-node';
|
||||
import { Config } from '@backstage/config';
|
||||
import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import express from 'express';
|
||||
import { GitRepository } from 'azure-devops-node-api/interfaces/GitInterfaces';
|
||||
import { GitTag } from '@backstage/plugin-azure-devops-common';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-common';
|
||||
import { Logger } from 'winston';
|
||||
import { Project } from '@backstage/plugin-azure-devops-common';
|
||||
import { PullRequest } from '@backstage/plugin-azure-devops-common';
|
||||
import { PullRequestOptions } from '@backstage/plugin-azure-devops-common';
|
||||
import { RepoBuild } from '@backstage/plugin-azure-devops-common';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { Team } from '@backstage/plugin-azure-devops-common';
|
||||
import { TeamMember } from '@backstage/plugin-azure-devops-common';
|
||||
import { UrlReader } from '@backstage/backend-common';
|
||||
import { WebApi } from 'azure-devops-node-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export class AzureDevOpsAnnotatorProcessor implements CatalogProcessor {
|
||||
constructor(opts: {
|
||||
scmIntegrationRegistry: ScmIntegrationRegistry;
|
||||
kinds?: string[];
|
||||
});
|
||||
// (undocumented)
|
||||
static fromConfig(
|
||||
config: Config,
|
||||
options?: {
|
||||
kinds?: string[];
|
||||
},
|
||||
): AzureDevOpsAnnotatorProcessor;
|
||||
// (undocumented)
|
||||
getProcessorName(): string;
|
||||
// (undocumented)
|
||||
preProcessEntity(entity: Entity, location: LocationSpec): Promise<Entity>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export class AzureDevOpsApi {
|
||||
constructor(logger: Logger, webApi: WebApi, urlReader: UrlReader);
|
||||
|
||||
@@ -30,12 +30,17 @@
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "workspace:^",
|
||||
"@backstage/backend-plugin-api": "workspace:^",
|
||||
"@backstage/catalog-model": "workspace:^",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/integration": "workspace:^",
|
||||
"@backstage/plugin-azure-devops-common": "workspace:^",
|
||||
"@backstage/plugin-catalog-common": "workspace:^",
|
||||
"@backstage/plugin-catalog-node": "workspace:^",
|
||||
"@types/express": "^4.17.6",
|
||||
"azure-devops-node-api": "^11.0.1",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^4.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mime-types": "^2.1.27",
|
||||
"p-limit": "^3.1.0",
|
||||
"winston": "^3.2.1",
|
||||
|
||||
@@ -23,3 +23,4 @@
|
||||
export { AzureDevOpsApi } from './api';
|
||||
export * from './service/router';
|
||||
export { azureDevOpsPlugin as default } from './plugin';
|
||||
export { AzureDevOpsAnnotatorProcessor } from './processor';
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* 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 { Entity } from '@backstage/catalog-model';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { AzureDevOpsAnnotatorProcessor } from './AzureDevOpsAnnotatorProcessor';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-common';
|
||||
|
||||
describe('AzureDevOpsAnnotatorProcessor', () => {
|
||||
it('adds annotation', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
},
|
||||
};
|
||||
const location: LocationSpec = {
|
||||
type: 'url',
|
||||
target:
|
||||
'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
};
|
||||
|
||||
const processor = AzureDevOpsAnnotatorProcessor.fromConfig(
|
||||
new ConfigReader({}),
|
||||
);
|
||||
|
||||
expect(await processor.preProcessEntity(entity, location)).toEqual({
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': 'dev.azure.com/organization',
|
||||
'dev.azure.com/project-repo': 'project/repository',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('adds annotation for Azure DevOps Server url', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
},
|
||||
};
|
||||
const location: LocationSpec = {
|
||||
type: 'url',
|
||||
target:
|
||||
'https://example.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
};
|
||||
|
||||
const processor = AzureDevOpsAnnotatorProcessor.fromConfig(
|
||||
new ConfigReader({
|
||||
integrations: {
|
||||
azure: [
|
||||
{
|
||||
host: 'example.com',
|
||||
credentials: [
|
||||
{
|
||||
personalAccessToken: 'pat',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(await processor.preProcessEntity(entity, location)).toEqual({
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': 'example.com/organization',
|
||||
'dev.azure.com/project-repo': 'project/repository',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('adds annotation for TFS subpath url', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
},
|
||||
};
|
||||
const location: LocationSpec = {
|
||||
type: 'url',
|
||||
target:
|
||||
'https://example.com/tfs/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
};
|
||||
|
||||
const processor = AzureDevOpsAnnotatorProcessor.fromConfig(
|
||||
new ConfigReader({
|
||||
integrations: {
|
||||
azure: [
|
||||
{
|
||||
host: 'example.com',
|
||||
credentials: [
|
||||
{
|
||||
personalAccessToken: 'pat',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(await processor.preProcessEntity(entity, location)).toEqual({
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': 'example.com/tfs/organization',
|
||||
'dev.azure.com/project-repo': 'project/repository',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('does not override existing annotation', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': 'myhost/myorg',
|
||||
'dev.azure.com/project-repo': 'myproj/myrepo',
|
||||
},
|
||||
},
|
||||
};
|
||||
const location: LocationSpec = {
|
||||
type: 'url',
|
||||
target:
|
||||
'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
};
|
||||
|
||||
const processor = AzureDevOpsAnnotatorProcessor.fromConfig(
|
||||
new ConfigReader({}),
|
||||
);
|
||||
|
||||
expect(await processor.preProcessEntity(entity, location)).toEqual({
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': 'myhost/myorg',
|
||||
'dev.azure.com/project-repo': 'myproj/myrepo',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should not add annotation for other providers', async () => {
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
},
|
||||
};
|
||||
const location: LocationSpec = {
|
||||
type: 'url',
|
||||
target:
|
||||
'https://not-in-mock-config.example.com/backstage/backstage/-/blob/master/catalog-info.yaml',
|
||||
};
|
||||
|
||||
const processor = AzureDevOpsAnnotatorProcessor.fromConfig(
|
||||
new ConfigReader({}),
|
||||
);
|
||||
|
||||
expect(await processor.preProcessEntity(entity, location)).toEqual({
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should only process applicable kinds', async () => {
|
||||
const component: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
},
|
||||
};
|
||||
|
||||
const api: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'API',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
},
|
||||
};
|
||||
|
||||
const system: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'System',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
},
|
||||
};
|
||||
|
||||
const location: LocationSpec = {
|
||||
type: 'url',
|
||||
target:
|
||||
'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
};
|
||||
|
||||
const processor = AzureDevOpsAnnotatorProcessor.fromConfig(
|
||||
new ConfigReader({}),
|
||||
{ kinds: ['API', 'Component'] },
|
||||
);
|
||||
|
||||
expect(await processor.preProcessEntity(component, location)).toEqual({
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': 'dev.azure.com/organization',
|
||||
'dev.azure.com/project-repo': 'project/repository',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(await processor.preProcessEntity(api, location)).toEqual({
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'API',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
annotations: {
|
||||
'dev.azure.com/host-org': 'dev.azure.com/organization',
|
||||
'dev.azure.com/project-repo': 'project/repository',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(await processor.preProcessEntity(system, location)).toEqual({
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'System',
|
||||
metadata: {
|
||||
name: 'my-component',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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 { Entity } from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
import {
|
||||
ScmIntegrationRegistry,
|
||||
ScmIntegrations,
|
||||
} from '@backstage/integration';
|
||||
import { identity, merge, pickBy } from 'lodash';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-common';
|
||||
import { CatalogProcessor } from '@backstage/plugin-catalog-node';
|
||||
import {
|
||||
AZURE_DEVOPS_HOST_ORG_ANNOTATION,
|
||||
AZURE_DEVOPS_REPO_ANNOTATION,
|
||||
} from '@backstage/plugin-azure-devops-common';
|
||||
import { parseAzureDevOpsUrl } from '../utils';
|
||||
|
||||
/** @public */
|
||||
export class AzureDevOpsAnnotatorProcessor implements CatalogProcessor {
|
||||
constructor(
|
||||
private readonly opts: {
|
||||
scmIntegrationRegistry: ScmIntegrationRegistry;
|
||||
kinds?: string[];
|
||||
},
|
||||
) {}
|
||||
|
||||
getProcessorName(): string {
|
||||
return 'AzureDevOpsAnnotatorProcessor';
|
||||
}
|
||||
|
||||
static fromConfig(
|
||||
config: Config,
|
||||
options?: { kinds?: string[] },
|
||||
): AzureDevOpsAnnotatorProcessor {
|
||||
return new AzureDevOpsAnnotatorProcessor({
|
||||
scmIntegrationRegistry: ScmIntegrations.fromConfig(config),
|
||||
kinds: options?.kinds,
|
||||
});
|
||||
}
|
||||
|
||||
async preProcessEntity(
|
||||
entity: Entity,
|
||||
location: LocationSpec,
|
||||
): Promise<Entity> {
|
||||
const applicableKinds = (this.opts.kinds ?? ['Component']).map(k =>
|
||||
k.toLocaleLowerCase('en-US'),
|
||||
);
|
||||
if (
|
||||
!applicableKinds.includes(entity.kind.toLocaleLowerCase('en-US')) ||
|
||||
location.type !== 'url'
|
||||
) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
const scmIntegration = this.opts.scmIntegrationRegistry.byUrl(
|
||||
location.target,
|
||||
);
|
||||
|
||||
if (!scmIntegration) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
if (scmIntegration.type !== 'azure') {
|
||||
return entity;
|
||||
}
|
||||
|
||||
const { host, org, project, repo } = parseAzureDevOpsUrl(location.target);
|
||||
|
||||
if (!org || !project || !repo) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
const hostOrgAnnotation = AZURE_DEVOPS_HOST_ORG_ANNOTATION;
|
||||
let hostOrgValue = entity.metadata.annotations?.[hostOrgAnnotation];
|
||||
if (!hostOrgValue) {
|
||||
hostOrgValue = `${host}/${org}`;
|
||||
}
|
||||
|
||||
const projectRepoAnnotation = AZURE_DEVOPS_REPO_ANNOTATION;
|
||||
let projectRepoValue = entity.metadata.annotations?.[projectRepoAnnotation];
|
||||
if (!projectRepoValue) {
|
||||
projectRepoValue = `${project}/${repo}`;
|
||||
}
|
||||
|
||||
const result = merge(
|
||||
{
|
||||
metadata: {
|
||||
annotations: pickBy(
|
||||
{
|
||||
[hostOrgAnnotation]: hostOrgValue,
|
||||
},
|
||||
identity,
|
||||
),
|
||||
},
|
||||
},
|
||||
entity,
|
||||
);
|
||||
|
||||
return merge(
|
||||
{
|
||||
metadata: {
|
||||
annotations: pickBy(
|
||||
{
|
||||
[projectRepoAnnotation]: projectRepoValue,
|
||||
},
|
||||
identity,
|
||||
),
|
||||
},
|
||||
},
|
||||
result,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 { AzureDevOpsAnnotatorProcessor } from './AzureDevOpsAnnotatorProcessor';
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
getPullRequestLink,
|
||||
replaceReadme,
|
||||
buildEncodedUrl,
|
||||
parseAzureDevOpsUrl,
|
||||
} from './azure-devops-utils';
|
||||
import { GitPullRequest } from 'azure-devops-node-api/interfaces/GitInterfaces';
|
||||
import { UrlReader } from '@backstage/backend-common';
|
||||
@@ -295,3 +296,38 @@ describe('buildEncodedUrl', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseAzureDevOpsUrl', () => {
|
||||
it('parses Azure DevOps Cloud url', async () => {
|
||||
const result = parseAzureDevOpsUrl(
|
||||
'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
);
|
||||
|
||||
expect(result.host).toEqual('dev.azure.com');
|
||||
expect(result.org).toEqual('organization');
|
||||
expect(result.project).toEqual('project');
|
||||
expect(result.repo).toEqual('repository');
|
||||
});
|
||||
|
||||
it('parses Azure DevOps Server url', async () => {
|
||||
const result = parseAzureDevOpsUrl(
|
||||
'https://server.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
);
|
||||
|
||||
expect(result.host).toEqual('server.com');
|
||||
expect(result.org).toEqual('organization');
|
||||
expect(result.project).toEqual('project');
|
||||
expect(result.repo).toEqual('repository');
|
||||
});
|
||||
|
||||
it('parses TFS subpath Url', async () => {
|
||||
const result = parseAzureDevOpsUrl(
|
||||
'https://server.com/tfs/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
);
|
||||
|
||||
expect(result.host).toEqual('server.com/tfs');
|
||||
expect(result.org).toEqual('organization');
|
||||
expect(result.project).toEqual('project');
|
||||
expect(result.repo).toEqual('repository');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -328,3 +328,29 @@ export function extractPartsFromAsset(content: string): {
|
||||
path: path.startsWith('.') ? path.substring(1, path.length) : path,
|
||||
};
|
||||
}
|
||||
|
||||
export function parseAzureDevOpsUrl(sourceUrl: string) {
|
||||
const url = new URL(sourceUrl);
|
||||
|
||||
let host = url.host;
|
||||
let org;
|
||||
let project;
|
||||
let repo;
|
||||
|
||||
const parts = url.pathname.split('/').map(part => decodeURIComponent(part));
|
||||
if (parts[2] === '_git') {
|
||||
org = parts[1];
|
||||
project = repo = parts[3];
|
||||
} else if (parts[3] === '_git') {
|
||||
org = parts[1];
|
||||
project = parts[2];
|
||||
repo = parts[4];
|
||||
} else if (parts[4] === '_git') {
|
||||
host = `${host}/${parts[1]}`;
|
||||
org = parts[2];
|
||||
project = parts[3];
|
||||
repo = parts[5];
|
||||
}
|
||||
|
||||
return { host, org, project, repo };
|
||||
}
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
// @public (undocumented)
|
||||
export const AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION =
|
||||
'dev.azure.com/build-definition';
|
||||
|
||||
// @public (undocumented)
|
||||
export const AZURE_DEVOPS_DEFAULT_TOP: number;
|
||||
|
||||
// @public (undocumented)
|
||||
export const AZURE_DEVOPS_HOST_ORG_ANNOTATION = 'dev.azure.com/host-org';
|
||||
|
||||
// @public (undocumented)
|
||||
export const AZURE_DEVOPS_PROJECT_ANNOTATION = 'dev.azure.com/project';
|
||||
|
||||
// @public (undocumented)
|
||||
export const AZURE_DEVOPS_REPO_ANNOTATION = 'dev.azure.com/project-repo';
|
||||
|
||||
// @public (undocumented)
|
||||
export enum BuildResult {
|
||||
Canceled = 32,
|
||||
|
||||
@@ -14,9 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** @public */
|
||||
export const AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION =
|
||||
'dev.azure.com/build-definition';
|
||||
/** @public */
|
||||
export const AZURE_DEVOPS_HOST_ORG_ANNOTATION = 'dev.azure.com/host-org';
|
||||
/** @public */
|
||||
export const AZURE_DEVOPS_PROJECT_ANNOTATION = 'dev.azure.com/project';
|
||||
/** @public */
|
||||
export const AZURE_DEVOPS_REPO_ANNOTATION = 'dev.azure.com/project-repo';
|
||||
/** @public */
|
||||
export const AZURE_DEVOPS_DEFAULT_TOP: number = 10;
|
||||
@@ -15,3 +15,4 @@
|
||||
*/
|
||||
|
||||
export * from './types';
|
||||
export * from './constants';
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
AZURE_DEVOPS_DEFAULT_TOP,
|
||||
BuildRun,
|
||||
BuildRunOptions,
|
||||
} from '@backstage/plugin-azure-devops-common';
|
||||
|
||||
import { AZURE_DEVOPS_DEFAULT_TOP } from '../constants';
|
||||
import { azureDevOpsApiRef } from '../api';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
AZURE_DEVOPS_DEFAULT_TOP,
|
||||
PullRequest,
|
||||
PullRequestOptions,
|
||||
PullRequestStatus,
|
||||
} from '@backstage/plugin-azure-devops-common';
|
||||
|
||||
import { AZURE_DEVOPS_DEFAULT_TOP } from '../constants';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { azureDevOpsApiRef } from '../api';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION,
|
||||
AZURE_DEVOPS_PROJECT_ANNOTATION,
|
||||
AZURE_DEVOPS_REPO_ANNOTATION,
|
||||
} from './constants';
|
||||
import {
|
||||
azurePipelinesEntityContentRouteRef,
|
||||
azurePullRequestDashboardRouteRef,
|
||||
@@ -37,6 +32,11 @@ import {
|
||||
import { AzureDevOpsClient } from './api/AzureDevOpsClient';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { azureDevOpsApiRef } from './api/AzureDevOpsApi';
|
||||
import {
|
||||
AZURE_DEVOPS_REPO_ANNOTATION,
|
||||
AZURE_DEVOPS_PROJECT_ANNOTATION,
|
||||
AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION,
|
||||
} from '@backstage/plugin-azure-devops-common';
|
||||
|
||||
/** @public */
|
||||
export const isAzureDevOpsAvailable = (entity: Entity) =>
|
||||
|
||||
@@ -14,14 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION,
|
||||
AZURE_DEVOPS_HOST_ORG_ANNOTATION,
|
||||
AZURE_DEVOPS_PROJECT_ANNOTATION,
|
||||
AZURE_DEVOPS_REPO_ANNOTATION,
|
||||
} from '../constants';
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import {
|
||||
AZURE_DEVOPS_PROJECT_ANNOTATION,
|
||||
AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION,
|
||||
AZURE_DEVOPS_REPO_ANNOTATION,
|
||||
AZURE_DEVOPS_HOST_ORG_ANNOTATION,
|
||||
} from '@backstage/plugin-azure-devops-common';
|
||||
|
||||
export function getAnnotationValuesFromEntity(entity: Entity): {
|
||||
project: string;
|
||||
|
||||
@@ -5049,14 +5049,19 @@ __metadata:
|
||||
dependencies:
|
||||
"@backstage/backend-common": "workspace:^"
|
||||
"@backstage/backend-plugin-api": "workspace:^"
|
||||
"@backstage/catalog-model": "workspace:^"
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/config": "workspace:^"
|
||||
"@backstage/integration": "workspace:^"
|
||||
"@backstage/plugin-azure-devops-common": "workspace:^"
|
||||
"@backstage/plugin-catalog-common": "workspace:^"
|
||||
"@backstage/plugin-catalog-node": "workspace:^"
|
||||
"@types/express": ^4.17.6
|
||||
"@types/supertest": ^2.0.8
|
||||
azure-devops-node-api: ^11.0.1
|
||||
express: ^4.17.1
|
||||
express-promise-router: ^4.1.0
|
||||
lodash: ^4.17.21
|
||||
mime-types: ^2.1.27
|
||||
msw: ^1.0.0
|
||||
p-limit: ^3.1.0
|
||||
|
||||
Reference in New Issue
Block a user