Skip to content

Conversation

@michelle0927
Copy link
Collaborator

@michelle0927 michelle0927 commented Nov 5, 2025

Resolves #18939

Summary by CodeRabbit

  • New Features

    • Option to include all custom fields when searching for persons.
  • Improvements

    • Search can return human-friendly custom field names and early-exit with "No persons found".
    • Search UI labels refined for consistent capitalization and wording.
  • Chores

    • Version bumps across multiple Pipedrive actions, sources, and package metadata.

@vercel
Copy link

vercel bot commented Nov 5, 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 6, 2025 8:19pm
pipedream-docs-redirect-do-not-edit Ignored Ignored Nov 6, 2025 8:19pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 5, 2025

Walkthrough

Patch-level version bumps across many Pipedrive actions and sources; adds a new formatCustomFields utility, an includeAllCustomFields boolean prop (app + search-persons action), and conditional custom field formatting plus minor UI label capitalizations in search-persons.

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-note/add-note.mjs, components/pipedrive/actions/add-organization/add-organization.mjs, components/pipedrive/actions/add-person/add-person.mjs, components/pipedrive/actions/get-lead-by-id/get-lead-by-id.mjs, components/pipedrive/actions/get-person-details/get-person-details.mjs, components/pipedrive/actions/merge-deals/merge-deals.mjs, components/pipedrive/actions/merge-persons/merge-persons.mjs, components/pipedrive/actions/remove-duplicate-notes/remove-duplicate-notes.mjs, components/pipedrive/actions/search-leads/search-leads.mjs, components/pipedrive/actions/search-notes/search-notes.mjs, components/pipedrive/actions/update-deal/update-deal.mjs, components/pipedrive/actions/update-person/update-person.mjs
Patch version increments only (no behavioral changes).
search-persons Action Enhancement
components/pipedrive/actions/search-persons/search-persons.mjs
Version bump; added includeAllCustomFields prop; imports and conditionally uses formatCustomFields to remap custom field keys to names; early exit when no persons found; UI label capitalization and description tweaks.
Custom Fields Utility
components/pipedrive/common/utils.mjs
Added exported formatCustomFields(resp, getResourcesFn, getFieldsFn) and internal getCustomFieldNames(fn) to fetch field definitions and remap item.custom_fields keys to human-friendly names.
App Configuration
components/pipedrive/pipedrive.app.mjs
Added public prop includeAllCustomFields (boolean) and updated searchPersons to use Persons API v2.
Source Version Bumps
components/pipedrive/sources/new-deal-instant/new-deal-instant.mjs, components/pipedrive/sources/new-event-instant/new-event-instant.mjs, components/pipedrive/sources/new-person-instant/new-person-instant.mjs, components/pipedrive/sources/updated-deal-instant/updated-deal-instant.mjs, components/pipedrive/sources/updated-lead-instant/updated-lead-instant.mjs, components/pipedrive/sources/updated-person-instant/updated-person-instant.mjs
Patch version increments only (no behavioral changes).
Package Version
components/pipedrive/package.json
Package version bumped from 0.10.3 to 0.10.4.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Search as search-persons Action
    participant App as Pipedrive App
    participant Utils as formatCustomFields
    participant FieldsAPI as getPersonCustomFields
    participant PersonsAPI as Persons API (v2)

    User->>Search: Run search-persons (includeAllCustomFields = true)
    Search->>App: call searchPersons (uses Persons API v2)
    App->>PersonsAPI: search persons
    PersonsAPI-->>Search: resp (items with custom_fields)
    alt no persons found
        Search-->>User: Summary "No persons found"
    else includeAllCustomFields enabled
        Search->>Utils: formatCustomFields(resp, getPersons, getPersonCustomFields)
        Utils->>FieldsAPI: fetch field definitions (key → name)
        FieldsAPI-->>Utils: field mappings
        Utils->>PersonsAPI: fetch person resources (ids)
        PersonsAPI-->>Utils: person resources
        Utils-->>Search: transformed resp (custom_fields remapped)
        Search-->>User: Return results with formatted custom fields
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Focus areas:
    • components/pipedrive/common/utils.mjs: verify correctness of field-mapping logic, async flows, and edge-case handling (empty/missing fields, value types).
    • components/pipedrive/actions/search-persons/search-persons.mjs: validate integration, early-exit path, and new public prop usage.
    • components/pipedrive/pipedrive.app.mjs: confirm public prop definition and Persons API v2 change.

Possibly related PRs

Suggested labels

ai-assisted

