Skip to content

Conversation

@michelle0927
Copy link
Collaborator

@michelle0927 michelle0927 commented Nov 10, 2025

Resolves #18999

Summary by CodeRabbit

  • Chores
    • Pipedrive connector bumped to 0.10.5 with incremental version updates across multiple actions and instant webhook sources.
  • New Features
    • Improved lead data formatting for updated-lead webhooks to better map custom fields into incoming lead records.

@vercel
Copy link

vercel bot commented Nov 10, 2025

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

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
pipedream-docs Ignored Ignored Nov 11, 2025 8:14pm
pipedream-docs-redirect-do-not-edit Ignored Ignored Nov 11, 2025 8:14pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

Walkthrough

Version bumps across multiple Pipedrive actions and sources, addition of a new utility formatLeadDataFromSource in common utils, and refactor of updated-lead-instant to use the new utility. Package version incremented to 0.10.5.

Changes

Cohort / File(s) Summary
Action version bumps
components/pipedrive/actions/add-activity/add-activity.mjs, components/pipedrive/actions/add-deal/add-deal.mjs, components/pipedrive/actions/add-lead/add-lead.mjs, components/pipedrive/actions/add-person/add-person.mjs, components/pipedrive/actions/search-persons/search-persons.mjs, components/pipedrive/actions/update-person/update-person.mjs
Incremented version fields across six actions (no logic or API changes)
Source version bumps
components/pipedrive/sources/updated-deal-instant/updated-deal-instant.mjs, components/pipedrive/sources/updated-person-instant/updated-person-instant.mjs
Bumped version from 0.1.6 → 0.1.7; no behavioral changes
Lead data utility addition
components/pipedrive/common/utils.mjs
Added exported formatLeadDataFromSource({ body, customFieldFn, resourceFn }) to map lead fields to custom field names and populate data.custom_fields; also formats previous.custom_fields when present
Updated lead instant refactor
components/pipedrive/sources/updated-lead-instant/updated-lead-instant.mjs
Replaced import/use of old parse helper with formatLeadDataFromSource; parseData(body) now calls the new utility; bumped version to 0.1.7
Package metadata
components/pipedrive/package.json
Package version bumped 0.10.4 → 0.10.5

Sequence Diagram

sequenceDiagram
    participant Source as updated-lead-instant
    participant Util as formatLeadDataFromSource
    participant PD as Pipedrive API

    rect rgb(240,248,255)
    Source->>Util: formatLeadDataFromSource({ body, customFieldFn, resourceFn })
    end

    rect rgb(245,245,245)
    Util->>PD: customFieldFn() (e.g. getDealCustomFields)
    PD-->>Util: custom field metadata
    Util->>PD: resourceFn(body.id) (e.g. getLead)
    PD-->>Util: lead data
    Util->>Util: map lead fields → custom field names (populate data.custom_fields)
    Util-->>Source: return body with data.custom_fields (and previous.custom_fields) populated
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review the new formatLeadDataFromSource for correctness, edge cases (missing/null fields), and async/error handling.
  • Verify updated-lead-instant calls the utility with correct functions (customFieldFn, resourceFn) and expected argument shapes.
  • Quick scan of action/source version bumps to ensure exported descriptors changed only in version fields.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Multiple version bumps and updates to other unrelated Pipedrive actions appear outside the scope of fixing updated-lead-instant, including add-activity, add-deal, add-lead, add-person, search-persons, and update-person. Review whether all version bumps are necessary for this fix. Consider splitting version updates into a separate maintenance PR if they are not directly related to issue #18999.
