Skip to content

Conversation

@michelle0927
Copy link
Collaborator

@michelle0927 michelle0927 commented Dec 12, 2025

Resolves #13310

Summary by CodeRabbit

  • New Features

    • Full Canny integration: Create Post, Create Comment, Change Post Status, Get Post actions; three new event sources (new comment, new vote, post status changed).
    • Dynamic resource pickers and server-side pagination for boards, posts, users, companies, tags, categories, and comments.
    • Reusable polling base, generic paginator, and parseObject utility; added POST status options.
  • Chores

    • Component version bumped to 0.7.0.

✏️ 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 16, 2025 3:53pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

Walkthrough

Adds a complete Canny integration: an app client with HTTP + pagination, action modules (create/get post, create comment, change post status), a parse utility, a polling base, three polling sources (comments, votes, status changes), and bumps package version to 0.7.0.

Changes

Cohort / File(s) Summary
Core App Integration
components/canny/canny.app.mjs
New app client: _baseUrl(), centralized _makeRequest() using axios and this.$auth, endpoint helpers (getPost, listBoards, listPosts, listComments, listVotes, listStatusChanges, listUsers, listCompanies, listTags, listCategories, createPost, createComment, updatePostStatus) and an async paginate() generator. Adds dynamic propDefinitions for boardId, postId, userId, companyId, tagId, categoryId, commentId; defines DEFAULT_PAGE_SIZE.
Action Modules
components/canny/actions/create-post/create-post.mjs, components/canny/actions/create-comment/create-comment.mjs, components/canny/actions/get-post/get-post.mjs, components/canny/actions/change-post-status/change-post-status.mjs
Four new action exports that call corresponding this.canny methods: Create Post (maps inputs, parses customFields), Create Comment (requires value or imageUrls, maps fields), Get Post (fetch by id or urlName), Change Post Status (maps changerId, shouldNotifyVoters, status using POST_STATUSES). Each exports a summary and returns the API response.
Polling Source Base
components/canny/sources/common/base-polling.mjs
New reusable polling base component managing lastTs in db, providing processEvents(max) using this.canny.paginate, filtering by timestamp and isRelevant, emitting items with generateMeta, and declaring abstract getResourceFn, getResourceKey, generateMeta methods. Includes deploy hook and run.
Event Source Modules
components/canny/sources/new-comment-created/new-comment-created.mjs, components/canny/sources/new-vote-created/new-vote-created.mjs, components/canny/sources/post-status-changed/post-status-changed.mjs
Three new sources extending the polling base: New Comment Created (uses listComments, filters by content/image, props: boardId, authorId, companyId, postId), New Vote Created (uses listVotes, props: boardId, companyId, postId, userId), Post Status Changed (uses listStatusChanges, prop: boardId). Each maps props to API payload keys and generates event meta (id, summary, ts).
Utilities & Constants
components/canny/common/utils.mjs, components/canny/common/constants.mjs, components/canny/package.json
Adds parseObject() utility for recursive parsing of strings/arrays/objects; exports POST_STATUSES array; bumps package version from 0.6.0 to 0.7.0.

Sequence Diagram(s)

