Skip to content

Conversation

@michelle0927
Copy link
Collaborator

@michelle0927 michelle0927 commented Dec 12, 2025

Resolves #18106

Summary by CodeRabbit

  • New Features

    • Added new Azure DevOps event source for real-time webhook subscriptions.
    • Dynamic selection of event types and projects from Azure DevOps.
    • Automatic creation, persistence, and removal of webhook subscriptions; emitted events include generated metadata.
  • Chores

    • Bumped package to 0.1.0 and added required platform dependency.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 12, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Review Updated (UTC)
pipedream-docs-redirect-do-not-edit Ignored Ignored Dec 15, 2025 6:15pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

Walkthrough

Adds OAuth-backed Azure DevOps API helpers and subscription management to the app component, introduces a new event source that creates/deletes webhook subscriptions and emits received events, and bumps the component package version and dependencies.

Changes

Cohort / File(s) Summary
App integration & API helpers
components/azure_devops_microsoft_entra_id_oauth/azure_devops_microsoft_entra_id_oauth.app.mjs
Added propDefinitions.eventType and propDefinitions.projectId; added _baseUrl() and _makeRequest({$, path, params, ...opts}); implemented listEventTypes(), listProjects(), createSubscription(), deleteSubscription(); removed legacy authKeys().
Package metadata
components/azure_devops_microsoft_entra_id_oauth/package.json
Bumped version 0.0.10.1.0; added dependency @pipedream/platform: ^3.1.1.
Event source (new)
components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs
New source that creates/deletes Azure DevOps webhook subscriptions on activate/deactivate, persists subscription ID to the DB, constructs event metadata (generateMeta), and emits incoming webhook events in run().

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Source as Event Source
    participant App as AzureDevOps App
    participant ADO as Azure DevOps API
    participant DB as Database
    participant Webhook as Webhook (HTTP endpoint)

    User->>Source: Activate (select eventType, projectId)
    Source->>App: call createSubscription(opts with http.endpoint)
    App->>ADO: POST /hooks/subscriptions (Bearer token, api-version)
    ADO-->>App: subscriptionId
    App-->>Source: subscription response
    Source->>DB: _setHookId(subscriptionId)

    Webhook->>Source: Incoming webhook POST (event body)
    Source->>Source: generateMeta(body)
    Source->>User: emit(event, meta)

    User->>Source: Deactivate
    Source->>DB: _getHookId()
    Source->>App: deleteSubscription(subscriptionId)
    App->>ADO: DELETE /hooks/subscriptions/{subscriptionId}
    ADO-->>App: success
    Source->>DB: clear stored subscriptionId
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review _makeRequest() for correct header/token handling and api-version parameterization.
  • Verify subscription payload structure in createSubscription() matches Azure DevOps expectations (publisherInputs/consumerInputs).
  • Confirm listEventTypes() and listProjects() handle pagination/errors and provide options shape expected by prop definitions.
  • Check DB persistence methods in the new source (_getHookId, _setHookId) for edge cases and error handling.
  • Validate package.json dependency bump is intentional and compatible.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description is minimal, containing only 'Resolves #18106' without filling the template's WHY section or providing context about the implementation approach. Expand the PR description by completing the WHY section with details about the migration rationale, implementation approach, and any breaking changes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main objective: migrating Azure DevOps components to Microsoft Entra ID OAuth, directly addressing issue #18106.
