Skip to content

Conversation

@michelle0927
Copy link
Collaborator

@michelle0927 michelle0927 commented Dec 3, 2025

Resolves #13339

Summary by CodeRabbit

  • New Features

    • Added three Growsurf event sources: Campaign Completed, New Participant Added, and New Campaign Referral Made.
    • Campaign ID now provides dynamic options populated from your Growsurf account for easier configuration.
  • Chores

    • Growsurf integration bumped to v0.1.0 and underlying API request handling improved.

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

@vercel
Copy link

vercel bot commented Dec 3, 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 Dec 3, 2025 6:28pm
pipedream-docs-redirect-do-not-edit Ignored Ignored Dec 3, 2025 6:28pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

Walkthrough

Adds a GrowSurf integration: a request layer with pagination, a polling-source base class, and three polling sources (campaign-completed, new-participant-added, new-campaign-referral-made). Also bumps package version and adds a platform dependency.

Changes

Cohort / File(s) Summary
Core API Integration
components/growsurf/growsurf.app.mjs
Added _baseUrl() and _makeRequest() for authenticated HTTP calls, public API methods listCampaigns(), listParticipants(), listReferrals(), an async generator paginate() for paginated resources, and a dynamic campaignId prop with options resolver.
Package Metadata
components/growsurf/package.json
Bumped version 0.0.40.1.0. Added dependency "@pipedream/platform": "^3.1.1".
Base Polling Source
components/growsurf/sources/common/base.mjs
New reusable polling source base with props (growsurf, db, timer), state accessors _getLastTs()/_setLastTs(), abstract getResources()/generateMeta() stubs, processEvent(max), and lifecycle hooks (deploy(), run()).
Campaign-Completed Source
components/growsurf/sources/campaign-completed/campaign-completed.mjs
New source extending common base; getResources() returns campaigns filtered by status === "COMPLETE", generateMeta() creates id/summary/ts.
New Participant Source
components/growsurf/sources/new-participant-added/new-participant-added.mjs
New source with campaignId prop; getResources(max) paginates participants via growsurf.paginate(), filters by created timestamp, updates last-ts; generateMeta() builds id/summary/ts.
New Referral Source
components/growsurf/sources/new-campaign-referral-made/new-campaign-referral-made.mjs
New source with campaignId prop; getResources(max) paginates referrals with timestamp filtering and state updates; generateMeta() builds metadata from referral.

Sequence Diagram(s)

sequenceDiagram
    participant Timer
    participant Source as Polling Source
    participant Base as Base Class (base.mjs)
    participant App as GrowSurf App (growsurf.app.mjs)
    participant API as GrowSurf API
    participant DB as Pipedream DB

    Timer->>Source: trigger run()
    Source->>Base: run()
    Base->>Base: processEvent()
    Base->>Source: getResources(max)
    Source->>DB: _getLastTs()
    DB-->>Source: lastTs
    Source->>App: paginate(fn=listParticipants/listReferrals, args={campaignId,...}, resourceKey, max)
    loop pages
      App->>API: GET /... (with nextId)
      API-->>App: items batch + nextId
      App-->>Source: yield item
      Source->>Source: if item.createdAt > lastTs -> collect
      Source->>DB: _setLastTs(newMaxTs)
    end
    Source-->>Base: return filtered items
    Base->>Source: generateMeta(item)
    Source-->>Base: {id, summary, ts}
    Base->>Base: emit(item, {meta})
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify pagination generator handles nextId termination, respects max, and yields correct items.
  • Review timestamp persistence/ordering in _getLastTs()/_setLastTs() and their usage in each source to avoid duplicates or gaps.
  • Confirm campaignId prop options resolver uses listCampaigns() safely (error handling, rate limits).
  • Inspect _makeRequest() for correct Authorization header handling, error propagation, and path construction.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is minimal and only references the issue number. It does not follow the provided template that requires a 'WHY' section explaining the motivation for the changes. Complete the description by adding a 'WHY' section explaining the purpose of these GrowSurf components, as specified in the repository template.
