From 5bc3a400d5e6f257806dff617a8a77664257e3b4 Mon Sep 17 00:00:00 2001 From: Lokesh Kaki Date: Tue, 17 Mar 2026 21:13:59 -0500 Subject: [PATCH] fix(catalog-backend-module-azure): fix prettier formatting, export alpha types, and add API reports Signed-off-by: Lokesh Kaki --- .../report-alpha.api.md | 32 +++++++++++++++ .../catalog-backend-module-azure/src/alpha.ts | 6 ++- .../analyzeAzureDevOpsWebhookEvent.test.ts | 5 ++- .../events/analyzeAzureDevOpsWebhookEvent.ts | 39 +++++++++++++++++-- 4 files changed, 76 insertions(+), 6 deletions(-) diff --git a/plugins/catalog-backend-module-azure/report-alpha.api.md b/plugins/catalog-backend-module-azure/report-alpha.api.md index 3336b07e09..35853db61c 100644 --- a/plugins/catalog-backend-module-azure/report-alpha.api.md +++ b/plugins/catalog-backend-module-azure/report-alpha.api.md @@ -4,6 +4,38 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; +import { CatalogScmEvent } from '@backstage/plugin-catalog-node/alpha'; + +// @alpha +export function analyzeAzureDevOpsWebhookEvent( + eventType: string, + eventPayload: unknown, + options: AnalyzeAzureDevOpsWebhookEventOptions, +): Promise; + +// @alpha +export interface AnalyzeAzureDevOpsWebhookEventOptions { + isRelevantPath: (path: string) => boolean; +} + +// @alpha +export type AnalyzeAzureDevOpsWebhookEventResult = + | { + result: 'unsupported-event'; + event: string; + } + | { + result: 'ignored'; + reason: string; + } + | { + result: 'aborted'; + reason: string; + } + | { + result: 'ok'; + events: CatalogScmEvent[]; + }; // @alpha (undocumented) const _feature: BackendFeature; diff --git a/plugins/catalog-backend-module-azure/src/alpha.ts b/plugins/catalog-backend-module-azure/src/alpha.ts index 3e2354114f..14a7fe1379 100644 --- a/plugins/catalog-backend-module-azure/src/alpha.ts +++ b/plugins/catalog-backend-module-azure/src/alpha.ts @@ -20,4 +20,8 @@ import { default as feature } from './module'; const _feature = feature; export default _feature; -export { analyzeAzureDevOpsWebhookEvent } from './events/analyzeAzureDevOpsWebhookEvent'; +export { + analyzeAzureDevOpsWebhookEvent, + type AnalyzeAzureDevOpsWebhookEventOptions, + type AnalyzeAzureDevOpsWebhookEventResult, +} from './events/analyzeAzureDevOpsWebhookEvent'; diff --git a/plugins/catalog-backend-module-azure/src/events/analyzeAzureDevOpsWebhookEvent.test.ts b/plugins/catalog-backend-module-azure/src/events/analyzeAzureDevOpsWebhookEvent.test.ts index 77e30946cc..4a520aa5fb 100644 --- a/plugins/catalog-backend-module-azure/src/events/analyzeAzureDevOpsWebhookEvent.test.ts +++ b/plugins/catalog-backend-module-azure/src/events/analyzeAzureDevOpsWebhookEvent.test.ts @@ -22,7 +22,8 @@ const baseRepository = { id: 'repo-id', name: 'example-repo', defaultBranch: 'refs/heads/main', - remoteUrl: 'https://dev.azure.com/example-org/example-project/_git/example-repo', + remoteUrl: + 'https://dev.azure.com/example-org/example-project/_git/example-repo', }; const withPushEvent = (resource: Record) => ({ @@ -287,4 +288,4 @@ describe('analyzeAzureDevOpsWebhookEvent', () => { }); }); }); -}); \ No newline at end of file +}); diff --git a/plugins/catalog-backend-module-azure/src/events/analyzeAzureDevOpsWebhookEvent.ts b/plugins/catalog-backend-module-azure/src/events/analyzeAzureDevOpsWebhookEvent.ts index 0840c8b1d3..0dfa1c0f99 100644 --- a/plugins/catalog-backend-module-azure/src/events/analyzeAzureDevOpsWebhookEvent.ts +++ b/plugins/catalog-backend-module-azure/src/events/analyzeAzureDevOpsWebhookEvent.ts @@ -17,10 +17,28 @@ import { InputError } from '@backstage/errors'; import { CatalogScmEvent } from '@backstage/plugin-catalog-node/alpha'; +/** + * Options for {@link analyzeAzureDevOpsWebhookEvent}. + * @alpha + */ export interface AnalyzeAzureDevOpsWebhookEventOptions { + /** + * Predicate that returns true for file paths that are relevant to the + * catalog (e.g. paths ending in `.yaml` or `.yml`). + */ isRelevantPath: (path: string) => boolean; } +/** + * The result of analyzing an Azure DevOps webhook event. + * + * - `ok` — one or more catalog SCM events were produced. + * - `ignored` — the event was valid but not relevant. + * - `aborted` — the event could not be fully processed due to missing data. + * - `unsupported-event` — the event type is not handled by this analyzer. + * + * @alpha + */ export type AnalyzeAzureDevOpsWebhookEventResult = | { result: 'unsupported-event'; @@ -263,7 +281,9 @@ function normalizePushCommitChanges( for (const change of commit.changes ?? []) { const changeType = change.changeType?.toLowerCase() ?? ''; - const toPath = normalizePath(change.item?.path ?? change.path ?? change.newPath); + const toPath = normalizePath( + change.item?.path ?? change.path ?? change.newPath, + ); const fromPath = normalizePath( change.originalPath ?? change.item?.originalPath ?? @@ -380,9 +400,11 @@ async function onPushEvent( ): Promise { const resource = asObject(eventPayload.resource); const repository = getRepository(resource); - const refUpdates = (resource?.refUpdates as AzurePushRefUpdate[] | undefined) ?? []; + const refUpdates = + (resource?.refUpdates as AzurePushRefUpdate[] | undefined) ?? []; const commits = (resource?.commits as AzurePushCommit[] | undefined) ?? []; - const contextUrl = asString(resource?.url) ?? repository.remoteUrl ?? ''; + const contextUrl = + asString(resource?.url) ?? repository.remoteUrl ?? ''; if (commits.length === 0) { return { @@ -507,6 +529,17 @@ async function onRepositoryEvent( }; } +/** + * Analyzes an Azure DevOps webhook event and translates it into zero or more + * catalog SCM events that entity providers can act on. + * + * Supported event types: + * - `git.push` — translates file-level adds, modifications, and deletions on + * the default branch into catalog SCM events for paths matching + * `isRelevantPath`. + * + * @alpha + */ export async function analyzeAzureDevOpsWebhookEvent( eventType: string, eventPayload: unknown,