Description check ❓ Inconclusive The description is minimal but includes the linked issue number (#18999). However, it lacks detail about the changes made and why they were necessary. Expand the description to explain what changes were made to resolve the issue, such as the addition of formatLeadDataFromSource and modifications to the parseData implementation.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: enabling the updated-lead-instant trigger to return all custom fields in Pipedrive.
Linked Issues check ✅ Passed The PR addresses the bug by adding formatLeadDataFromSource function and updating updated-lead-instant to use it, returning all custom fields for leads as required by #18999.
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-18999

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

@michelle0927 michelle0927 marked this pull request as ready for review November 10, 2025 21:03
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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2d0c3e and c4d4eb5.

📒 Files selected for processing (11)
  • components/pipedrive/actions/add-activity/add-activity.mjs (1 hunks)
  • components/pipedrive/actions/add-deal/add-deal.mjs (1 hunks)
  • components/pipedrive/actions/add-lead/add-lead.mjs (1 hunks)
  • components/pipedrive/actions/add-person/add-person.mjs (1 hunks)
  • components/pipedrive/actions/search-persons/search-persons.mjs (1 hunks)
  • components/pipedrive/actions/update-person/update-person.mjs (1 hunks)
  • components/pipedrive/common/utils.mjs (1 hunks)
  • components/pipedrive/package.json (1 hunks)
  • components/pipedrive/sources/updated-deal-instant/updated-deal-instant.mjs (1 hunks)
  • components/pipedrive/sources/updated-lead-instant/updated-lead-instant.mjs (3 hunks)
  • components/pipedrive/sources/updated-person-instant/updated-person-instant.mjs (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 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/pipedrive/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/pipedrive/sources/updated-lead-instant/updated-lead-instant.mjs
🧬 Code graph analysis (1)
components/pipedrive/sources/updated-lead-instant/updated-lead-instant.mjs (1)
components/pipedrive/common/utils.mjs (2)
  • formatLeadDataFromSource (94-115)
  • formatLeadDataFromSource (94-115)
⏰ 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). (3)
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Lint Code Base
🔇 Additional comments (12)
components/pipedrive/package.json (1)

3-3: Version bump aligns with the component updates.
Matches the action/source metadata increments in this PR; no issues spotted.

components/pipedrive/actions/add-lead/add-lead.mjs (1)

9-9: Action version metadata looks good.
Increment to 0.0.12 stays in sync with the package release.

components/pipedrive/actions/add-activity/add-activity.mjs (1)

10-10: Version increment confirmed.
Metadata now reflects 0.1.18; consistent with the rollout.

components/pipedrive/actions/add-person/add-person.mjs (1)

9-9: Metadata version bump looks correct.
0.1.18 tracks with the package release numbers.

components/pipedrive/sources/updated-deal-instant/updated-deal-instant.mjs (1)

10-10: Source version update acknowledged.
Setting the descriptor to 0.1.7 keeps the source in step with this release.

components/pipedrive/actions/update-person/update-person.mjs (1)

9-9: Action version bump confirmed.
0.0.10 is consistent with the other component updates.

components/pipedrive/actions/search-persons/search-persons.mjs (1)

11-11: Version metadata matches the release plan.
Setting 0.1.18 keeps this action aligned with the package bump.

components/pipedrive/actions/add-deal/add-deal.mjs (1)

9-9: Version increment looks good.
Updating to 0.1.19 keeps the action’s metadata aligned with this release.

components/pipedrive/sources/updated-person-instant/updated-person-instant.mjs (1)

10-10: LGTM: Version bump aligns with package update.

This version bump is coordinated with the package-level version update to 0.10.5.

components/pipedrive/sources/updated-lead-instant/updated-lead-instant.mjs (3)

1-1: LGTM: Import updated for new utility function.

The import correctly switches to the new formatLeadDataFromSource function that provides more comprehensive custom field handling.


10-10: LGTM: Version bump reflects functional changes.


24-30: No changes required—the code is correct.

Leads do not have separate custom fields; they share the same custom field definitions as Deals. The Pipedrive API has no distinct "lead custom fields" endpoint. Using this.pipedrive.getDealCustomFields is the correct and intended approach for retrieving custom field definitions for leads. The original concern was based on a false assumption about the API structure.

Likely an incorrect or invalid review comment.

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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4d4eb5 and 1fae870.

📒 Files selected for processing (1)
  • components/pipedrive/common/utils.mjs (1 hunks)
⏰ 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: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: pnpm publish
  • GitHub Check: Lint Code Base

jcortes
jcortes previously approved these changes Nov 10, 2025
Copy link
Collaborator

@jcortes jcortes 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 (1)
components/pipedrive/common/utils.mjs (1)

109-119: Critical: Extract .value from webhook custom field structure.

Lines 115-116 read from body.previous.custom_fields[key], which comes from the webhook payload. According to parseCustomFields (line 32), webhook custom fields have a .value property. Line 116 stores the entire object instead of extracting .value, creating a structure mismatch with the current custom fields at line 105 (which stores direct values from the API).

Additionally, line 115's check will exclude valid falsy values.

Apply this diff to extract .value and handle falsy values:

   const formattedPreviousCustomFields = {};
   if (body?.previous?.custom_fields) {
     for (const [
       key,
       value,
     ] of Object.entries(customFieldNames)) {
-      if (body.previous.custom_fields[key]) {
-        formattedPreviousCustomFields[value] = body.previous.custom_fields[key];
+      if (body.previous.custom_fields[key]?.value !== undefined) {
+        formattedPreviousCustomFields[value] = body.previous.custom_fields[key].value;
       }
     }
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1fae870 and 91f7b95.

📒 Files selected for processing (1)
  • components/pipedrive/common/utils.mjs (1 hunks)
⏰ 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: pnpm publish
  • GitHub Check: Lint Code Base
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
🔇 Additional comments (1)
components/pipedrive/common/utils.mjs (1)

120-132: Verify the conditional logic for including previous in the return value.

Line 126 only includes previous in the return value if body.previous?.custom_fields exists. If body.previous exists but doesn't have custom_fields, other fields from previous (if any) will be omitted from the output.

If body.previous is always present for update events (as suggested by line 45 in parseData), consider simplifying to:

-    ...(body.previous?.custom_fields && {
+    ...(body.previous && {
       previous: {
         ...body.previous,
         custom_fields: formattedPreviousCustomFields,
       },
     }),

This ensures all previous fields are preserved even if custom_fields is absent. Please verify whether body.previous can exist without custom_fields in your webhook payloads.

Comment on lines +94 to +107
export const formatLeadDataFromSource = async ({
body, customFieldFn, resourceFn,
}) => {
const customFieldNames = await getCustomFieldNames(customFieldFn);
const { data: lead } = await resourceFn(body.data.id);
const formattedCustomFields = {};
for (const [
key,
value,
] of Object.entries(customFieldNames)) {
if (lead[key]) {
formattedCustomFields[value] = lead[key];
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider handling falsy custom field values.

Line 104 checks if (lead[key]), which will exclude valid falsy values like 0, false, or empty strings. If custom fields can legitimately have these values, use a more precise check.

Apply this diff to handle falsy values correctly:

   for (const [
     key,
     value,
   ] of Object.entries(customFieldNames)) {
-    if (lead[key]) {
+    if (lead[key] !== undefined) {
       formattedCustomFields[value] = lead[key];
     }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const formatLeadDataFromSource = async ({
body, customFieldFn, resourceFn,
}) => {
const customFieldNames = await getCustomFieldNames(customFieldFn);
const { data: lead } = await resourceFn(body.data.id);
const formattedCustomFields = {};
for (const [
key,
value,
] of Object.entries(customFieldNames)) {
if (lead[key]) {
formattedCustomFields[value] = lead[key];
}
}
export const formatLeadDataFromSource = async ({
body, customFieldFn, resourceFn,
}) => {
const customFieldNames = await getCustomFieldNames(customFieldFn);
const { data: lead } = await resourceFn(body.data.id);
const formattedCustomFields = {};
for (const [
key,
value,
] of Object.entries(customFieldNames)) {
if (lead[key] !== undefined) {
formattedCustomFields[value] = lead[key];
}
}
🤖 Prompt for AI Agents
In components/pipedrive/common/utils.mjs around lines 94 to 107, the check `if
(lead[key])` wrongly filters out valid falsy custom field values (0, false, ""),
so change it to test presence rather than truthiness; replace that condition
with a presence check such as `if (Object.prototype.hasOwnProperty.call(lead,
key) && lead[key] !== null && lead[key] !== undefined)` so falsy-but-valid
values are included while still excluding missing or null/undefined fields.

@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:

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.

[BUG] Return all custom fields in Pipedrive trigger updated-lead-instant

4 participants