Repository navigation
Conversation
NewSubscriberTrigger, MemberStatusChangeTrigger and CampaignSentTrigger poll Mailchimp sorted ascending on timestamp_opt / last_changed / send_time with 1 s since_* slack. TriggerCursor (newest timestamp + ids seen at it) in the namespace KV store drops boundary rows client-side, so inclusive or exclusive server filters both fire each row once. One execution per poll carries all new rows as ION. Shared logic lives in models/CursorPoll and audiences/AbstractMemberTrigger; interval (default PT5M, minimum PT30S) in AbstractMailchimpTrigger.
a8afbb0 to
97463b5
Compare
|
@fdelbrayelle Could you please review this? |
fdelbrayelle
left a comment
There was a problem hiding this comment.
Automated review by the kestra-plugins:code-reviewer agent, run on behalf of @fdelbrayelle. Static read of the diff, the build and tests were not run.
VERDICT: APPROVE
Blocking: none found. I read the full diff (100 files, including tests, flows and docs). CI is green (check / main). There is no prior review on the PR.
Non-blocking notes:
MailchimpClient.javaandMailchimpConnectionInterface.javause the JDKHttpClientinstead ofio.kestra.core.http.client. The guidelines require Kestra's client. The PR body explains the choice: Kestra's client replays POST on 429/503, which is unsafe forSendCampaignandBatchSubscribe. A maintainer should confirm this deviation. Response bodies are also read whole withBodyHandlers.ofString(), which is bounded in practice by the 1000-row pages.AbstractMailchimpTask.java:24uses@EqualsAndHashCodewithoutcallSuper = true(the trigger base class sets it).maxRetries,timeoutandintervalhave no@Minbound in the schema, although the code checks the bounds at runtime. This breaks the guidelines' range rule.AbstractMailchimpTask.java:59andAbstractMailchimpTrigger.java:59both define thebaseUrloverride. Any https host receives the bearer token, so a flow author can send credentials anywhere. The schema marks it as for testing and proxies, so this is acceptable. Consider documenting it insrc/main/resources/doc/io.kestra.plugin.mailchimp.md.
fdelbrayelle
left a comment
There was a problem hiding this comment.
Approved. See my earlier review comment for non-blocking suggestions.
… credential exposure
86b9850 to
2a8f57f
Compare
|
@fdelbrayelle Thanks for the review , for the use of For the other two notes I have pushed a small commit , to follow the guideline's range rule and the required documentation. |
|
@23abdul23 Closing it since it should be a PR against plugin-mailchimp. Plus, what is the initial issue it addresses? Thanks! |
|
@fdelbrayelle Well this is a new plugin that I want to submit, currently this plugin doesn't exist and I wasn't assigned this issue (there was no issue for mailchimp in first place) The usecase is like , for eg: we have an event and want to send campaign/poster invites to various past participants and insititutes / orgs , so mailchimp helps in analytics realted to campaings, clicks etc |
|
@23abdul23 Could you first open an issue properly in https://github.com/kestra-io/kestra with why we should add this plugin? Then we'll consider to create the plugin-mailchamp and you could open a PR on it accordingly. Thanks. |
What changes are being made and why?
Adds a Mailchimp plugin (
io.kestra.plugin.mailchimp) so audience and campaign steps can live in Kestra flows instead of shell or Python tasks calling the Marketing API.Tasks
account.Pingaudiences.ListAudiences,ListMembers,UpsertMember,BatchSubscribe,UpdateMemberTagscampaigns.ListCampaigns,SendCampaignreports.GetCampaignReport,ListEmailActivityTriggers
audiences.NewSubscriberTrigger,audiences.MemberStatusChangeTrigger,campaigns.CampaignSentTriggerAuthentication is an API key (data center derived from the key suffix unless
serveris set) or an OAuth access token.Deviations from the usual plugin shape
java.net.http.HttpClientinstead of Kestra'sHttpClient: Kestra's client replays POST on 429/503 and that cannot be turned off, which is unsafe forSendCampaignandBatchSubscribe. Retry (GET and idempotent calls only, honoringRetry-After) lives inMailchimpClient.Pingsits in anaccountsubpackage so every subgroup has its own icon and category.How the changes have been QAed?
Unit tests (
./gradlew build, JDK 23, no Mailchimp credentials): 176 tests, 163 passed, 0 failed. A local fake Mailchimp server covers pagination, retries, error mapping and trigger cursors.Live tests against a throwaway account (
./gradlew test --tests '*integration*'): 13 integration tests passed, 0 failed, 0 skipped. They createkestra-it-<uuid>members asunsubscribedin one audience only, archive them afterwards, and never send a campaign (a guard test fails if the integration sources reference the send action). Covered: ping, server derived from key, list audiences and campaigns, upsert + tag + list round trip, 3-member batch, campaign report and email activity (read only), real 401/404/400 mapping,NewSubscriberTriggerfirst poll, andMemberStatusChangeTrigger(first poll fires nothing, a new unsubscribed member fires exactly once, third poll fires nothing).Run in a local Kestra 2.x container with the plugin jar mounted: the plugin registers 13 plugin classes with no load errors, and this flow succeeded (
kestra flow test, secret read fromSECRET_MAILCHIMP_API_KEY):Not exercised: a flow run through the UI/API (the local instance requires a Setup-page account), JDK 21 (only JDK 23 available locally),
SendCampaignagainst a real campaign (deliberately never run), 403 andRetry-Afteron 429.Setup Instructions
.env.exampleto.env(git-ignored) and load it for integration tests, see the README "Integration tests" section.example.comfor test members, so setMAILCHIMP_TEST_EMAIL_DOMAINto a domain with MX records;since_*filters are exclusive with whole-second precision (the triggers re-read one second and de-duplicate by id);DELETEonly archives members;filter_botsis accepted but its effect was not observable; one page per trigger poll.Contributor Checklist ✅