Skip to content

feat(connector): Airtable, PagerDuty, Twilio, and Asana connectors#145

Merged
michaelmcnees merged 2 commits into
mainfrom
feat/rest-connectors-batch
May 30, 2026
Merged

feat(connector): Airtable, PagerDuty, Twilio, and Asana connectors#145
michaelmcnees merged 2 commits into
mainfrom
feat/rest-connectors-batch

Conversation

@michaelmcnees

@michaelmcnees michaelmcnees commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements 8 connector actions across 4 REST services, closing issues #103, #99, #96, and #116.

Action Description
airtable/list List records from a table; supports max_records, filter_by_formula, view, offset
airtable/create_record Create a record with arbitrary fields
pagerduty/create_incident Create an incident; optional urgency, details, from_email
pagerduty/resolve Resolve an incident by ID
twilio/sms Send an SMS; form-encoded body, Basic auth
twilio/call Initiate a call; accepts url or twiml
asana/create_task Create a task in a workspace or project(s); optional notes, assignee, due_on
asana/search Search tasks in a workspace by text, assignee, completed, limit

All connectors follow the established patterns from existing connectors:

  • Dual credential shape (map[string]string + map[string]any)
  • url.PathEscape on all user-supplied path segments
  • io.LimitReader(resp.Body, DefaultMaxResponseBytes) on all responses
  • baseURL field for httptest.Server injection in tests
  • _credential deleted from params after extraction

Test plan

  • 49 new unit tests; all pass (go test ./internal/connector/...)
  • Registry tests confirm all 8 actions are registered
  • Each connector has: happy path, optional param, missing required param, missing credential, API error, and map[string]any credential shape coverage

Closes #103, #99, #96, #116

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

New Features

  • Airtable connector: List and filter records with pagination support; create new records with specified fields
  • Asana connector: Create tasks with project and workspace assignment; search for tasks within workspaces
  • PagerDuty connector: Create incidents with details and urgency levels; resolve incidents and manage status
  • Twilio connector: Send SMS messages to phone numbers; initiate outbound phone calls

Review Change Stack

#103, #99, #96, #116)

Implements eight connector actions across four services:
- airtable/list, airtable/create_record
- pagerduty/create_incident, pagerduty/resolve
- twilio/sms, twilio/call
- asana/create_task, asana/search

All connectors follow established patterns: dual credential shape
(map[string]string + map[string]any), url.PathEscape on user-supplied
path segments, io.LimitReader on response bodies, and httptest.Server
injection via baseURL for unit testing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds four new external service connectors to the Mantle engine: Airtable (list and create-record), Asana (create-task and search), PagerDuty (create-incident and resolve), and Twilio (SMS and call). Each connector validates credentials, performs HTTP operations with appropriate auth, enforces expected status codes, and returns normalized response maps. All connectors are registered in the central connector registry.

Changes

Connector implementations for Airtable, Asana, PagerDuty, and Twilio

Layer / File(s) Summary
Airtable List and Create Record connectors
packages/engine/internal/connector/airtable.go, packages/engine/internal/connector/airtable_test.go
AirtableListConnector builds GET URLs with pagination and filtering via query parameters; AirtableCreateRecordConnector POSTs new records with a fields map. Both validate _credential token, base_id, and table_id, use Bearer token auth, enforce HTTP 200, and parse JSON responses. Tests cover successful operations, query parameters, pagination, missing required fields, API errors, and alternate credential formats.
Asana Create Task and Search connectors
packages/engine/internal/connector/asana.go, packages/engine/internal/connector/asana_test.go
AsanaCreateTaskConnector requires name plus workspace or projects, POSTs to create endpoint, and returns gid, name, and permalink_url. AsanaSearchConnector requires workspace, supports optional query filters, and returns tasks list plus count. Both extract and validate Bearer token, enforce HTTP 201/200 status codes, and parse JSON responses. Tests cover happy paths, field validation, project list variants, API errors, and alternate credential formats.
PagerDuty Create Incident and Resolve connectors
packages/engine/internal/connector/pagerduty.go, packages/engine/internal/connector/pagerduty_test.go
PagerDutyCreateIncidentConnector validates title and service_id, supports optional urgency and details, POSTs to create endpoint with status 201, and returns incident ID, title, urgency, and HTML URL. PagerDutyResolveConnector validates incident_id and requires from_email, PUTs to resolve endpoint with status 200, and returns ID and status. Both use token-based auth with PagerDuty versioned Accept headers. Tests cover happy paths, optional fields, credential/from_email sourcing, missing required inputs, API errors, and alternate credential formats.
Twilio SMS and Call connectors
packages/engine/internal/connector/twilio.go, packages/engine/internal/connector/twilio_test.go
TwilioSMSConnector validates to, from, and body, POSTs form-encoded data with HTTP Basic auth, and returns sid, status, to, from, and body. TwilioCallConnector validates to, from, and exactly one of url or twiml, POSTs with appropriate form field, and returns sid, status, to, and from. Both enforce HTTP 201 Created and include account SID in the request path. Tests cover happy paths for both SMS and call variants, input validation for each required field, API errors, account SID path inclusion, and alternate credential formats.
Connector registry wiring
packages/engine/internal/connector/connector.go
NewRegistry() now registers eight new built-in connectors under their action names: airtable/list, airtable/create_record, asana/create_task, asana/search, pagerduty/create_incident, pagerduty/resolve, twilio/sms, and twilio/call.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • dvflw/mantle#144: Both PRs extend NewRegistry() in packages/engine/internal/connector/connector.go to register newly implemented connectors, making them directly related at the registry wiring level.

