@backstage/plugin-catalog-backend-module-azure 0.1.8 → 0.1.9-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/alpha/package.json +6 -0
- package/config.d.ts +6 -5
- package/dist/index.alpha.d.ts +85 -0
- package/dist/index.beta.d.ts +80 -0
- package/dist/index.cjs.js +45 -6
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +21 -6
- package/package.json +22 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend-module-azure
|
|
2
2
|
|
|
3
|
+
## 0.1.9-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 87ff05892d: `AzureDevOpsEntityProvider`: Add option to configure schedule via `app-config.yaml` instead of in code.
|
|
8
|
+
|
|
9
|
+
Please find how to configure the schedule at the config at
|
|
10
|
+
https://backstage.io/docs/integrations/azure/discovery
|
|
11
|
+
|
|
12
|
+
- 0ca399b31b: Add `azureDevOpsEntityProviderCatalogModule` (new backend-plugin-api, alpha).
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
- @backstage/backend-common@0.16.0-next.0
|
|
15
|
+
- @backstage/plugin-catalog-backend@1.5.1-next.0
|
|
16
|
+
- @backstage/integration@1.4.0-next.0
|
|
17
|
+
- @backstage/backend-tasks@0.3.7-next.0
|
|
18
|
+
- @backstage/catalog-model@1.1.3-next.0
|
|
19
|
+
- @backstage/types@1.0.1-next.0
|
|
20
|
+
- @backstage/backend-plugin-api@0.1.4-next.0
|
|
21
|
+
- @backstage/plugin-catalog-node@1.2.1-next.0
|
|
22
|
+
- @backstage/config@1.0.4-next.0
|
|
23
|
+
- @backstage/errors@1.1.3-next.0
|
|
24
|
+
|
|
3
25
|
## 0.1.8
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/config.d.ts
CHANGED
|
@@ -14,34 +14,35 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { TaskScheduleDefinitionConfig } from '@backstage/backend-tasks';
|
|
18
|
+
|
|
17
19
|
interface AzureDevOpsConfig {
|
|
18
20
|
/**
|
|
19
21
|
* (Optional) The DevOps host; leave empty for `dev.azure.com`, otherwise set to your self-hosted instance host.
|
|
20
|
-
* @visibility backend
|
|
21
22
|
*/
|
|
22
23
|
host: string;
|
|
23
24
|
/**
|
|
24
25
|
* (Required) Your organization slug.
|
|
25
|
-
* @visibility backend
|
|
26
26
|
*/
|
|
27
27
|
organization: string;
|
|
28
28
|
/**
|
|
29
29
|
* (Required) Your project slug.
|
|
30
|
-
* @visibility backend
|
|
31
30
|
*/
|
|
32
31
|
project: string;
|
|
33
32
|
/**
|
|
34
33
|
* (Optional) The repository name. Wildcards are supported as show on the examples above.
|
|
35
34
|
* If not set, all repositories will be searched.
|
|
36
|
-
* @visibility backend
|
|
37
35
|
*/
|
|
38
36
|
repository?: string;
|
|
39
37
|
/**
|
|
40
38
|
* (Optional) Where to find catalog-info.yaml files. Wildcards are supported.
|
|
41
39
|
* If not set, defaults to /catalog-info.yaml.
|
|
42
|
-
* @visibility backend
|
|
43
40
|
*/
|
|
44
41
|
path?: string;
|
|
42
|
+
/**
|
|
43
|
+
* (Optional) TaskScheduleDefinition for the refresh.
|
|
44
|
+
*/
|
|
45
|
+
schedule?: TaskScheduleDefinitionConfig;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export interface Config {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Backstage catalog backend module that helps integrate towards Azure
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { BackendFeature } from '@backstage/backend-plugin-api';
|
|
8
|
+
import { CatalogProcessor } from '@backstage/plugin-catalog-backend';
|
|
9
|
+
import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend';
|
|
10
|
+
import { Config } from '@backstage/config';
|
|
11
|
+
import { EntityProvider } from '@backstage/plugin-catalog-backend';
|
|
12
|
+
import { EntityProviderConnection } from '@backstage/plugin-catalog-backend';
|
|
13
|
+
import { LocationSpec } from '@backstage/plugin-catalog-backend';
|
|
14
|
+
import { Logger } from 'winston';
|
|
15
|
+
import { PluginTaskScheduler } from '@backstage/backend-tasks';
|
|
16
|
+
import { ScmIntegrationRegistry } from '@backstage/integration';
|
|
17
|
+
import { TaskRunner } from '@backstage/backend-tasks';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Extracts repositories out of an Azure DevOps org.
|
|
21
|
+
*
|
|
22
|
+
* The following will create locations for all projects which have a catalog-info.yaml
|
|
23
|
+
* on the default branch. The first is shorthand for the second.
|
|
24
|
+
*
|
|
25
|
+
* target: "https://dev.azure.com/org/project"
|
|
26
|
+
* or
|
|
27
|
+
* target: https://dev.azure.com/org/project?path=/catalog-info.yaml
|
|
28
|
+
*
|
|
29
|
+
* You may also explicitly specify a single repo:
|
|
30
|
+
*
|
|
31
|
+
* target: https://dev.azure.com/org/project/_git/repo
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
**/
|
|
35
|
+
export declare class AzureDevOpsDiscoveryProcessor implements CatalogProcessor {
|
|
36
|
+
private readonly integrations;
|
|
37
|
+
private readonly logger;
|
|
38
|
+
static fromConfig(config: Config, options: {
|
|
39
|
+
logger: Logger;
|
|
40
|
+
}): AzureDevOpsDiscoveryProcessor;
|
|
41
|
+
constructor(options: {
|
|
42
|
+
integrations: ScmIntegrationRegistry;
|
|
43
|
+
logger: Logger;
|
|
44
|
+
});
|
|
45
|
+
getProcessorName(): string;
|
|
46
|
+
readLocation(location: LocationSpec, _optional: boolean, emit: CatalogProcessorEmit): Promise<boolean>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Provider which discovers catalog files within an Azure DevOps repositories.
|
|
51
|
+
*
|
|
52
|
+
* Use `AzureDevOpsEntityProvider.fromConfig(...)` to create instances.
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export declare class AzureDevOpsEntityProvider implements EntityProvider {
|
|
57
|
+
private readonly config;
|
|
58
|
+
private readonly integration;
|
|
59
|
+
private readonly logger;
|
|
60
|
+
private readonly scheduleFn;
|
|
61
|
+
private connection?;
|
|
62
|
+
static fromConfig(configRoot: Config, options: {
|
|
63
|
+
logger: Logger;
|
|
64
|
+
schedule?: TaskRunner;
|
|
65
|
+
scheduler?: PluginTaskScheduler;
|
|
66
|
+
}): AzureDevOpsEntityProvider[];
|
|
67
|
+
private constructor();
|
|
68
|
+
private createScheduleFn;
|
|
69
|
+
/** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */
|
|
70
|
+
getProviderName(): string;
|
|
71
|
+
/** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */
|
|
72
|
+
connect(connection: EntityProviderConnection): Promise<void>;
|
|
73
|
+
refresh(logger: Logger): Promise<void>;
|
|
74
|
+
private createLocationSpec;
|
|
75
|
+
private createObjectUrl;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Registers the AzureDevOpsEntityProvider with the catalog processing extension point.
|
|
80
|
+
*
|
|
81
|
+
* @alpha
|
|
82
|
+
*/
|
|
83
|
+
export declare const azureDevOpsEntityProviderCatalogModule: (options?: undefined) => BackendFeature;
|
|
84
|
+
|
|
85
|
+
export { }
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Backstage catalog backend module that helps integrate towards Azure
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { BackendFeature } from '@backstage/backend-plugin-api';
|
|
8
|
+
import { CatalogProcessor } from '@backstage/plugin-catalog-backend';
|
|
9
|
+
import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend';
|
|
10
|
+
import { Config } from '@backstage/config';
|
|
11
|
+
import { EntityProvider } from '@backstage/plugin-catalog-backend';
|
|
12
|
+
import { EntityProviderConnection } from '@backstage/plugin-catalog-backend';
|
|
13
|
+
import { LocationSpec } from '@backstage/plugin-catalog-backend';
|
|
14
|
+
import { Logger } from 'winston';
|
|
15
|
+
import { PluginTaskScheduler } from '@backstage/backend-tasks';
|
|
16
|
+
import { ScmIntegrationRegistry } from '@backstage/integration';
|
|
17
|
+
import { TaskRunner } from '@backstage/backend-tasks';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Extracts repositories out of an Azure DevOps org.
|
|
21
|
+
*
|
|
22
|
+
* The following will create locations for all projects which have a catalog-info.yaml
|
|
23
|
+
* on the default branch. The first is shorthand for the second.
|
|
24
|
+
*
|
|
25
|
+
* target: "https://dev.azure.com/org/project"
|
|
26
|
+
* or
|
|
27
|
+
* target: https://dev.azure.com/org/project?path=/catalog-info.yaml
|
|
28
|
+
*
|
|
29
|
+
* You may also explicitly specify a single repo:
|
|
30
|
+
*
|
|
31
|
+
* target: https://dev.azure.com/org/project/_git/repo
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
**/
|
|
35
|
+
export declare class AzureDevOpsDiscoveryProcessor implements CatalogProcessor {
|
|
36
|
+
private readonly integrations;
|
|
37
|
+
private readonly logger;
|
|
38
|
+
static fromConfig(config: Config, options: {
|
|
39
|
+
logger: Logger;
|
|
40
|
+
}): AzureDevOpsDiscoveryProcessor;
|
|
41
|
+
constructor(options: {
|
|
42
|
+
integrations: ScmIntegrationRegistry;
|
|
43
|
+
logger: Logger;
|
|
44
|
+
});
|
|
45
|
+
getProcessorName(): string;
|
|
46
|
+
readLocation(location: LocationSpec, _optional: boolean, emit: CatalogProcessorEmit): Promise<boolean>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Provider which discovers catalog files within an Azure DevOps repositories.
|
|
51
|
+
*
|
|
52
|
+
* Use `AzureDevOpsEntityProvider.fromConfig(...)` to create instances.
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export declare class AzureDevOpsEntityProvider implements EntityProvider {
|
|
57
|
+
private readonly config;
|
|
58
|
+
private readonly integration;
|
|
59
|
+
private readonly logger;
|
|
60
|
+
private readonly scheduleFn;
|
|
61
|
+
private connection?;
|
|
62
|
+
static fromConfig(configRoot: Config, options: {
|
|
63
|
+
logger: Logger;
|
|
64
|
+
schedule?: TaskRunner;
|
|
65
|
+
scheduler?: PluginTaskScheduler;
|
|
66
|
+
}): AzureDevOpsEntityProvider[];
|
|
67
|
+
private constructor();
|
|
68
|
+
private createScheduleFn;
|
|
69
|
+
/** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */
|
|
70
|
+
getProviderName(): string;
|
|
71
|
+
/** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */
|
|
72
|
+
connect(connection: EntityProviderConnection): Promise<void>;
|
|
73
|
+
refresh(logger: Logger): Promise<void>;
|
|
74
|
+
private createLocationSpec;
|
|
75
|
+
private createObjectUrl;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* Excluded from this release type: azureDevOpsEntityProviderCatalogModule */
|
|
79
|
+
|
|
80
|
+
export { }
|
package/dist/index.cjs.js
CHANGED
|
@@ -5,7 +5,10 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var integration = require('@backstage/integration');
|
|
6
6
|
var pluginCatalogBackend = require('@backstage/plugin-catalog-backend');
|
|
7
7
|
var fetch = require('node-fetch');
|
|
8
|
+
var backendTasks = require('@backstage/backend-tasks');
|
|
8
9
|
var uuid = require('uuid');
|
|
10
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
11
|
+
var pluginCatalogNode = require('@backstage/plugin-catalog-node');
|
|
9
12
|
|
|
10
13
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
11
14
|
|
|
@@ -158,28 +161,34 @@ function readAzureDevOpsConfig(id, config) {
|
|
|
158
161
|
const host = config.getOptionalString("host") || "dev.azure.com";
|
|
159
162
|
const repository = config.getOptionalString("repository") || "*";
|
|
160
163
|
const path = config.getOptionalString("path") || "/catalog-info.yaml";
|
|
164
|
+
const schedule = config.has("schedule") ? backendTasks.readTaskScheduleDefinitionFromConfig(config.getConfig("schedule")) : void 0;
|
|
161
165
|
return {
|
|
162
166
|
id,
|
|
163
167
|
host,
|
|
164
168
|
organization,
|
|
165
169
|
project,
|
|
166
170
|
repository,
|
|
167
|
-
path
|
|
171
|
+
path,
|
|
172
|
+
schedule
|
|
168
173
|
};
|
|
169
174
|
}
|
|
170
175
|
|
|
171
176
|
class AzureDevOpsEntityProvider {
|
|
172
|
-
constructor(config, integration, logger,
|
|
177
|
+
constructor(config, integration, logger, taskRunner) {
|
|
173
178
|
this.config = config;
|
|
174
179
|
this.integration = integration;
|
|
175
180
|
this.logger = logger.child({
|
|
176
181
|
target: this.getProviderName()
|
|
177
182
|
});
|
|
178
|
-
this.scheduleFn = this.createScheduleFn(
|
|
183
|
+
this.scheduleFn = this.createScheduleFn(taskRunner);
|
|
179
184
|
}
|
|
180
185
|
static fromConfig(configRoot, options) {
|
|
181
186
|
const providerConfigs = readAzureDevOpsConfigs(configRoot);
|
|
187
|
+
if (!options.schedule && !options.scheduler) {
|
|
188
|
+
throw new Error("Either schedule or scheduler must be provided.");
|
|
189
|
+
}
|
|
182
190
|
return providerConfigs.map((providerConfig) => {
|
|
191
|
+
var _a;
|
|
183
192
|
const integration$1 = integration.ScmIntegrations.fromConfig(configRoot).azure.byHost(
|
|
184
193
|
providerConfig.host
|
|
185
194
|
);
|
|
@@ -188,18 +197,24 @@ class AzureDevOpsEntityProvider {
|
|
|
188
197
|
`There is no Azure integration for host ${providerConfig.host}. Please add a configuration entry for it under integrations.azure`
|
|
189
198
|
);
|
|
190
199
|
}
|
|
200
|
+
if (!options.schedule && !providerConfig.schedule) {
|
|
201
|
+
throw new Error(
|
|
202
|
+
`No schedule provided neither via code nor config for AzureDevOpsEntityProvider:${providerConfig.id}.`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
const taskRunner = (_a = options.schedule) != null ? _a : options.scheduler.createScheduledTaskRunner(providerConfig.schedule);
|
|
191
206
|
return new AzureDevOpsEntityProvider(
|
|
192
207
|
providerConfig,
|
|
193
208
|
integration$1,
|
|
194
209
|
options.logger,
|
|
195
|
-
|
|
210
|
+
taskRunner
|
|
196
211
|
);
|
|
197
212
|
});
|
|
198
213
|
}
|
|
199
|
-
createScheduleFn(
|
|
214
|
+
createScheduleFn(taskRunner) {
|
|
200
215
|
return async () => {
|
|
201
216
|
const taskId = `${this.getProviderName()}:refresh`;
|
|
202
|
-
return
|
|
217
|
+
return taskRunner.run({
|
|
203
218
|
id: taskId,
|
|
204
219
|
fn: async () => {
|
|
205
220
|
const logger = this.logger.child({
|
|
@@ -265,6 +280,30 @@ class AzureDevOpsEntityProvider {
|
|
|
265
280
|
}
|
|
266
281
|
}
|
|
267
282
|
|
|
283
|
+
const azureDevOpsEntityProviderCatalogModule = backendPluginApi.createBackendModule({
|
|
284
|
+
pluginId: "catalog",
|
|
285
|
+
moduleId: "azureDevOpsEntityProvider",
|
|
286
|
+
register(env) {
|
|
287
|
+
env.registerInit({
|
|
288
|
+
deps: {
|
|
289
|
+
config: backendPluginApi.configServiceRef,
|
|
290
|
+
catalog: pluginCatalogNode.catalogProcessingExtensionPoint,
|
|
291
|
+
logger: backendPluginApi.loggerServiceRef,
|
|
292
|
+
scheduler: backendPluginApi.schedulerServiceRef
|
|
293
|
+
},
|
|
294
|
+
async init({ config, catalog, logger, scheduler }) {
|
|
295
|
+
catalog.addEntityProvider(
|
|
296
|
+
AzureDevOpsEntityProvider.fromConfig(config, {
|
|
297
|
+
logger: backendPluginApi.loggerToWinstonLogger(logger),
|
|
298
|
+
scheduler
|
|
299
|
+
})
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
|
|
268
306
|
exports.AzureDevOpsDiscoveryProcessor = AzureDevOpsDiscoveryProcessor;
|
|
269
307
|
exports.AzureDevOpsEntityProvider = AzureDevOpsEntityProvider;
|
|
308
|
+
exports.azureDevOpsEntityProviderCatalogModule = azureDevOpsEntityProviderCatalogModule;
|
|
270
309
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/lib/azure.ts","../src/processors/AzureDevOpsDiscoveryProcessor.ts","../src/providers/config.ts","../src/providers/AzureDevOpsEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fetch from 'node-fetch';\nimport {\n AzureIntegrationConfig,\n getAzureRequestOptions,\n} from '@backstage/integration';\n\nexport interface CodeSearchResponse {\n count: number;\n results: CodeSearchResultItem[];\n}\n\nexport interface CodeSearchResultItem {\n fileName: string;\n path: string;\n repository: {\n name: string;\n };\n}\n\nconst isCloud = (host: string) => host === 'dev.azure.com';\nconst PAGE_SIZE = 1000;\n\n// codeSearch returns all files that matches the given search path.\nexport async function codeSearch(\n azureConfig: AzureIntegrationConfig,\n org: string,\n project: string,\n repo: string,\n path: string,\n): Promise<CodeSearchResultItem[]> {\n const searchBaseUrl = isCloud(azureConfig.host)\n ? 'https://almsearch.dev.azure.com'\n : `https://${azureConfig.host}`;\n const searchUrl = `${searchBaseUrl}/${org}/${project}/_apis/search/codesearchresults?api-version=6.0-preview.1`;\n\n let items: CodeSearchResultItem[] = [];\n let hasMorePages = true;\n\n do {\n const response = await fetch(searchUrl, {\n ...getAzureRequestOptions(azureConfig, {\n 'Content-Type': 'application/json',\n }),\n method: 'POST',\n body: JSON.stringify({\n searchText: `path:${path} repo:${repo || '*'}`,\n $skip: items.length,\n $top: PAGE_SIZE,\n }),\n });\n\n if (response.status !== 200) {\n throw new Error(\n `Azure DevOps search failed with response status ${response.status}`,\n );\n }\n\n const body: CodeSearchResponse = await response.json();\n items = [...items, ...body.results];\n hasMorePages = body.count > items.length;\n } while (hasMorePages);\n\n return items;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport {\n ScmIntegrationRegistry,\n ScmIntegrations,\n} from '@backstage/integration';\nimport {\n CatalogProcessor,\n CatalogProcessorEmit,\n LocationSpec,\n processingResult,\n} from '@backstage/plugin-catalog-backend';\nimport { Logger } from 'winston';\nimport { codeSearch } from '../lib';\n\n/**\n * Extracts repositories out of an Azure DevOps org.\n *\n * The following will create locations for all projects which have a catalog-info.yaml\n * on the default branch. The first is shorthand for the second.\n *\n * target: \"https://dev.azure.com/org/project\"\n * or\n * target: https://dev.azure.com/org/project?path=/catalog-info.yaml\n *\n * You may also explicitly specify a single repo:\n *\n * target: https://dev.azure.com/org/project/_git/repo\n *\n * @public\n **/\nexport class AzureDevOpsDiscoveryProcessor implements CatalogProcessor {\n private readonly integrations: ScmIntegrationRegistry;\n private readonly logger: Logger;\n\n static fromConfig(config: Config, options: { logger: Logger }) {\n const integrations = ScmIntegrations.fromConfig(config);\n\n return new AzureDevOpsDiscoveryProcessor({\n ...options,\n integrations,\n });\n }\n\n constructor(options: {\n integrations: ScmIntegrationRegistry;\n logger: Logger;\n }) {\n this.integrations = options.integrations;\n this.logger = options.logger;\n }\n\n getProcessorName(): string {\n return 'AzureDevOpsDiscoveryProcessor';\n }\n\n async readLocation(\n location: LocationSpec,\n _optional: boolean,\n emit: CatalogProcessorEmit,\n ): Promise<boolean> {\n if (location.type !== 'azure-discovery') {\n return false;\n }\n\n const azureConfig = this.integrations.azure.byUrl(location.target)?.config;\n if (!azureConfig) {\n throw new Error(\n `There is no Azure integration that matches ${location.target}. Please add a configuration entry for it under integrations.azure`,\n );\n }\n\n const { baseUrl, org, project, repo, catalogPath } = parseUrl(\n location.target,\n );\n this.logger.info(\n `Reading Azure DevOps repositories from ${location.target}`,\n );\n\n const files = await codeSearch(\n azureConfig,\n org,\n project,\n repo,\n catalogPath,\n );\n\n this.logger.debug(\n `Found ${files.length} files in Azure DevOps from ${location.target}.`,\n );\n\n for (const file of files) {\n emit(\n processingResult.location({\n type: 'url',\n target: `${baseUrl}/${org}/${project}/_git/${file.repository.name}?path=${file.path}`,\n // Not all locations may actually exist, since the user defined them as a wildcard pattern.\n // Thus, we emit them as optional and let the downstream processor find them while not outputting\n // an error if it couldn't.\n presence: 'optional',\n }),\n );\n }\n\n return true;\n }\n}\n\n/**\n * parseUrl extracts segments from the Azure DevOps URL.\n **/\nexport function parseUrl(urlString: string): {\n baseUrl: string;\n org: string;\n project: string;\n repo: string;\n catalogPath: string;\n} {\n const url = new URL(urlString);\n const path = url.pathname.substr(1).split('/');\n\n const catalogPath = url.searchParams.get('path') || '/catalog-info.yaml';\n\n if (path.length === 2 && path[0].length && path[1].length) {\n return {\n baseUrl: url.origin,\n org: decodeURIComponent(path[0]),\n project: decodeURIComponent(path[1]),\n repo: '',\n catalogPath,\n };\n } else if (\n path.length === 4 &&\n path[0].length &&\n path[1].length &&\n path[2].length &&\n path[3].length\n ) {\n return {\n baseUrl: url.origin,\n org: decodeURIComponent(path[0]),\n project: decodeURIComponent(path[1]),\n repo: decodeURIComponent(path[3]),\n catalogPath,\n };\n }\n\n throw new Error(`Failed to parse ${urlString}`);\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { AzureDevOpsConfig } from './types';\n\nexport function readAzureDevOpsConfigs(config: Config): AzureDevOpsConfig[] {\n const configs: AzureDevOpsConfig[] = [];\n\n const providerConfigs = config.getOptionalConfig(\n 'catalog.providers.azureDevOps',\n );\n\n if (!providerConfigs) {\n return configs;\n }\n\n for (const id of providerConfigs.keys()) {\n configs.push(readAzureDevOpsConfig(id, providerConfigs.getConfig(id)));\n }\n\n return configs;\n}\n\nfunction readAzureDevOpsConfig(id: string, config: Config): AzureDevOpsConfig {\n const organization = config.getString('organization');\n const project = config.getString('project');\n const host = config.getOptionalString('host') || 'dev.azure.com';\n const repository = config.getOptionalString('repository') || '*';\n const path = config.getOptionalString('path') || '/catalog-info.yaml';\n\n return {\n id,\n host,\n organization,\n project,\n repository,\n path,\n };\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { TaskRunner } from '@backstage/backend-tasks';\nimport { Config } from '@backstage/config';\nimport { AzureIntegration, ScmIntegrations } from '@backstage/integration';\nimport {\n EntityProvider,\n EntityProviderConnection,\n LocationSpec,\n locationSpecToLocationEntity,\n} from '@backstage/plugin-catalog-backend';\nimport { readAzureDevOpsConfigs } from './config';\nimport { Logger } from 'winston';\nimport { AzureDevOpsConfig } from './types';\nimport * as uuid from 'uuid';\nimport { codeSearch, CodeSearchResultItem } from '../lib';\n\n/**\n * Provider which discovers catalog files within an Azure DevOps repositories.\n *\n * Use `AzureDevOpsEntityProvider.fromConfig(...)` to create instances.\n *\n * @public\n */\nexport class AzureDevOpsEntityProvider implements EntityProvider {\n private readonly logger: Logger;\n private readonly scheduleFn: () => Promise<void>;\n private connection?: EntityProviderConnection;\n\n static fromConfig(\n configRoot: Config,\n options: {\n logger: Logger;\n schedule: TaskRunner;\n },\n ): AzureDevOpsEntityProvider[] {\n const providerConfigs = readAzureDevOpsConfigs(configRoot);\n\n return providerConfigs.map(providerConfig => {\n const integration = ScmIntegrations.fromConfig(configRoot).azure.byHost(\n providerConfig.host,\n );\n\n if (!integration) {\n throw new Error(\n `There is no Azure integration for host ${providerConfig.host}. Please add a configuration entry for it under integrations.azure`,\n );\n }\n\n return new AzureDevOpsEntityProvider(\n providerConfig,\n integration,\n options.logger,\n options.schedule,\n );\n });\n }\n\n private constructor(\n private readonly config: AzureDevOpsConfig,\n private readonly integration: AzureIntegration,\n logger: Logger,\n schedule: TaskRunner,\n ) {\n this.logger = logger.child({\n target: this.getProviderName(),\n });\n\n this.scheduleFn = this.createScheduleFn(schedule);\n }\n\n private createScheduleFn(schedule: TaskRunner): () => Promise<void> {\n return async () => {\n const taskId = `${this.getProviderName()}:refresh`;\n return schedule.run({\n id: taskId,\n fn: async () => {\n const logger = this.logger.child({\n class: AzureDevOpsEntityProvider.prototype.constructor.name,\n taskId,\n taskInstanceId: uuid.v4(),\n });\n\n try {\n await this.refresh(logger);\n } catch (error) {\n logger.error(error);\n }\n },\n });\n };\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */\n getProviderName(): string {\n return `AzureDevOpsEntityProvider:${this.config.id}`;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */\n async connect(connection: EntityProviderConnection): Promise<void> {\n this.connection = connection;\n await this.scheduleFn();\n }\n\n async refresh(logger: Logger) {\n if (!this.connection) {\n throw new Error('Not initialized');\n }\n\n logger.info('Discovering Azure DevOps catalog files');\n\n const files = await codeSearch(\n this.integration.config,\n this.config.organization,\n this.config.project,\n this.config.repository,\n this.config.path,\n );\n\n logger.info(`Discovered ${files.length} catalog files`);\n\n const locations = files.map(key => this.createLocationSpec(key));\n\n await this.connection.applyMutation({\n type: 'full',\n entities: locations.map(location => {\n return {\n locationKey: this.getProviderName(),\n entity: locationSpecToLocationEntity({ location }),\n };\n }),\n });\n\n logger.info(\n `Committed ${locations.length} locations for AzureDevOps catalog files`,\n );\n }\n\n private createLocationSpec(file: CodeSearchResultItem): LocationSpec {\n return {\n type: 'url',\n target: this.createObjectUrl(file),\n presence: 'required',\n };\n }\n\n private createObjectUrl(file: CodeSearchResultItem): string {\n const baseUrl = `https://${this.config.host}/${this.config.organization}/${this.config.project}`;\n return encodeURI(\n `${baseUrl}/_git/${file.repository.name}?path=${file.path}`,\n );\n }\n}\n"],"names":["fetch","getAzureRequestOptions","ScmIntegrations","processingResult","integration","uuid","locationSpecToLocationEntity"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/lib/azure.ts","../src/processors/AzureDevOpsDiscoveryProcessor.ts","../src/providers/config.ts","../src/providers/AzureDevOpsEntityProvider.ts","../src/service/AzureDevOpsEntityProviderCatalogModule.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fetch from 'node-fetch';\nimport {\n AzureIntegrationConfig,\n getAzureRequestOptions,\n} from '@backstage/integration';\n\nexport interface CodeSearchResponse {\n count: number;\n results: CodeSearchResultItem[];\n}\n\nexport interface CodeSearchResultItem {\n fileName: string;\n path: string;\n repository: {\n name: string;\n };\n}\n\nconst isCloud = (host: string) => host === 'dev.azure.com';\nconst PAGE_SIZE = 1000;\n\n// codeSearch returns all files that matches the given search path.\nexport async function codeSearch(\n azureConfig: AzureIntegrationConfig,\n org: string,\n project: string,\n repo: string,\n path: string,\n): Promise<CodeSearchResultItem[]> {\n const searchBaseUrl = isCloud(azureConfig.host)\n ? 'https://almsearch.dev.azure.com'\n : `https://${azureConfig.host}`;\n const searchUrl = `${searchBaseUrl}/${org}/${project}/_apis/search/codesearchresults?api-version=6.0-preview.1`;\n\n let items: CodeSearchResultItem[] = [];\n let hasMorePages = true;\n\n do {\n const response = await fetch(searchUrl, {\n ...getAzureRequestOptions(azureConfig, {\n 'Content-Type': 'application/json',\n }),\n method: 'POST',\n body: JSON.stringify({\n searchText: `path:${path} repo:${repo || '*'}`,\n $skip: items.length,\n $top: PAGE_SIZE,\n }),\n });\n\n if (response.status !== 200) {\n throw new Error(\n `Azure DevOps search failed with response status ${response.status}`,\n );\n }\n\n const body: CodeSearchResponse = await response.json();\n items = [...items, ...body.results];\n hasMorePages = body.count > items.length;\n } while (hasMorePages);\n\n return items;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport {\n ScmIntegrationRegistry,\n ScmIntegrations,\n} from '@backstage/integration';\nimport {\n CatalogProcessor,\n CatalogProcessorEmit,\n LocationSpec,\n processingResult,\n} from '@backstage/plugin-catalog-backend';\nimport { Logger } from 'winston';\nimport { codeSearch } from '../lib';\n\n/**\n * Extracts repositories out of an Azure DevOps org.\n *\n * The following will create locations for all projects which have a catalog-info.yaml\n * on the default branch. The first is shorthand for the second.\n *\n * target: \"https://dev.azure.com/org/project\"\n * or\n * target: https://dev.azure.com/org/project?path=/catalog-info.yaml\n *\n * You may also explicitly specify a single repo:\n *\n * target: https://dev.azure.com/org/project/_git/repo\n *\n * @public\n **/\nexport class AzureDevOpsDiscoveryProcessor implements CatalogProcessor {\n private readonly integrations: ScmIntegrationRegistry;\n private readonly logger: Logger;\n\n static fromConfig(config: Config, options: { logger: Logger }) {\n const integrations = ScmIntegrations.fromConfig(config);\n\n return new AzureDevOpsDiscoveryProcessor({\n ...options,\n integrations,\n });\n }\n\n constructor(options: {\n integrations: ScmIntegrationRegistry;\n logger: Logger;\n }) {\n this.integrations = options.integrations;\n this.logger = options.logger;\n }\n\n getProcessorName(): string {\n return 'AzureDevOpsDiscoveryProcessor';\n }\n\n async readLocation(\n location: LocationSpec,\n _optional: boolean,\n emit: CatalogProcessorEmit,\n ): Promise<boolean> {\n if (location.type !== 'azure-discovery') {\n return false;\n }\n\n const azureConfig = this.integrations.azure.byUrl(location.target)?.config;\n if (!azureConfig) {\n throw new Error(\n `There is no Azure integration that matches ${location.target}. Please add a configuration entry for it under integrations.azure`,\n );\n }\n\n const { baseUrl, org, project, repo, catalogPath } = parseUrl(\n location.target,\n );\n this.logger.info(\n `Reading Azure DevOps repositories from ${location.target}`,\n );\n\n const files = await codeSearch(\n azureConfig,\n org,\n project,\n repo,\n catalogPath,\n );\n\n this.logger.debug(\n `Found ${files.length} files in Azure DevOps from ${location.target}.`,\n );\n\n for (const file of files) {\n emit(\n processingResult.location({\n type: 'url',\n target: `${baseUrl}/${org}/${project}/_git/${file.repository.name}?path=${file.path}`,\n // Not all locations may actually exist, since the user defined them as a wildcard pattern.\n // Thus, we emit them as optional and let the downstream processor find them while not outputting\n // an error if it couldn't.\n presence: 'optional',\n }),\n );\n }\n\n return true;\n }\n}\n\n/**\n * parseUrl extracts segments from the Azure DevOps URL.\n **/\nexport function parseUrl(urlString: string): {\n baseUrl: string;\n org: string;\n project: string;\n repo: string;\n catalogPath: string;\n} {\n const url = new URL(urlString);\n const path = url.pathname.substr(1).split('/');\n\n const catalogPath = url.searchParams.get('path') || '/catalog-info.yaml';\n\n if (path.length === 2 && path[0].length && path[1].length) {\n return {\n baseUrl: url.origin,\n org: decodeURIComponent(path[0]),\n project: decodeURIComponent(path[1]),\n repo: '',\n catalogPath,\n };\n } else if (\n path.length === 4 &&\n path[0].length &&\n path[1].length &&\n path[2].length &&\n path[3].length\n ) {\n return {\n baseUrl: url.origin,\n org: decodeURIComponent(path[0]),\n project: decodeURIComponent(path[1]),\n repo: decodeURIComponent(path[3]),\n catalogPath,\n };\n }\n\n throw new Error(`Failed to parse ${urlString}`);\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { readTaskScheduleDefinitionFromConfig } from '@backstage/backend-tasks';\nimport { Config } from '@backstage/config';\nimport { AzureDevOpsConfig } from './types';\n\nexport function readAzureDevOpsConfigs(config: Config): AzureDevOpsConfig[] {\n const configs: AzureDevOpsConfig[] = [];\n\n const providerConfigs = config.getOptionalConfig(\n 'catalog.providers.azureDevOps',\n );\n\n if (!providerConfigs) {\n return configs;\n }\n\n for (const id of providerConfigs.keys()) {\n configs.push(readAzureDevOpsConfig(id, providerConfigs.getConfig(id)));\n }\n\n return configs;\n}\n\nfunction readAzureDevOpsConfig(id: string, config: Config): AzureDevOpsConfig {\n const organization = config.getString('organization');\n const project = config.getString('project');\n const host = config.getOptionalString('host') || 'dev.azure.com';\n const repository = config.getOptionalString('repository') || '*';\n const path = config.getOptionalString('path') || '/catalog-info.yaml';\n\n const schedule = config.has('schedule')\n ? readTaskScheduleDefinitionFromConfig(config.getConfig('schedule'))\n : undefined;\n\n return {\n id,\n host,\n organization,\n project,\n repository,\n path,\n schedule,\n };\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PluginTaskScheduler, TaskRunner } from '@backstage/backend-tasks';\nimport { Config } from '@backstage/config';\nimport { AzureIntegration, ScmIntegrations } from '@backstage/integration';\nimport {\n EntityProvider,\n EntityProviderConnection,\n LocationSpec,\n locationSpecToLocationEntity,\n} from '@backstage/plugin-catalog-backend';\nimport { readAzureDevOpsConfigs } from './config';\nimport { Logger } from 'winston';\nimport { AzureDevOpsConfig } from './types';\nimport * as uuid from 'uuid';\nimport { codeSearch, CodeSearchResultItem } from '../lib';\n\n/**\n * Provider which discovers catalog files within an Azure DevOps repositories.\n *\n * Use `AzureDevOpsEntityProvider.fromConfig(...)` to create instances.\n *\n * @public\n */\nexport class AzureDevOpsEntityProvider implements EntityProvider {\n private readonly logger: Logger;\n private readonly scheduleFn: () => Promise<void>;\n private connection?: EntityProviderConnection;\n\n static fromConfig(\n configRoot: Config,\n options: {\n logger: Logger;\n schedule?: TaskRunner;\n scheduler?: PluginTaskScheduler;\n },\n ): AzureDevOpsEntityProvider[] {\n const providerConfigs = readAzureDevOpsConfigs(configRoot);\n\n if (!options.schedule && !options.scheduler) {\n throw new Error('Either schedule or scheduler must be provided.');\n }\n\n return providerConfigs.map(providerConfig => {\n const integration = ScmIntegrations.fromConfig(configRoot).azure.byHost(\n providerConfig.host,\n );\n\n if (!integration) {\n throw new Error(\n `There is no Azure integration for host ${providerConfig.host}. Please add a configuration entry for it under integrations.azure`,\n );\n }\n\n if (!options.schedule && !providerConfig.schedule) {\n throw new Error(\n `No schedule provided neither via code nor config for AzureDevOpsEntityProvider:${providerConfig.id}.`,\n );\n }\n\n const taskRunner =\n options.schedule ??\n options.scheduler!.createScheduledTaskRunner(providerConfig.schedule!);\n\n return new AzureDevOpsEntityProvider(\n providerConfig,\n integration,\n options.logger,\n taskRunner,\n );\n });\n }\n\n private constructor(\n private readonly config: AzureDevOpsConfig,\n private readonly integration: AzureIntegration,\n logger: Logger,\n taskRunner: TaskRunner,\n ) {\n this.logger = logger.child({\n target: this.getProviderName(),\n });\n\n this.scheduleFn = this.createScheduleFn(taskRunner);\n }\n\n private createScheduleFn(taskRunner: TaskRunner): () => Promise<void> {\n return async () => {\n const taskId = `${this.getProviderName()}:refresh`;\n return taskRunner.run({\n id: taskId,\n fn: async () => {\n const logger = this.logger.child({\n class: AzureDevOpsEntityProvider.prototype.constructor.name,\n taskId,\n taskInstanceId: uuid.v4(),\n });\n\n try {\n await this.refresh(logger);\n } catch (error) {\n logger.error(error);\n }\n },\n });\n };\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */\n getProviderName(): string {\n return `AzureDevOpsEntityProvider:${this.config.id}`;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */\n async connect(connection: EntityProviderConnection): Promise<void> {\n this.connection = connection;\n await this.scheduleFn();\n }\n\n async refresh(logger: Logger) {\n if (!this.connection) {\n throw new Error('Not initialized');\n }\n\n logger.info('Discovering Azure DevOps catalog files');\n\n const files = await codeSearch(\n this.integration.config,\n this.config.organization,\n this.config.project,\n this.config.repository,\n this.config.path,\n );\n\n logger.info(`Discovered ${files.length} catalog files`);\n\n const locations = files.map(key => this.createLocationSpec(key));\n\n await this.connection.applyMutation({\n type: 'full',\n entities: locations.map(location => {\n return {\n locationKey: this.getProviderName(),\n entity: locationSpecToLocationEntity({ location }),\n };\n }),\n });\n\n logger.info(\n `Committed ${locations.length} locations for AzureDevOps catalog files`,\n );\n }\n\n private createLocationSpec(file: CodeSearchResultItem): LocationSpec {\n return {\n type: 'url',\n target: this.createObjectUrl(file),\n presence: 'required',\n };\n }\n\n private createObjectUrl(file: CodeSearchResultItem): string {\n const baseUrl = `https://${this.config.host}/${this.config.organization}/${this.config.project}`;\n return encodeURI(\n `${baseUrl}/_git/${file.repository.name}?path=${file.path}`,\n );\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createBackendModule,\n loggerToWinstonLogger,\n configServiceRef,\n loggerServiceRef,\n schedulerServiceRef,\n} from '@backstage/backend-plugin-api';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';\nimport { AzureDevOpsEntityProvider } from '../providers';\n\n/**\n * Registers the AzureDevOpsEntityProvider with the catalog processing extension point.\n *\n * @alpha\n */\nexport const azureDevOpsEntityProviderCatalogModule = createBackendModule({\n pluginId: 'catalog',\n moduleId: 'azureDevOpsEntityProvider',\n register(env) {\n env.registerInit({\n deps: {\n config: configServiceRef,\n catalog: catalogProcessingExtensionPoint,\n logger: loggerServiceRef,\n scheduler: schedulerServiceRef,\n },\n async init({ config, catalog, logger, scheduler }) {\n catalog.addEntityProvider(\n AzureDevOpsEntityProvider.fromConfig(config, {\n logger: loggerToWinstonLogger(logger),\n scheduler,\n }),\n );\n },\n });\n },\n});\n"],"names":["fetch","getAzureRequestOptions","ScmIntegrations","processingResult","readTaskScheduleDefinitionFromConfig","integration","uuid","locationSpecToLocationEntity","createBackendModule","configServiceRef","catalogProcessingExtensionPoint","loggerServiceRef","schedulerServiceRef","loggerToWinstonLogger"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Backstage catalog backend module that helps integrate towards Azure
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { BackendFeature } from '@backstage/backend-plugin-api';
|
|
8
|
+
import { CatalogProcessor } from '@backstage/plugin-catalog-backend';
|
|
9
|
+
import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend';
|
|
1
10
|
import { Config } from '@backstage/config';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
11
|
+
import { EntityProvider } from '@backstage/plugin-catalog-backend';
|
|
12
|
+
import { EntityProviderConnection } from '@backstage/plugin-catalog-backend';
|
|
13
|
+
import { LocationSpec } from '@backstage/plugin-catalog-backend';
|
|
4
14
|
import { Logger } from 'winston';
|
|
15
|
+
import { PluginTaskScheduler } from '@backstage/backend-tasks';
|
|
16
|
+
import { ScmIntegrationRegistry } from '@backstage/integration';
|
|
5
17
|
import { TaskRunner } from '@backstage/backend-tasks';
|
|
6
18
|
|
|
7
19
|
/**
|
|
@@ -20,7 +32,7 @@ import { TaskRunner } from '@backstage/backend-tasks';
|
|
|
20
32
|
*
|
|
21
33
|
* @public
|
|
22
34
|
**/
|
|
23
|
-
declare class AzureDevOpsDiscoveryProcessor implements CatalogProcessor {
|
|
35
|
+
export declare class AzureDevOpsDiscoveryProcessor implements CatalogProcessor {
|
|
24
36
|
private readonly integrations;
|
|
25
37
|
private readonly logger;
|
|
26
38
|
static fromConfig(config: Config, options: {
|
|
@@ -41,7 +53,7 @@ declare class AzureDevOpsDiscoveryProcessor implements CatalogProcessor {
|
|
|
41
53
|
*
|
|
42
54
|
* @public
|
|
43
55
|
*/
|
|
44
|
-
declare class AzureDevOpsEntityProvider implements EntityProvider {
|
|
56
|
+
export declare class AzureDevOpsEntityProvider implements EntityProvider {
|
|
45
57
|
private readonly config;
|
|
46
58
|
private readonly integration;
|
|
47
59
|
private readonly logger;
|
|
@@ -49,7 +61,8 @@ declare class AzureDevOpsEntityProvider implements EntityProvider {
|
|
|
49
61
|
private connection?;
|
|
50
62
|
static fromConfig(configRoot: Config, options: {
|
|
51
63
|
logger: Logger;
|
|
52
|
-
schedule
|
|
64
|
+
schedule?: TaskRunner;
|
|
65
|
+
scheduler?: PluginTaskScheduler;
|
|
53
66
|
}): AzureDevOpsEntityProvider[];
|
|
54
67
|
private constructor();
|
|
55
68
|
private createScheduleFn;
|
|
@@ -62,4 +75,6 @@ declare class AzureDevOpsEntityProvider implements EntityProvider {
|
|
|
62
75
|
private createObjectUrl;
|
|
63
76
|
}
|
|
64
77
|
|
|
65
|
-
|
|
78
|
+
/* Excluded from this release type: azureDevOpsEntityProviderCatalogModule */
|
|
79
|
+
|
|
80
|
+
export { }
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-catalog-backend-module-azure",
|
|
3
3
|
"description": "A Backstage catalog backend module that helps integrate towards Azure",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.9-next.0",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"publishConfig": {
|
|
9
9
|
"access": "public",
|
|
10
|
+
"alphaTypes": "dist/index.alpha.d.ts",
|
|
10
11
|
"main": "dist/index.cjs.js",
|
|
11
12
|
"types": "dist/index.d.ts"
|
|
12
13
|
},
|
|
@@ -23,23 +24,25 @@
|
|
|
23
24
|
"backstage"
|
|
24
25
|
],
|
|
25
26
|
"scripts": {
|
|
26
|
-
"
|
|
27
|
+
"start": "backstage-cli package start",
|
|
28
|
+
"build": "backstage-cli package build --experimental-type-build",
|
|
27
29
|
"lint": "backstage-cli package lint",
|
|
28
30
|
"test": "backstage-cli package test",
|
|
29
31
|
"prepack": "backstage-cli package prepack",
|
|
30
32
|
"postpack": "backstage-cli package postpack",
|
|
31
|
-
"clean": "backstage-cli package clean"
|
|
32
|
-
"start": "backstage-cli package start"
|
|
33
|
+
"clean": "backstage-cli package clean"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"@backstage/backend-common": "^0.
|
|
36
|
-
"@backstage/backend-
|
|
37
|
-
"@backstage/
|
|
38
|
-
"@backstage/
|
|
39
|
-
"@backstage/
|
|
40
|
-
"@backstage/
|
|
41
|
-
"@backstage/
|
|
42
|
-
"@backstage/
|
|
36
|
+
"@backstage/backend-common": "^0.16.0-next.0",
|
|
37
|
+
"@backstage/backend-plugin-api": "^0.1.4-next.0",
|
|
38
|
+
"@backstage/backend-tasks": "^0.3.7-next.0",
|
|
39
|
+
"@backstage/catalog-model": "^1.1.3-next.0",
|
|
40
|
+
"@backstage/config": "^1.0.4-next.0",
|
|
41
|
+
"@backstage/errors": "^1.1.3-next.0",
|
|
42
|
+
"@backstage/integration": "^1.4.0-next.0",
|
|
43
|
+
"@backstage/plugin-catalog-backend": "^1.5.1-next.0",
|
|
44
|
+
"@backstage/plugin-catalog-node": "^1.2.1-next.0",
|
|
45
|
+
"@backstage/types": "^1.0.1-next.0",
|
|
43
46
|
"lodash": "^4.17.21",
|
|
44
47
|
"msw": "^0.47.0",
|
|
45
48
|
"node-fetch": "^2.6.7",
|
|
@@ -47,13 +50,15 @@
|
|
|
47
50
|
"winston": "^3.2.1"
|
|
48
51
|
},
|
|
49
52
|
"devDependencies": {
|
|
50
|
-
"@backstage/backend-test-utils": "^0.1.
|
|
51
|
-
"@backstage/cli": "^0.
|
|
52
|
-
"@types/lodash": "^4.14.151"
|
|
53
|
+
"@backstage/backend-test-utils": "^0.1.30-next.0",
|
|
54
|
+
"@backstage/cli": "^0.21.0-next.0",
|
|
55
|
+
"@types/lodash": "^4.14.151",
|
|
56
|
+
"luxon": "^3.0.0"
|
|
53
57
|
},
|
|
54
58
|
"files": [
|
|
55
|
-
"
|
|
56
|
-
"config.d.ts"
|
|
59
|
+
"alpha",
|
|
60
|
+
"config.d.ts",
|
|
61
|
+
"dist"
|
|
57
62
|
],
|
|
58
63
|
"configSchema": "config.d.ts"
|
|
59
64
|
}
|