Skip to content

Commit

Permalink
feat: Airtable CDP destination, creating records per-event (#25656)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
daniloc and github-actions[bot] authored Oct 17, 2024
1 parent 40e69dd commit c4a87c7
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 1 deletion.
Binary file added frontend/public/services/airtable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion posthog/cdp/templates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@
template as google_cloud_storage,
TemplateGoogleCloudStorageMigrator,
)

from .airtable.template_airtable import template as airtable

HOG_FUNCTION_TEMPLATES = [
slack,
webhook,
activecampaign,
airtable,
attio,
avo,
aws_kinesis,
Expand Down
82 changes: 82 additions & 0 deletions posthog/cdp/templates/airtable/template_airtable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from posthog.cdp.templates.hog_function_template import HogFunctionTemplate


template: HogFunctionTemplate = HogFunctionTemplate(
status="alpha",
id="template-airtable",
name="Airtable",
description="Creates Airtable records",
icon_url="/static/services/airtable.png",
category=["Custom"],
hog="""
let url := f'https://api.airtable.com/v0/{inputs.base_id}/{inputs.table_name}'
let payload := {
'headers': {
'Content-Type': 'application/json',
'Authorization': f'Bearer {inputs.access_token}'
},
'body': {
'fields': inputs.fields,
'typecast': true
},
'method': 'POST'
}
if (inputs.debug) {
print('Request', url, payload)
}
let res := fetch(url, payload);
if (inputs.debug) {
print('Response', res.status, res.body);
}
if (res.status >= 400) {
throw Error(f'Error from api.airtable.com (status {res.status}): {res.body}')
}
""".strip(),
inputs_schema=[
{
"key": "access_token",
"type": "string",
"label": "Airtable access token",
"secret": True,
"required": True,
"description": "Create this at https://airtable.com/create/tokens",
},
{
"key": "base_id",
"type": "string",
"label": "Airtable base ID",
"secret": False,
"required": True,
"description": "Find this at https://airtable.com/developers/web/api/introduction",
},
{
"key": "table_name",
"type": "string",
"label": "Table name",
"secret": False,
"required": True,
},
{
"key": "fields",
"type": "json",
"label": "Fields",
"default": {"Timestamp": "{event.timestamp}", "Person Name": "{person.name}"},
"secret": False,
"required": True,
"description": "Map field names from Airtable to properties from events and person records.",
},
{
"key": "debug",
"type": "boolean",
"label": "Log responses",
"description": "Logs the response of http calls for debugging.",
"secret": False,
"required": False,
"default": False,
},
],
)
66 changes: 66 additions & 0 deletions posthog/cdp/templates/airtable/test_template_airtable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from inline_snapshot import snapshot
from posthog.cdp.templates.helpers import BaseHogFunctionTemplateTest
from posthog.cdp.templates.airtable.template_airtable import template as template_airtable


class TestTemplateAirtable(BaseHogFunctionTemplateTest):
template = template_airtable

def test_function_works(self):
self.run_function(
inputs={
"access_token": "test_token",
"base_id": "test_base_id",
"table_name": "test_table",
"fields": {"Name": "John Doe", "Email": "[email protected]"},
"debug": False,
}
)

assert self.get_mock_fetch_calls()[0] == snapshot(
(
"https://api.airtable.com/v0/test_base_id/test_table",
{
"headers": {"Content-Type": "application/json", "Authorization": "Bearer test_token"},
"body": {"fields": {"Name": "John Doe", "Email": "[email protected]"}, "typecast": True},
"method": "POST",
},
)
)
assert self.get_mock_print_calls() == snapshot([])

def test_prints_when_debugging(self):
self.run_function(
inputs={
"access_token": "test_token",
"base_id": "test_base_id",
"table_name": "test_table",
"fields": {"Name": "John Doe", "Email": "[email protected]"},
"debug": True,
}
)

assert self.get_mock_fetch_calls()[0] == snapshot(
(
"https://api.airtable.com/v0/test_base_id/test_table",
{
"headers": {"Content-Type": "application/json", "Authorization": "Bearer test_token"},
"body": {"fields": {"Name": "John Doe", "Email": "[email protected]"}, "typecast": True},
"method": "POST",
},
)
)
assert self.get_mock_print_calls() == snapshot(
[
(
"Request",
"https://api.airtable.com/v0/test_base_id/test_table",
{
"headers": {"Content-Type": "application/json", "Authorization": "Bearer test_token"},
"body": {"fields": {"Name": "John Doe", "Email": "[email protected]"}, "typecast": True},
"method": "POST",
},
),
("Response", 200, {}),
]
)

0 comments on commit c4a87c7

Please sign in to comment.