Poem

🐰 Four connectors hop into the fold,
Airtable, Asana, PagerDuty told,
Twilio joins the merry crew,
Bearer tokens, Basic auth too!
Registry rings with actions new,
What a magical connector zoo! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(connector): Airtable, PagerDuty, Twilio, and Asana connectors' clearly and specifically summarizes the main change—adding four new connector implementations—without vague terms or extraneous details.
Linked Issues check ✅ Passed All code changes in airtable.go, airtable_test.go, pagerduty.go, pagerduty_test.go, twilio.go, twilio_test.go, asana.go, and asana_test.go directly implement the required connectors with proper credential handling, request/response patterns, and comprehensive test coverage matching issue #103 requirements.
Out of Scope Changes check ✅ Passed All changes are in-scope: eight new connector implementations (Airtable list/create, PagerDuty create/resolve, Twilio SMS/call, Asana create_task/search) in dedicated files with tests, plus registry updates to register these connectors.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rest-connectors-batch

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 964e4d0f70

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/engine/internal/connector/pagerduty.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds four new REST connectors — Airtable, PagerDuty, Twilio, and Asana — exposing eight new actions and registering them in the connector registry. Each connector follows the established pattern (path-escaped user inputs, io.LimitReader on responses, dual map[string]string / map[string]any credential handling, baseURL test injection) and ships with unit tests covering happy paths, optional params, missing required params, missing credentials, API errors, and the map[string]any credential shape.

Changes:

  • Implement Airtable, PagerDuty, Twilio, and Asana connectors (8 actions total) with consistent credential/error/response handling.
  • Register all 8 new actions in NewRegistry().
  • Add ~49 unit tests using httptest.NewServer and unexported baseURL injection.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/engine/internal/connector/connector.go Registers the 8 new connector actions in the default registry.
packages/engine/internal/connector/airtable.go Implements airtable/list and airtable/create_record with PAT bearer auth and optional list query params.
packages/engine/internal/connector/airtable_test.go Unit tests for both Airtable connectors, including pagination offset and map[string]any credentials.
packages/engine/internal/connector/pagerduty.go Implements pagerduty/create_incident and pagerduty/resolve with token auth and optional From header.
packages/engine/internal/connector/pagerduty_test.go Unit tests covering required params, optional details/urgency, from_email handling, and error cases.
packages/engine/internal/connector/twilio.go Implements twilio/sms and twilio/call using Basic auth and form-encoded bodies.
packages/engine/internal/connector/twilio_test.go Tests for SMS, call (with url and with twiml), missing-param/credential paths, and SID-in-URL escaping.
packages/engine/internal/connector/asana.go Implements asana/create_task (workspace or projects) and asana/search (text/assignee/completed/limit filters).
packages/engine/internal/connector/asana_test.go Tests for both Asana connectors including optional fields, filters, and map[string]any credentials.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/engine/internal/connector/asana.go Outdated
Comment thread packages/engine/internal/connector/twilio.go
- pagerduty/resolve: make from_email required (PagerDuty rejects PUT /incidents
  without a From header when using REST API keys); accepted from credential or
  as an explicit param
- twilio/call: error when both url and twiml are supplied (mutually exclusive)
- asana/create_task: use toStringSlice for projects so []string and []any are
  both accepted without a silent nil fallback

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/engine/internal/connector/asana.go (1)

191-211: ⚡ Quick win

Consider consolidating the duplicated bearer-token extractor.

extractAsanaToken is byte-for-byte identical to extractAirtableToken in airtable.go. As more connectors follow this Bearer-token pattern, a single shared helper (e.g. extractBearerToken) would reduce drift risk.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/engine/internal/connector/asana.go` around lines 191 - 211, The
Asana token extractor duplicates logic from Airtable; create a shared helper
function named extractBearerToken(params map[string]any) (string, error) that
performs the common steps (read and delete "_credential" from params, accept
both map[string]string and map[string]any, extract "token" string, and return an
error if missing), then replace extractAsanaToken and extractAirtableToken to
call extractBearerToken and return its result (or remove the duplicates and
update callers to use extractBearerToken); ensure the helper preserves the
current behavior of deleting "_credential" from params and returns the same
error messages when token is missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/engine/internal/connector/asana.go`:
- Around line 191-211: The Asana token extractor duplicates logic from Airtable;
create a shared helper function named extractBearerToken(params map[string]any)
(string, error) that performs the common steps (read and delete "_credential"
from params, accept both map[string]string and map[string]any, extract "token"
string, and return an error if missing), then replace extractAsanaToken and
extractAirtableToken to call extractBearerToken and return its result (or remove
the duplicates and update callers to use extractBearerToken); ensure the helper
preserves the current behavior of deleting "_credential" from params and returns
the same error messages when token is missing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d8d8e5de-9b28-4ac1-9b50-462e19b6bb78

📥 Commits

Reviewing files that changed from the base of the PR and between 0579850 and 8a0c111.

📒 Files selected for processing (9)
  • packages/engine/internal/connector/airtable.go
  • packages/engine/internal/connector/airtable_test.go
  • packages/engine/internal/connector/asana.go
  • packages/engine/internal/connector/asana_test.go
  • packages/engine/internal/connector/connector.go
  • packages/engine/internal/connector/pagerduty.go
  • packages/engine/internal/connector/pagerduty_test.go
  • packages/engine/internal/connector/twilio.go
  • packages/engine/internal/connector/twilio_test.go

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.

[Feature] Native Airtable connector (airtable/list, airtable/create_record)

2 participants