sequenceDiagram
    participant Timer
    participant Source as Polling Source
    participant DB
    participant CannyAPI
    participant Emitter

    Timer->>Source: trigger run()/deploy()
    Source->>DB: _getLastTs()
    Source->>CannyAPI: paginate (list* with skip/limit)
    alt page has items
        CannyAPI-->>Source: return page of items
        Source->>Source: filter items by ts >= lastTs and isRelevant()
        Source->>Emitter: emit(item, meta)
        Source->>DB: _setLastTs(newest ts)
        Source->>CannyAPI: fetch next page (loop)
    else no items / done
        CannyAPI-->>Source: no more pages
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review hotspots:
    • components/canny/canny.app.mjs: _makeRequest auth handling, error propagation, and paginate() correctness (hasMore/skip/limit).
    • components/canny/sources/common/base-polling.mjs: lastTs persistence, initial bootstrap (deploy) behaviour, and abstract method contracts.
    • components/canny/actions/create-comment/create-comment.mjs: validation ensuring value or imageUrls.
    • components/canny/common/utils.mjs: parseObject() recursive parsing edge cases.

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description only contains 'Resolves #13310' and lacks details about the changes made, implementation approach, or testing. Expand the description following the template to include WHY section explaining the purpose of these new components and any relevant implementation details.
Linked Issues check ⚠️ Warning The PR implements polling sources instead of webhook sources as required, and is missing find-post action; create-comment lacks value/imageUrls validation mentioned in requirements. Replace polling sources with proper webhook implementations [#13310], add find-post action, and ensure comment requirements are fully met per issue specifications.
Out of Scope Changes check ⚠️ Warning The PR includes utility functions, base polling components, and a full API integration layer that exceed the stated requirements for individual actions and sources. Clarify whether utility components and API integration are necessary infrastructure, or remove them as out-of-scope additions beyond the required actions and sources.
Title check ❓ Inconclusive The title 'Canny - new components' is generic and doesn't clearly specify which components were added or their primary functionality. Consider using a more descriptive title like 'Canny: Add comment, vote, and status change actions and sources' to better convey the scope.
✅ Passed checks (1 passed)
Check name Status Explanation
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-13310

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 080d445 and 3eb1cba.

📒 Files selected for processing (11)
  • components/canny/actions/change-post-status/change-post-status.mjs (1 hunks)
  • components/canny/actions/create-comment/create-comment.mjs (1 hunks)
  • components/canny/actions/create-post/create-post.mjs (1 hunks)
  • components/canny/actions/get-post/get-post.mjs (1 hunks)
  • components/canny/canny.app.mjs (1 hunks)
  • components/canny/common/utils.mjs (1 hunks)
  • components/canny/package.json (1 hunks)
  • components/canny/sources/common/base-polling.mjs (1 hunks)
  • components/canny/sources/new-comment-created/new-comment-created.mjs (1 hunks)
  • components/canny/sources/new-vote-created/new-vote-created.mjs (1 hunks)
  • components/canny/sources/post-status-changed/post-status-changed.mjs (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 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/canny/sources/common/base-polling.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/canny/canny.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/canny/canny.app.mjs
🧬 Code graph analysis (6)
components/canny/actions/get-post/get-post.mjs (3)
components/canny/actions/change-post-status/change-post-status.mjs (1)
  • response (60-68)
components/canny/actions/create-comment/create-comment.mjs (1)
  • response (65-75)
components/canny/actions/create-post/create-post.mjs (1)
  • response (83-97)
components/canny/actions/create-comment/create-comment.mjs (3)
components/canny/actions/change-post-status/change-post-status.mjs (1)
  • response (60-68)
components/canny/actions/create-post/create-post.mjs (1)
  • response (83-97)
components/canny/actions/get-post/get-post.mjs (1)
  • response (41-48)
components/canny/sources/common/base-polling.mjs (2)
components/zep/actions/get-threads/get-threads.mjs (1)
  • max (39-39)
components/canny/canny.app.mjs (1)
  • items (243-243)
components/canny/actions/create-post/create-post.mjs (1)
components/canny/common/utils.mjs (2)
  • parseObject (1-27)
  • parseObject (1-27)
components/canny/actions/change-post-status/change-post-status.mjs (3)
components/canny/actions/create-comment/create-comment.mjs (1)
  • response (65-75)
components/canny/actions/create-post/create-post.mjs (1)
  • response (83-97)
components/canny/actions/get-post/get-post.mjs (1)
  • response (41-48)
components/canny/canny.app.mjs (2)
components/canny/sources/common/base-polling.mjs (3)
  • data (33-33)
  • items (43-43)
  • resourceKey (34-34)
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: Lint Code Base
  • GitHub Check: pnpm publish
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
🔇 Additional comments (8)
components/canny/package.json (1)

1-18: Version bump looks consistent with new surface area.
No concerns in this file.

components/canny/actions/get-post/get-post.mjs (1)

14-51: [rewritten comment]
[classification tag]

components/canny/actions/create-comment/create-comment.mjs (1)

17-59: [rewritten comment]
[classification tag]

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

136-151: LGTM!

The centralized _makeRequest method correctly injects apiKey into all requests and uses POST method as required by Canny's API.

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

12-27: LGTM!

The recursive handling for arrays and objects is correctly implemented, and the null check on line 16 properly guards against typeof null === "object".

components/canny/actions/create-post/create-post.mjs (3)

4-14: LGTM!

Action metadata and annotations are properly configured with appropriate hints for the action's behavior (non-destructive, open-world, read-write).


82-100: LGTM!

The run method correctly maps prop names to Canny's API field naming convention (e.g., authorIdauthorID) and provides a clear summary on success.


69-74: Consider parsing imageUrls like customFields for consistency.

If users provide imageUrls as a JSON string (e.g., from a previous step), it won't be parsed. For consistency with customFields handling, consider using parseObject.

-        imageURLs: this.imageUrls,
+        imageURLs: parseObject(this.imageUrls),

Also applies to: 94-94

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

lcaresia
lcaresia previously approved these changes Dec 15, 2025
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.

Hey, just one minor fix. Moving to QA.

@vunguyenhung
Copy link
Collaborator

For Integration QA:

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

♻️ Duplicate comments (2)
components/canny/sources/common/base-polling.mjs (1)

33-68: Unbounded historical backfill and timestamp boundary issues already flagged.

The issues with processEvents() have been identified in a previous review:

  1. run() calls processEvents() without max, causing unbounded fetch on first poll
  2. Using ts >= lastTs re-emits the newest item on every poll interval
  3. Items are emitted newest-first rather than chronological order

Please address the fix proposed in the previous review.

components/canny/sources/new-comment-created/new-comment-created.mjs (1)

37-47: Spec mismatch: postId should be required per linked issue.

The linked issue #13310 specifies new-comment-instant with a required post id prop. This has been flagged in a previous review.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9937dd7 and 2cdce3e.

📒 Files selected for processing (2)
  • components/canny/sources/common/base-polling.mjs (1 hunks)
  • components/canny/sources/new-comment-created/new-comment-created.mjs (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 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/canny/sources/common/base-polling.mjs
📚 Learning: 2024-10-08T15:33:38.240Z
Learnt from: LucBerge
Repo: PipedreamHQ/pipedream PR: 14080
File: components/nocodb/nocodb.app.mjs:133-133
Timestamp: 2024-10-08T15:33:38.240Z
Learning: When implementing pagination with an offset, incrementing `args.params.offset` within the loop ensures correct tracking of the offset, particularly when a maximum count limit (`max`) is used.

Applied to files:

  • components/canny/sources/common/base-polling.mjs
🧬 Code graph analysis (1)
components/canny/sources/common/base-polling.mjs (2)
components/zep/actions/get-threads/get-threads.mjs (1)
  • max (39-39)
components/canny/canny.app.mjs (1)
  • items (243-243)
⏰ 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 (3)
components/canny/sources/common/base-polling.mjs (2)

17-32: Helper methods and default implementations look good.

The timestamp tracking via db.get/db.set, default getData() returning empty object, getTsField() returning "created" (matching Canny API), and isRelevant() defaulting to true are appropriate patterns for a base polling component.


69-77: Abstract method stubs are correctly implemented.

Using ConfigurationError to enforce implementation in subclasses is the correct pattern for Pipedream components.

components/canny/sources/new-comment-created/new-comment-created.mjs (1)

49-64: Resource methods are correctly implemented.

The getResourceFn, getData, and getResourceKey implementations properly integrate with the base polling component and correctly map prop names to Canny API field names.

@vunguyenhung
Copy link
Collaborator

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

Test reports

@michelle0927
Copy link
Collaborator Author

/approve

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!

@michelle0927 michelle0927 merged commit dece727 into master Dec 17, 2025
9 checks passed
@michelle0927 michelle0927 deleted the issue-13310 branch December 17, 2025 18:57
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] canny

4 participants