Suggested reviewers

  • jcortes

Pre-merge checks and finishing touches

❌ Failed checks (2 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description is minimal but references the resolved issue number (#18939). However, it does not follow the provided template structure with a WHY section. Consider expanding the description using the provided template structure, specifically filling in the WHY section to explain the motivation and context for these changes.
Out of Scope Changes check ❓ Inconclusive The PR includes version bumps across multiple files beyond search-persons changes and Pipedrive app modifications, which appear justified as maintenance updates but represent scope expansion beyond the core custom fields feature. Clarify whether the widespread version bumps across all actions and sources are intentional as part of a coordinated release, or if scope should be limited to search-persons and related utilities.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: adding custom field support to search-persons, addressing issue #18939 about missing dropdown-type custom fields.
Linked Issues check ✅ Passed The PR implements functionality to fetch dropdown-type custom fields in search-persons via formatCustomFields utility and includeAllCustomFields flag, directly addressing issue #18939's requirement to include all custom field types.
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-18939

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

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ccd2b4 and aa97d2b.

📒 Files selected for processing (25)
  • 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-note/add-note.mjs (1 hunks)
  • components/pipedrive/actions/add-organization/add-organization.mjs (1 hunks)
  • components/pipedrive/actions/add-person/add-person.mjs (1 hunks)
  • components/pipedrive/actions/get-lead-by-id/get-lead-by-id.mjs (1 hunks)
  • components/pipedrive/actions/get-person-details/get-person-details.mjs (1 hunks)
  • components/pipedrive/actions/merge-deals/merge-deals.mjs (1 hunks)
  • components/pipedrive/actions/merge-persons/merge-persons.mjs (1 hunks)
  • components/pipedrive/actions/remove-duplicate-notes/remove-duplicate-notes.mjs (1 hunks)
  • components/pipedrive/actions/search-leads/search-leads.mjs (1 hunks)
  • components/pipedrive/actions/search-notes/search-notes.mjs (1 hunks)
  • components/pipedrive/actions/search-persons/search-persons.mjs (4 hunks)
  • components/pipedrive/actions/update-deal/update-deal.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/pipedrive.app.mjs (2 hunks)
  • components/pipedrive/sources/new-deal-instant/new-deal-instant.mjs (1 hunks)
  • components/pipedrive/sources/new-event-instant/new-event-instant.mjs (1 hunks)
  • components/pipedrive/sources/new-person-instant/new-person-instant.mjs (1 hunks)
  • components/pipedrive/sources/updated-deal-instant/updated-deal-instant.mjs (1 hunks)
  • components/pipedrive/sources/updated-lead-instant/updated-lead-instant.mjs (1 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: 2025-06-04T17:52:05.780Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 16954
File: components/salesloft/salesloft.app.mjs:14-23
Timestamp: 2025-06-04T17:52:05.780Z
Learning: In the Salesloft API integration (components/salesloft/salesloft.app.mjs), the _makeRequest method returns response.data which directly contains arrays for list endpoints like listPeople, listCadences, listUsers, and listAccounts. The propDefinitions correctly call .map() directly on these responses without needing to destructure a nested data property.

Applied to files:

  • components/pipedrive/pipedrive.app.mjs
  • components/pipedrive/actions/search-persons/search-persons.mjs
🧬 Code graph analysis (2)
components/pipedrive/common/utils.mjs (2)
components/pipedrive/actions/search-persons/search-persons.mjs (1)
  • resp (73-82)
components/pipedrive/pipedrive.app.mjs (1)
  • persons (32-38)
components/pipedrive/actions/search-persons/search-persons.mjs (1)
components/pipedrive/common/utils.mjs (2)
  • formatCustomFields (59-85)
  • formatCustomFields (59-85)
⏰ 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 (25)
components/pipedrive/sources/new-person-instant/new-person-instant.mjs (1)

9-9: LGTM! Standard version bump.

The patch version increment is appropriate and consistent with the PR's updates across Pipedrive components.

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

9-9: Version bump only—core functionality changes missing.

This file shows only a version bump. The PR's core functionality (formatCustomFields utility, includeAllCustomFields prop, search-persons logic changes) is not visible in the provided files. Verify that components/pipedrive/actions/search-persons/search-persons.mjs and components/pipedrive/common/utils.mjs are included in this PR and contain the stated changes.

components/pipedrive/package.json (1)

1-21: Package version and dependencies look good.

The version bump to 0.10.4 aligns with the broader release pattern across actions and sources. No new external dependencies were introduced—the feature is implemented via internal utilities. Dependencies are stable and appropriate.

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

8-8: Version bump looks good.

This metadata-only update aligns with the coordinated package-wide version bumps across Pipedrive components.

components/pipedrive/actions/get-person-details/get-person-details.mjs (1)

8-8: Version bump looks good.

Metadata-only update consistent with the PR's coordinated versioning strategy.

components/pipedrive/sources/new-event-instant/new-event-instant.mjs (1)

8-8: Version bump looks good.

Metadata-only update aligned with package-wide versioning.

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

7-7: Version bump looks good.

Metadata-only update consistent with coordinated package versioning.

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

10-10: Version bump looks good.

Metadata-only update aligned with the PR's versioning strategy.

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

10-10: Version bump looks good.

Metadata-only update consistent with coordinated package versioning.

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

9-9: Version bump looks good.

Metadata-only update aligned with the PR's coordinated versioning.

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

10-10: Version bump looks good.

Metadata-only update consistent with the package-wide versioning strategy.

components/pipedrive/actions/remove-duplicate-notes/remove-duplicate-notes.mjs (1)

8-8: LGTM: Version bump

Standard version increment as part of the package release cycle.

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

7-7: LGTM: Version bump

Standard version increment as part of the package release cycle.

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

9-9: LGTM: Version bump

Standard version increment as part of the package release cycle.

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

10-10: LGTM: Version bump

Standard version increment as part of the package release cycle.

components/pipedrive/actions/get-lead-by-id/get-lead-by-id.mjs (1)

7-7: LGTM: Version bump

Standard version increment as part of the package release cycle.

components/pipedrive/common/utils.mjs (1)

49-57: LGTM: Custom field name mapping

The logic correctly filters user-created custom fields and builds a key-to-name mapping.

components/pipedrive/pipedrive.app.mjs (2)

373-378: LGTM: New feature flag added

The includeAllCustomFields prop definition is correctly structured with appropriate metadata.


488-491: LGTM: API version upgrade

The switch to v2 PersonsApi aligns with the new custom fields feature and ensures compatibility with the enhanced search functionality.

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

5-5: LGTM: Import added

Correct import of the new formatCustomFields utility.


11-11: LGTM: Version bump

Version increment reflects the new feature addition.


22-22: LGTM: Label capitalization improvements

The label text updates improve consistency and readability in the UI.

Also applies to: 27-27, 34-34, 47-47, 54-54, 61-61


64-69: LGTM: Feature flag integration

Correctly references the new includeAllCustomFields prop definition from the app.


84-87: LGTM: Early exit for empty results

Good UX improvement - provides clear feedback when no persons are found instead of returning an empty structure.


89-95: Verify bound method compatibility and consider immutability

Two considerations:

  1. The code directly mutates resp.data.items (line 90). While this works, returning a new response object would be more predictable and safer for downstream consumers.

  2. Verify that this.pipedriveApp.getPersons.bind(this) correctly passes the bound context, since formatCustomFields calls the function with an ids parameter that may not match the expected method signature.

Consider this refactor to avoid mutation:

       if (this.includeAllCustomFields) {
-        resp.data.items = await formatCustomFields(
+        const formattedItems = await formatCustomFields(
           resp,
           this.pipedriveApp.getPersons.bind(this),
           this.pipedriveApp.getPersonCustomFields.bind(this),
         );
+        resp = {
+          ...resp,
+          data: {
+            ...resp.data,
+            items: formattedItems,
+          },
+        };
       }

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)

60-62: Fix parameter type and implement batching for large result sets.

Two unresolved issues from previous review:

  1. Type mismatch (critical): The Pipedrive v2 PersonsApi expects ids as a comma-separated string (e.g., "1,2,3"), but line 61 passes an array. This will cause the API call to fail or return unexpected results.

  2. Missing batching (major): The API accepts a maximum of 100 IDs per request. For search results with more than 100 persons, this will either fail or silently truncate the data, leading to incomplete custom field formatting.

Apply this diff to fix the type conversion and add batching:

-  const { data: persons } = await getResourcesFn({
-    ids: resp.data.items.map((item) => item.item.id),
-  });
+  const ids = resp.data.items.map((item) => item.item.id);
+  const batchSize = 100;
+  const batches = [];
+  
+  for (let i = 0; i < ids.length; i += batchSize) {
+    const batchIds = ids.slice(i, i + batchSize).join(',');
+    const { data: batchPersons } = await getResourcesFn({
+      ids: batchIds,
+    });
+    batches.push(...batchPersons);
+  }
+  
+  const persons = batches;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa97d2b and 51b4f6b.

📒 Files selected for processing (1)
  • components/pipedrive/common/utils.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
components/pipedrive/common/utils.mjs (2)
components/pipedrive/actions/search-persons/search-persons.mjs (1)
  • resp (73-82)
components/pipedrive/pipedrive.app.mjs (1)
  • persons (32-38)
⏰ 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: Lint Code Base
  • GitHub Check: Ensure component commits modify component versions
  • GitHub Check: Verify TypeScript components
🔇 Additional comments (4)
components/pipedrive/common/utils.mjs (4)

49-57: LGTM! Clean helper function.

The getCustomFieldNames helper correctly filters user-created custom fields and builds a key-to-name mapping for downstream formatting.


65-68: Good fix: Object check correctly implemented.

The guard now properly checks whether custom_fields is an object with keys, addressing the previous review concern about treating it as an array.


73-81: Good fix: Unmapped fields are now skipped.

The guard at line 78 correctly prevents assignment when customFieldNames[key] is undefined, addressing the previous concern about unmapped custom fields.


82-88: LGTM! Clean object merging.

The return statement correctly preserves the original person structure while updating the custom_fields with formatted values.

GTFalcao
GTFalcao previously approved these changes Nov 5, 2025
Copy link
Collaborator

@GTFalcao GTFalcao left a comment

Choose a reason for hiding this comment

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

LGTM!

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

60-62: Critical: Fix ids parameter type and implement batching.

Two critical issues remain unresolved from previous review:

  1. Type mismatch: Line 61 passes an array to ids, but the Pipedrive v2 PersonsApi expects a comma-separated string (e.g., "1,2,3"). This will cause the API call to fail or behave unexpectedly.

  2. Missing batching: The Pipedrive API supports a maximum of 100 IDs per request. Search results with >100 persons will either fail or silently truncate, causing incomplete custom field data.

Apply this diff to fix the type and add batching:

-  const { data: persons } = await getResourcesFn({
-    ids: resp.data.items.map((item) => item.item.id),
-  });
+  const allIds = resp.data.items.map((item) => item.item.id);
+  const batches = [];
+  for (let i = 0; i < allIds.length; i += 100) {
+    batches.push(allIds.slice(i, i + 100));
+  }
+  
+  const personBatches = await Promise.all(
+    batches.map((batch) => getResourcesFn({ ids: batch.join(',') }))
+  );
+  const persons = personBatches.flatMap((batch) => batch.data);

66-74: Critical: Destructuring undefined throws before guards execute.

Line 66 destructures custom_fields immediately from persons.find(), but if the person ID doesn't exist in the fetched persons array, find() returns undefined and the destructuring throws a runtime error before the guards on lines 68 and 72 can handle it.

Additionally, lines 68 and 72 contain redundant checks for customFields.length === 0.

Apply this diff to assign before checking and eliminate redundancy:

-    const { custom_fields: customFields } = persons.find((p) => p.id === person.item.id);
-
-    if (!person.item?.custom_fields || Object.keys(customFields).length === 0) {
-      return person;
-    }
-
-    if (!customFields || Object.keys(customFields).length === 0) {
+    const foundPerson = persons.find((p) => p.id === person.item.id);
+    if (!foundPerson?.custom_fields || Object.keys(foundPerson.custom_fields).length === 0) {
       return person;
     }
+    const customFields = foundPerson.custom_fields;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51b4f6b and c86a104.

📒 Files selected for processing (1)
  • components/pipedrive/common/utils.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
components/pipedrive/common/utils.mjs (2)
components/pipedrive/actions/search-persons/search-persons.mjs (1)
  • resp (73-82)
components/pipedrive/pipedrive.app.mjs (1)
  • persons (32-38)
⏰ 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: Verify TypeScript components
  • GitHub Check: Publish TypeScript components
🔇 Additional comments (2)
components/pipedrive/common/utils.mjs (2)

49-57: LGTM: Clean helper for custom field name mapping.

The logic correctly filters user-created fields and builds a key-to-name mapping for downstream formatting.


76-83: LGTM: Guard correctly prevents undefined keys.

The check at line 80 ensures only mapped custom fields are included in the formatted output, preventing properties with undefined keys.

@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 49175b5 into master Nov 7, 2025
10 checks passed
@michelle0927 michelle0927 deleted the issue-18939 branch November 7, 2025 16:32
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] Fetch the data values for a dropdown field in Pipedrive

4 participants