Linked Issues check ✅ Passed The changes implement all required components: authentication methods, event type/project listings, and subscription management for Azure DevOps with Microsoft Entra ID OAuth [#18106].
Out of Scope Changes check ✅ Passed All changes directly support the Azure DevOps Microsoft Entra ID OAuth migration: app configuration updates, package dependencies, and new event source implementation are all in scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue-18106

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between da3b9b7 and 156b4b2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • components/azure_devops_microsoft_entra_id_oauth/azure_devops_microsoft_entra_id_oauth.app.mjs (1 hunks)
  • components/azure_devops_microsoft_entra_id_oauth/package.json (2 hunks)
  • components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2024-12-12T19:23:09.039Z
Learnt from: jcortes
Repo: PipedreamHQ/pipedream PR: 14935
File: components/sailpoint/package.json:15-18
Timestamp: 2024-12-12T19:23:09.039Z
Learning: When developing Pipedream components, do not add built-in Node.js modules like `fs` to `package.json` dependencies, as they are native modules provided by the Node.js runtime.

Applied to files:

  • components/azure_devops_microsoft_entra_id_oauth/package.json
📚 Learning: 2024-10-10T19:18:27.998Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 14265
File: components/the_magic_drip/sources/common.mjs:35-43
Timestamp: 2024-10-10T19:18:27.998Z
Learning: In `components/the_magic_drip/sources/common.mjs`, when processing items in `getAndProcessData`, `savedIds` is intentionally updated with IDs of both emitted and non-emitted items to avoid emitting retroactive events upon first deployment and ensure only new events are emitted as they occur.

Applied to files:

  • components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs
📚 Learning: 2025-09-15T22:01:11.472Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 18362
File: components/leonardo_ai/actions/generate-image/generate-image.mjs:103-105
Timestamp: 2025-09-15T22:01:11.472Z
Learning: In Pipedream components, pipedream/platform's axios implementation automatically excludes undefined values from HTTP requests, so there's no need to manually check for truthiness before including properties in request payloads.

Applied to files:

  • components/azure_devops_microsoft_entra_id_oauth/azure_devops_microsoft_entra_id_oauth.app.mjs
📚 Learning: 2024-10-08T15:33:38.240Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-10-08T15:33:38.240Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.

Applied to files:

  • components/azure_devops_microsoft_entra_id_oauth/azure_devops_microsoft_entra_id_oauth.app.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Lint Code Base
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: pnpm publish
🔇 Additional comments (8)
components/azure_devops_microsoft_entra_id_oauth/azure_devops_microsoft_entra_id_oauth.app.mjs (5)

18-20: LGTM!

The base URL construction correctly uses the organization from the auth configuration.


44-50: LGTM!

The subscription creation method correctly delegates to the POST endpoint.


51-57: LGTM!

The subscription deletion method correctly constructs the DELETE request.


21-36: No action needed. API version 7.1 is correct for Microsoft Entra ID OAuth with Azure DevOps REST API and is officially supported in 2024-2025. The implementation follows Microsoft's recommended approach for Entra ID OAuth integration.


37-43: No action needed on this endpoint.

The /hooks/publishers/tfs/eventtypes endpoint is the current, documented Azure DevOps REST API endpoint for retrieving webhook event types. The "tfs" publisher identifier is the standard publisher name for Azure DevOps (not a legacy identifier), and it works seamlessly with Microsoft Entra ID OAuth authentication. The endpoint compatibility is not affected by the authentication method used.

components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs (3)

1-20: LGTM!

The component structure and prop definitions follow Pipedream conventions correctly.


44-50: LGTM!

The hookId persistence methods correctly use the db service.


59-63: LGTM!

The run method correctly emits webhook events with generated metadata, following standard Pipedream patterns.

luancazarine
luancazarine previously approved these changes Dec 12, 2025
Copy link
Collaborator

@luancazarine luancazarine left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @michelle0927, LGTM! Ready for QA!

@vunguyenhung
Copy link
Collaborator

@vunguyenhung
Copy link
Collaborator

Hello everyone, I have tested this PR and there're some test cases failed or needed improvement.

Please check test reports below for more information:

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs (2)

28-51: Fix subscription payload shape and harden deactivation against missing hook IDs.

  • The subscription payload still includes a top-level url (Line 30) in addition to consumerInputs.url. Azure DevOps service hook subscriptions expect url only under consumerInputs; the extra top-level field is unnecessary and can cause API validation issues.
  • deactivate calls deleteSubscription even when _getHookId() may return null/undefined, which will produce a bad DELETE call if activation failed or state is missing.

Apply a change along these lines:

 async activate() {
   const data = {
-    url: this.http.endpoint,
     publisherId: "tfs",
     resourceVersion: "1.0",
     consumerId: "webHooks",
     consumerActionId: "httpRequest",
     consumerInputs: {
       url: this.http.endpoint,
     },
@@
   },
   async deactivate() {
     const id = this._getHookId();
+    if (!id) {
+      console.log("No subscription ID found; skipping deletion");
+      return;
+    }
     await this.azureDevops.deleteSubscription(id);
   },

Also verify that "resourceVersion": "1.0" is valid for all supported event types (some examples use 1.0-preview.1).

For Azure DevOps service hook subscriptions, what is the documented request body schema for POST /_apis/hooks/subscriptions (specifically: where should the webhook URL be placed, and what resourceVersion values are valid for tfs publisher event types)?

53-67: Add minimal validation around generateMeta payload fields.

generateMeta assumes body.id and body.createdDate are always present and valid. A malformed or unexpected webhook payload will yield undefined IDs or NaN timestamps, which can break dedupe and ordering.

Consider guarding these fields and falling back to safe defaults or throwing a clear error, e.g.:

   generateMeta(body) {
+    if (!body || !body.id || !body.createdDate) {
+      console.warn("Unexpected Azure DevOps event body structure:", body);
+    }
+
     return {
-      id: body.id,
+      id: body?.id || String(Date.now()),
       summary: `New ${this.eventType} event with ID ${body?.id}`,
-      ts: Date.parse(body.createdDate),
+      ts: body?.createdDate ? Date.parse(body.createdDate) : Date.now(),
     };
   },

This keeps the source resilient if Azure DevOps changes the envelope slightly or if a test/misconfigured webhook hits the endpoint.

components/azure_devops_microsoft_entra_id_oauth/azure_devops_microsoft_entra_id_oauth.app.mjs (1)

6-29: Improve eventType options UX and align shape with projectId options.

eventType.options() currently returns a plain array of IDs, while projectId.options() returns { label, value } objects. For consistency and better UI, consider returning label/value pairs for event types as well:

   async options() {
     const types = await this.listEventTypes();
-    return types.filter(({ id }) => id !== "tfvc.checkin" && id !== "build.complete").map(({ id }) => id);
+    return types
+      .filter(({ id }) => id !== "tfvc.checkin" && id !== "build.complete")
+      .map((type) => ({
+        value: type.id,
+        label: type.name || type.id,
+      }));
   },

This preserves the stored ID while showing a more descriptive label in the UI.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 156b4b2 and 6e548fd.

📒 Files selected for processing (2)
  • components/azure_devops_microsoft_entra_id_oauth/azure_devops_microsoft_entra_id_oauth.app.mjs (1 hunks)
  • components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-08-27T17:25:10.425Z
Learnt from: jverce
Repo: PipedreamHQ/pipedream PR: 18187
File: packages/connect-react/src/utils/type-guards.ts:23-33
Timestamp: 2025-08-27T17:25:10.425Z
Learning: In the connect-react package, the isOptionWithLabel type guard intentionally restricts value types to string|number for runtime filtering purposes, even though LabelValueOption<T> allows any T. This runtime behavior should be preserved over type safety improvements.

Applied to files:

  • components/azure_devops_microsoft_entra_id_oauth/azure_devops_microsoft_entra_id_oauth.app.mjs
📚 Learning: 2025-09-15T22:01:11.472Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 18362
File: components/leonardo_ai/actions/generate-image/generate-image.mjs:103-105
Timestamp: 2025-09-15T22:01:11.472Z
Learning: In Pipedream components, pipedream/platform's axios implementation automatically excludes undefined values from HTTP requests, so there's no need to manually check for truthiness before including properties in request payloads.

Applied to files:

  • components/azure_devops_microsoft_entra_id_oauth/azure_devops_microsoft_entra_id_oauth.app.mjs
📚 Learning: 2024-10-10T19:18:27.998Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 14265
File: components/the_magic_drip/sources/common.mjs:35-43
Timestamp: 2024-10-10T19:18:27.998Z
Learning: In `components/the_magic_drip/sources/common.mjs`, when processing items in `getAndProcessData`, `savedIds` is intentionally updated with IDs of both emitted and non-emitted items to avoid emitting retroactive events upon first deployment and ensure only new events are emitted as they occur.

Applied to files:

  • components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs
📚 Learning: 2025-10-20T01:01:02.970Z
Learnt from: js07
Repo: PipedreamHQ/pipedream PR: 18744
File: components/slack_v2/actions/send-large-message/send-large-message.mjs:49-64
Timestamp: 2025-10-20T01:01:02.970Z
Learning: In components/slack_v2/actions/send-large-message/send-large-message.mjs, the metadata_event_payload prop is typed as string, so the code only needs to handle string-to-JSON parsing and does not need to handle object inputs.

Applied to files:

  • components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs
📚 Learning: 2025-07-09T18:07:12.426Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 17538
File: components/aircall/sources/new-sms/new-sms.mjs:19-25
Timestamp: 2025-07-09T18:07:12.426Z
Learning: In Aircall API webhook payloads, the `created_at` field is returned as an ISO 8601 string format (e.g., "2020-02-18T20:52:22.000Z"), not as milliseconds since epoch. For Pipedream components, this needs to be converted to milliseconds using `Date.parse()` before assigning to the `ts` field in `generateMeta()`.

Applied to files:

  • components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Verify TypeScript components
  • GitHub Check: pnpm publish
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Lint Code Base
🔇 Additional comments (2)
components/azure_devops_microsoft_entra_id_oauth/sources/new-event/new-event.mjs (2)

1-26: Source definition and props wiring look correct.

Importing the app, wiring azureDevops, db, http, and using propDefinition for eventType and projectId matches Pipedream patterns; no issues here.


68-72: Event handling and emit flow are straightforward and appropriate.

Extracting body from the incoming event, building meta via generateMeta, and emitting { body, meta } matches standard Pipedream source patterns; no changes needed.

@vunguyenhung
Copy link
Collaborator

Hi everyone, all test cases are passed! Ready for release!

Test reports

@michelle0927
Copy link
Collaborator Author

/approve

@michelle0927 michelle0927 merged commit d6edb6e into master Dec 16, 2025
9 checks passed
@michelle0927 michelle0927 deleted the issue-18106 branch December 16, 2025 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[APP] Azure DevOps (Microsoft Entra ID OAuth)

4 participants