@backstage/plugin-catalog-backend-module-azure 0.1.14-next.2 → 0.1.14
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 +21 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.cjs.js +11 -7
- package/dist/alpha.cjs.js.map +1 -1
- package/dist/alpha.d.ts +2 -2
- package/dist/index.cjs.js +10 -6
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +11 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend-module-azure
|
|
2
2
|
|
|
3
|
+
## 0.1.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 90469c02c8c: Renamed `azureDevOpsEntityProviderCatalogModule` to `catalogModuleAzureDevOpsEntityProvider` to match the [recommended naming patterns](https://backstage.io/docs/backend-system/architecture/naming-patterns).
|
|
8
|
+
- c17fa101825: Add branch filter support
|
|
9
|
+
https://backstage.io/docs/integrations/azure/discovery
|
|
10
|
+
- e675f902980: Make sure to not use deprecated exports from `@backstage/plugin-catalog-backend`
|
|
11
|
+
- 928a12a9b3e: Internal refactor of `/alpha` exports.
|
|
12
|
+
- 52b0022dab7: Updated dependency `msw` to `^1.0.0`.
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
- @backstage/backend-tasks@0.5.0
|
|
15
|
+
- @backstage/backend-common@0.18.3
|
|
16
|
+
- @backstage/errors@1.1.5
|
|
17
|
+
- @backstage/plugin-catalog-node@1.3.4
|
|
18
|
+
- @backstage/backend-plugin-api@0.5.0
|
|
19
|
+
- @backstage/catalog-model@1.2.1
|
|
20
|
+
- @backstage/integration@1.4.3
|
|
21
|
+
- @backstage/config@1.0.7
|
|
22
|
+
- @backstage/types@1.0.2
|
|
23
|
+
|
|
3
24
|
## 0.1.14-next.2
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/alpha/package.json
CHANGED
package/dist/alpha.cjs.js
CHANGED
|
@@ -6,7 +6,7 @@ var backendCommon = require('@backstage/backend-common');
|
|
|
6
6
|
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
7
7
|
var alpha = require('@backstage/plugin-catalog-node/alpha');
|
|
8
8
|
var integration = require('@backstage/integration');
|
|
9
|
-
var
|
|
9
|
+
var pluginCatalogNode = require('@backstage/plugin-catalog-node');
|
|
10
10
|
var backendTasks = require('@backstage/backend-tasks');
|
|
11
11
|
var uuid = require('uuid');
|
|
12
12
|
var fetch = require('node-fetch');
|
|
@@ -52,6 +52,7 @@ function readAzureDevOpsConfig(id, config) {
|
|
|
52
52
|
const project = config.getString("project");
|
|
53
53
|
const host = config.getOptionalString("host") || "dev.azure.com";
|
|
54
54
|
const repository = config.getOptionalString("repository") || "*";
|
|
55
|
+
const branch = config.getOptionalString("branch");
|
|
55
56
|
const path = config.getOptionalString("path") || "/catalog-info.yaml";
|
|
56
57
|
const schedule = config.has("schedule") ? backendTasks.readTaskScheduleDefinitionFromConfig(config.getConfig("schedule")) : void 0;
|
|
57
58
|
return {
|
|
@@ -60,6 +61,7 @@ function readAzureDevOpsConfig(id, config) {
|
|
|
60
61
|
organization,
|
|
61
62
|
project,
|
|
62
63
|
repository,
|
|
64
|
+
branch,
|
|
63
65
|
path,
|
|
64
66
|
schedule
|
|
65
67
|
};
|
|
@@ -182,7 +184,7 @@ class AzureDevOpsEntityProvider {
|
|
|
182
184
|
entities: locations.map((location) => {
|
|
183
185
|
return {
|
|
184
186
|
locationKey: this.getProviderName(),
|
|
185
|
-
entity:
|
|
187
|
+
entity: pluginCatalogNode.locationSpecToLocationEntity({ location })
|
|
186
188
|
};
|
|
187
189
|
})
|
|
188
190
|
});
|
|
@@ -200,13 +202,15 @@ class AzureDevOpsEntityProvider {
|
|
|
200
202
|
}
|
|
201
203
|
createObjectUrl(file) {
|
|
202
204
|
const baseUrl = `https://${this.config.host}/${this.config.organization}/${file.project.name}`;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
205
|
+
let fullUrl = `${baseUrl}/_git/${file.repository.name}?path=${file.path}`;
|
|
206
|
+
if (this.config.branch) {
|
|
207
|
+
fullUrl += `&version=GB${this.config.branch}`;
|
|
208
|
+
}
|
|
209
|
+
return encodeURI(fullUrl);
|
|
206
210
|
}
|
|
207
211
|
}
|
|
208
212
|
|
|
209
|
-
const
|
|
213
|
+
const catalogModuleAzureDevOpsEntityProvider = backendPluginApi.createBackendModule({
|
|
210
214
|
pluginId: "catalog",
|
|
211
215
|
moduleId: "azureDevOpsEntityProvider",
|
|
212
216
|
register(env) {
|
|
@@ -229,5 +233,5 @@ const azureDevOpsEntityProviderCatalogModule = backendPluginApi.createBackendMod
|
|
|
229
233
|
}
|
|
230
234
|
});
|
|
231
235
|
|
|
232
|
-
exports.
|
|
236
|
+
exports.catalogModuleAzureDevOpsEntityProvider = catalogModuleAzureDevOpsEntityProvider;
|
|
233
237
|
//# sourceMappingURL=alpha.cjs.js.map
|
package/dist/alpha.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.cjs.js","sources":["../src/providers/config.ts","../src/lib/azure.ts","../src/providers/AzureDevOpsEntityProvider.ts","../src/service/AzureDevOpsEntityProviderCatalogModule.ts"],"sourcesContent":["/*\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 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 project: {\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}/_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 || '*'} proj:${project || '*'}`,\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 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(`${this.getProviderName()} refresh failed`, 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 const target = this.createObjectUrl(file);\n\n return {\n type: 'url',\n target: target,\n presence: 'required',\n };\n }\n\n private createObjectUrl(file: CodeSearchResultItem): string {\n const baseUrl = `https://${this.config.host}/${this.config.organization}/${file.project.name}`;\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 { loggerToWinstonLogger } from '@backstage/backend-common';\nimport {\n createBackendModule,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';\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: coreServices.config,\n catalog: catalogProcessingExtensionPoint,\n logger: coreServices.logger,\n scheduler: coreServices.scheduler,\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":["readTaskScheduleDefinitionFromConfig","fetch","getAzureRequestOptions","integration","ScmIntegrations","uuid","locationSpecToLocationEntity","createBackendModule","coreServices","catalogProcessingExtensionPoint","loggerToWinstonLogger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"alpha.cjs.js","sources":["../src/providers/config.ts","../src/lib/azure.ts","../src/providers/AzureDevOpsEntityProvider.ts","../src/module/catalogModuleAzureDevOpsEntityProvider.ts"],"sourcesContent":["/*\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 branch = config.getOptionalString('branch');\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 branch,\n path,\n schedule,\n };\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 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 project: {\n name: string;\n };\n branch?: string;\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}/_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 || '*'} proj:${project || '*'}`,\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 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-node';\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(`${this.getProviderName()} refresh failed`, 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 const target = this.createObjectUrl(file);\n\n return {\n type: 'url',\n target: target,\n presence: 'required',\n };\n }\n\n private createObjectUrl(file: CodeSearchResultItem): string {\n const baseUrl = `https://${this.config.host}/${this.config.organization}/${file.project.name}`;\n\n let fullUrl = `${baseUrl}/_git/${file.repository.name}?path=${file.path}`;\n if (this.config.branch) {\n fullUrl += `&version=GB${this.config.branch}`;\n }\n\n return encodeURI(fullUrl);\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 { loggerToWinstonLogger } from '@backstage/backend-common';\nimport {\n createBackendModule,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';\nimport { AzureDevOpsEntityProvider } from '../providers';\n\n/**\n * Registers the AzureDevOpsEntityProvider with the catalog processing extension point.\n *\n * @alpha\n */\nexport const catalogModuleAzureDevOpsEntityProvider = createBackendModule({\n pluginId: 'catalog',\n moduleId: 'azureDevOpsEntityProvider',\n register(env) {\n env.registerInit({\n deps: {\n config: coreServices.config,\n catalog: catalogProcessingExtensionPoint,\n logger: coreServices.logger,\n scheduler: coreServices.scheduler,\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":["readTaskScheduleDefinitionFromConfig","fetch","getAzureRequestOptions","integration","ScmIntegrations","uuid","locationSpecToLocationEntity","createBackendModule","coreServices","catalogProcessingExtensionPoint","loggerToWinstonLogger"],"mappings":"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"}
|
package/dist/alpha.d.ts
CHANGED
|
@@ -5,6 +5,6 @@ import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
|
5
5
|
*
|
|
6
6
|
* @alpha
|
|
7
7
|
*/
|
|
8
|
-
declare const
|
|
8
|
+
declare const catalogModuleAzureDevOpsEntityProvider: () => _backstage_backend_plugin_api.BackendFeature;
|
|
9
9
|
|
|
10
|
-
export {
|
|
10
|
+
export { catalogModuleAzureDevOpsEntityProvider };
|
package/dist/index.cjs.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var integration = require('@backstage/integration');
|
|
6
|
-
var
|
|
6
|
+
var pluginCatalogNode = require('@backstage/plugin-catalog-node');
|
|
7
7
|
var fetch = require('node-fetch');
|
|
8
8
|
var backendTasks = require('@backstage/backend-tasks');
|
|
9
9
|
var uuid = require('uuid');
|
|
@@ -106,7 +106,7 @@ class AzureDevOpsDiscoveryProcessor {
|
|
|
106
106
|
);
|
|
107
107
|
for (const file of files) {
|
|
108
108
|
emit(
|
|
109
|
-
|
|
109
|
+
pluginCatalogNode.processingResult.location({
|
|
110
110
|
type: "url",
|
|
111
111
|
target: `${baseUrl}/${org}/${project}/_git/${file.repository.name}?path=${file.path}`,
|
|
112
112
|
// Not all locations may actually exist, since the user defined them as a wildcard pattern.
|
|
@@ -161,6 +161,7 @@ function readAzureDevOpsConfig(id, config) {
|
|
|
161
161
|
const project = config.getString("project");
|
|
162
162
|
const host = config.getOptionalString("host") || "dev.azure.com";
|
|
163
163
|
const repository = config.getOptionalString("repository") || "*";
|
|
164
|
+
const branch = config.getOptionalString("branch");
|
|
164
165
|
const path = config.getOptionalString("path") || "/catalog-info.yaml";
|
|
165
166
|
const schedule = config.has("schedule") ? backendTasks.readTaskScheduleDefinitionFromConfig(config.getConfig("schedule")) : void 0;
|
|
166
167
|
return {
|
|
@@ -169,6 +170,7 @@ function readAzureDevOpsConfig(id, config) {
|
|
|
169
170
|
organization,
|
|
170
171
|
project,
|
|
171
172
|
repository,
|
|
173
|
+
branch,
|
|
172
174
|
path,
|
|
173
175
|
schedule
|
|
174
176
|
};
|
|
@@ -260,7 +262,7 @@ class AzureDevOpsEntityProvider {
|
|
|
260
262
|
entities: locations.map((location) => {
|
|
261
263
|
return {
|
|
262
264
|
locationKey: this.getProviderName(),
|
|
263
|
-
entity:
|
|
265
|
+
entity: pluginCatalogNode.locationSpecToLocationEntity({ location })
|
|
264
266
|
};
|
|
265
267
|
})
|
|
266
268
|
});
|
|
@@ -278,9 +280,11 @@ class AzureDevOpsEntityProvider {
|
|
|
278
280
|
}
|
|
279
281
|
createObjectUrl(file) {
|
|
280
282
|
const baseUrl = `https://${this.config.host}/${this.config.organization}/${file.project.name}`;
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
283
|
+
let fullUrl = `${baseUrl}/_git/${file.repository.name}?path=${file.path}`;
|
|
284
|
+
if (this.config.branch) {
|
|
285
|
+
fullUrl += `&version=GB${this.config.branch}`;
|
|
286
|
+
}
|
|
287
|
+
return encodeURI(fullUrl);
|
|
284
288
|
}
|
|
285
289
|
}
|
|
286
290
|
|
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 project: {\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}/_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 || '*'} proj:${project || '*'}`,\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.slice(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(`${this.getProviderName()} refresh failed`, 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 const target = this.createObjectUrl(file);\n\n return {\n type: 'url',\n target: target,\n presence: 'required',\n };\n }\n\n private createObjectUrl(file: CodeSearchResultItem): string {\n const baseUrl = `https://${this.config.host}/${this.config.organization}/${file.project.name}`;\n return encodeURI(\n `${baseUrl}/_git/${file.repository.name}?path=${file.path}`,\n );\n }\n}\n"],"names":["fetch","getAzureRequestOptions","ScmIntegrations","processingResult","readTaskScheduleDefinitionFromConfig","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"],"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 project: {\n name: string;\n };\n branch?: string;\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}/_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 || '*'} proj:${project || '*'}`,\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-node';\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.slice(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 branch = config.getOptionalString('branch');\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 branch,\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-node';\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(`${this.getProviderName()} refresh failed`, 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 const target = this.createObjectUrl(file);\n\n return {\n type: 'url',\n target: target,\n presence: 'required',\n };\n }\n\n private createObjectUrl(file: CodeSearchResultItem): string {\n const baseUrl = `https://${this.config.host}/${this.config.organization}/${file.project.name}`;\n\n let fullUrl = `${baseUrl}/_git/${file.repository.name}?path=${file.path}`;\n if (this.config.branch) {\n fullUrl += `&version=GB${this.config.branch}`;\n }\n\n return encodeURI(fullUrl);\n }\n}\n"],"names":["fetch","getAzureRequestOptions","ScmIntegrations","processingResult","readTaskScheduleDefinitionFromConfig","integration","uuid","locationSpecToLocationEntity"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Config } from '@backstage/config';
|
|
2
2
|
import { ScmIntegrationRegistry } from '@backstage/integration';
|
|
3
|
-
import { CatalogProcessor, LocationSpec, CatalogProcessorEmit, EntityProvider, EntityProviderConnection } from '@backstage/plugin-catalog-
|
|
3
|
+
import { CatalogProcessor, LocationSpec, CatalogProcessorEmit, EntityProvider, EntityProviderConnection } from '@backstage/plugin-catalog-node';
|
|
4
4
|
import { Logger } from 'winston';
|
|
5
5
|
import { TaskRunner, PluginTaskScheduler } from '@backstage/backend-tasks';
|
|
6
6
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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.14
|
|
4
|
+
"version": "0.1.14",
|
|
5
5
|
"main": "./dist/index.cjs.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -43,15 +43,14 @@
|
|
|
43
43
|
"clean": "backstage-cli package clean"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@backstage/backend-common": "^0.18.3
|
|
47
|
-
"@backstage/backend-plugin-api": "^0.
|
|
48
|
-
"@backstage/backend-tasks": "^0.5.0
|
|
49
|
-
"@backstage/catalog-model": "^1.2.1
|
|
50
|
-
"@backstage/config": "^1.0.7
|
|
51
|
-
"@backstage/errors": "^1.1.5
|
|
52
|
-
"@backstage/integration": "^1.4.3
|
|
53
|
-
"@backstage/plugin-catalog-
|
|
54
|
-
"@backstage/plugin-catalog-node": "^1.3.4-next.2",
|
|
46
|
+
"@backstage/backend-common": "^0.18.3",
|
|
47
|
+
"@backstage/backend-plugin-api": "^0.5.0",
|
|
48
|
+
"@backstage/backend-tasks": "^0.5.0",
|
|
49
|
+
"@backstage/catalog-model": "^1.2.1",
|
|
50
|
+
"@backstage/config": "^1.0.7",
|
|
51
|
+
"@backstage/errors": "^1.1.5",
|
|
52
|
+
"@backstage/integration": "^1.4.3",
|
|
53
|
+
"@backstage/plugin-catalog-node": "^1.3.4",
|
|
55
54
|
"@backstage/types": "^1.0.2",
|
|
56
55
|
"lodash": "^4.17.21",
|
|
57
56
|
"node-fetch": "^2.6.7",
|
|
@@ -59,8 +58,8 @@
|
|
|
59
58
|
"winston": "^3.2.1"
|
|
60
59
|
},
|
|
61
60
|
"devDependencies": {
|
|
62
|
-
"@backstage/backend-test-utils": "^0.1.35
|
|
63
|
-
"@backstage/cli": "^0.22.4
|
|
61
|
+
"@backstage/backend-test-utils": "^0.1.35",
|
|
62
|
+
"@backstage/cli": "^0.22.4",
|
|
64
63
|
"@types/lodash": "^4.14.151",
|
|
65
64
|
"luxon": "^3.0.0",
|
|
66
65
|
"msw": "^1.0.0"
|