Linked Issues check ⚠️ Warning The PR implements polling-based sources (campaign-completed, new-participant-added, new-campaign-referral-made) rather than webhook sources as specified in issue #13339. Implement webhook sources as required: campaign-ended-instant, new-participant-referral-instant, and new-participant-instant, rather than polling-based sources.
Title check ❓ Inconclusive The title 'GrowSurf - new components' is vague and generic. While it mentions GrowSurf, it does not convey specific information about which components are being added or their primary functionality. Consider a more specific title that describes the main functionality, such as 'Add GrowSurf webhook sources for campaign and participant events' or 'GrowSurf: Add webhook sources for campaign completion and participant referrals'.
✅ Passed checks (2 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed While the implementation approach differs from requirements, the added components are within scope for the GrowSurf integration. The base infrastructure (API integration, app component) supports the intended functionality.
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-13339

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 6512c92 and f2270b7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • components/growsurf/growsurf.app.mjs (1 hunks)
  • components/growsurf/package.json (2 hunks)
  • components/growsurf/sources/campaign-completed/campaign-completed.mjs (1 hunks)
  • components/growsurf/sources/common/base.mjs (1 hunks)
  • components/growsurf/sources/new-campaign-referral-made/new-campaign-referral-made.mjs (1 hunks)
  • components/growsurf/sources/new-participant-added/new-participant-added.mjs (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 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/growsurf/package.json
📚 Learning: 2024-07-24T02:06:47.016Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-07-24T02:06:47.016Z
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/growsurf/sources/new-campaign-referral-made/new-campaign-referral-made.mjs
  • components/growsurf/sources/new-participant-added/new-participant-added.mjs
📚 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/growsurf/growsurf.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/growsurf/growsurf.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/growsurf/sources/new-participant-added/new-participant-added.mjs
🧬 Code graph analysis (2)
components/growsurf/sources/new-campaign-referral-made/new-campaign-referral-made.mjs (2)
components/growsurf/sources/common/base.mjs (1)
  • results (31-31)
components/growsurf/sources/new-participant-added/new-participant-added.mjs (4)
  • results (23-32)
  • lastTs (34-34)
  • maxTs (35-35)
  • ts (37-37)
components/growsurf/growsurf.app.mjs (2)
components/elastic_email/actions/update-campaign/update-campaign.mjs (1)
  • campaign (105-108)
components/zep/actions/get-threads/get-threads.mjs (1)
  • max (39-39)
⏰ 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: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Lint Code Base
🔇 Additional comments (8)
components/growsurf/package.json (1)

3-16: LGTM!

Version bump to 0.1.0 is appropriate for introducing new features, and the @pipedream/platform dependency is correctly added to support the new API integration layer.

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

20-56: LGTM!

The request helper and API methods are well-structured with proper authentication and consistent patterns.


57-78: LGTM!

The pagination helper correctly implements cursor-based pagination with the nextId parameter and supports limiting results via the max parameter.

components/growsurf/sources/new-campaign-referral-made/new-campaign-referral-made.mjs (2)

50-56: LGTM!

The generateMeta method provides a clear summary with appropriate fallback from email to ID.


36-47: > Likely an incorrect or invalid review comment.

components/growsurf/sources/campaign-completed/campaign-completed.mjs (1)

17-23: LGTM!

Using Date.now() for the timestamp is appropriate here since we're detecting campaign completion status rather than a creation event.

components/growsurf/sources/common/base.mjs (1)

30-48: LGTM!

The processEvent method correctly iterates over resources and emits events with generated metadata. The deploy hook sensibly limits initial fetch to 10 items.

components/growsurf/sources/new-participant-added/new-participant-added.mjs (1)

33-47: Critical: Data loss when max truncates results.

The maxTs is updated based on all collected participants (line 43), but the array is truncated afterward (lines 44-46). If there are more participants than max, the skipped participants will never be emitted because lastTs advances past them.

Apply this diff to only track maxTs for participants that will actually be returned:

      const participants = [];
      const lastTs = this._getLastTs();
      let maxTs = lastTs;
      for await (const participant of results) {
        const ts = participant.createdAt;
        if (ts > lastTs) {
          participants.push(participant);
-         maxTs = Math.max(ts, maxTs);
+         if (!max || participants.length <= max) {
+           maxTs = Math.max(ts, maxTs);
+         }
        }
      }
      this._setLastTs(maxTs);
      if (max && participants.length > max) {
        participants.length = max;
      }
      return participants;

Alternatively, compute maxTs from the final truncated array before persisting.

⛔ Skipped due to learnings
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.

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 f2270b7 and 4fe4911.

📒 Files selected for processing (3)
  • components/growsurf/growsurf.app.mjs (1 hunks)
  • components/growsurf/sources/common/base.mjs (1 hunks)
  • components/growsurf/sources/new-participant-added/new-participant-added.mjs (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 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/growsurf/sources/new-participant-added/new-participant-added.mjs
📚 Learning: 2024-07-24T02:06:47.016Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-07-24T02:06:47.016Z
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/growsurf/sources/new-participant-added/new-participant-added.mjs
📚 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/growsurf/growsurf.app.mjs
📚 Learning: 2024-10-08T16:42:59.225Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 14229
File: components/americommerce/actions/update-customer/update-customer.mjs:89-94
Timestamp: 2024-10-08T16:42:59.225Z
Learning: When defining boolean properties in AmeriCommerce components (e.g., in `update-customer.mjs`), ensure that the label and description are consistent and clearly indicate the intent, especially when using negations like "No Account", to avoid confusion.

Applied to files:

  • components/growsurf/growsurf.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/growsurf/growsurf.app.mjs
🧬 Code graph analysis (3)
components/growsurf/sources/new-participant-added/new-participant-added.mjs (2)
components/growsurf/sources/common/base.mjs (1)
  • results (31-31)
components/growsurf/sources/new-campaign-referral-made/new-campaign-referral-made.mjs (4)
  • results (23-34)
  • lastTs (36-36)
  • maxTs (37-37)
  • ts (39-39)
components/growsurf/sources/common/base.mjs (3)
components/growsurf/sources/new-participant-added/new-participant-added.mjs (2)
  • lastTs (34-34)
  • results (23-32)
components/growsurf/sources/new-campaign-referral-made/new-campaign-referral-made.mjs (2)
  • lastTs (36-36)
  • results (23-34)
components/zep/actions/get-threads/get-threads.mjs (1)
  • max (39-39)
components/growsurf/growsurf.app.mjs (1)
components/zep/actions/get-threads/get-threads.mjs (1)
  • max (39-39)
⏰ 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
🔇 Additional comments (4)
components/growsurf/sources/common/base.mjs (1)

1-49: LGTM! Base class follows standard abstract pattern.

The polling source base class is well-structured with:

  • Proper abstract method enforcement via ConfigurationError
  • Clean state management for timestamp tracking
  • Standard deploy/run lifecycle hooks

The previous concern about getResourceFn vs getResources has been addressed.

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

6-56: LGTM! API integration methods are well-structured.

The request wrapper, authentication header, and API endpoint methods follow standard patterns. The campaignId prop definition with async options provides a good user experience.


57-78: Paginate logic looks correct for cursor-based pagination.

The async generator properly:

  • Yields items incrementally
  • Respects the max limit
  • Handles cursor-based pagination via nextId

Minor note: Line 60 mutates args.params, which is intentional for maintaining pagination state but could theoretically cause issues if args is reused externally. Given this is an internal helper, it's acceptable.

components/growsurf/sources/new-participant-added/new-participant-added.mjs (1)

49-59: LGTM! Name handling properly addresses missing fields.

The generateMeta implementation correctly handles cases where firstName or lastName might be undefined by using filter(Boolean) and providing fallbacks to email or id. This prevents "undefined" from appearing in summaries.

Copy link
Collaborator

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

For Integration QA:

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.

[Components] growsurf

4 participants