ingestr 0.14.1__tar.gz → 0.14.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ingestr might be problematic. Click here for more details.

Files changed (357) hide show
  1. ingestr-0.14.3/.github/workflows/release.yml +151 -0
  2. {ingestr-0.14.1 → ingestr-0.14.3}/Dockerfile +4 -1
  3. {ingestr-0.14.1 → ingestr-0.14.3}/Makefile +8 -2
  4. {ingestr-0.14.1 → ingestr-0.14.3}/PKG-INFO +1 -1
  5. {ingestr-0.14.1 → ingestr-0.14.3}/docs/.vitepress/config.mjs +12 -0
  6. {ingestr-0.14.1 → ingestr-0.14.3}/docs/index.md +1 -1
  7. ingestr-0.14.3/docs/supported-sources/elasticsearch.md +80 -0
  8. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/fluxx.md +1 -0
  9. ingestr-0.14.3/docs/supported-sources/intercom.md +57 -0
  10. ingestr-0.14.3/docs/supported-sources/jira.md +61 -0
  11. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/mongodb.md +56 -5
  12. ingestr-0.14.3/ingestr/src/buildinfo.py +1 -0
  13. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/destinations.py +1 -24
  14. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/elasticsearch/helpers.py +35 -9
  15. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/factory.py +4 -0
  16. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/fluxx/__init__.py +9 -0
  17. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/hubspot/__init__.py +6 -12
  18. ingestr-0.14.3/ingestr/src/intercom/__init__.py +142 -0
  19. ingestr-0.14.3/ingestr/src/intercom/helpers.py +674 -0
  20. ingestr-0.14.3/ingestr/src/intercom/settings.py +279 -0
  21. ingestr-0.14.3/ingestr/src/jira_source/__init__.py +314 -0
  22. ingestr-0.14.3/ingestr/src/jira_source/helpers.py +452 -0
  23. ingestr-0.14.3/ingestr/src/jira_source/settings.py +170 -0
  24. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/mongodb/helpers.py +34 -6
  25. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/sources.py +120 -0
  26. ingestr-0.14.3/resources/demo.gif +0 -0
  27. ingestr-0.14.1/.github/workflows/release.yml +0 -81
  28. ingestr-0.14.1/docs/supported-sources/elasticsearch.md +0 -35
  29. ingestr-0.14.1/ingestr/src/buildinfo.py +0 -1
  30. {ingestr-0.14.1 → ingestr-0.14.3}/.dlt/config.toml +0 -0
  31. {ingestr-0.14.1 → ingestr-0.14.3}/.dockerignore +0 -0
  32. {ingestr-0.14.1 → ingestr-0.14.3}/.githooks/pre-commit-hook.sh +0 -0
  33. {ingestr-0.14.1 → ingestr-0.14.3}/.github/workflows/deploy-docs.yml +0 -0
  34. {ingestr-0.14.1 → ingestr-0.14.3}/.github/workflows/secrets-scan.yml +0 -0
  35. {ingestr-0.14.1 → ingestr-0.14.3}/.github/workflows/tests.yml +0 -0
  36. {ingestr-0.14.1 → ingestr-0.14.3}/.gitignore +0 -0
  37. {ingestr-0.14.1 → ingestr-0.14.3}/.gitleaksignore +0 -0
  38. {ingestr-0.14.1 → ingestr-0.14.3}/.python-version +0 -0
  39. {ingestr-0.14.1 → ingestr-0.14.3}/.vale.ini +0 -0
  40. {ingestr-0.14.1 → ingestr-0.14.3}/LICENSE.md +0 -0
  41. {ingestr-0.14.1 → ingestr-0.14.3}/README.md +0 -0
  42. {ingestr-0.14.1 → ingestr-0.14.3}/docs/.vitepress/theme/custom.css +0 -0
  43. {ingestr-0.14.1 → ingestr-0.14.3}/docs/.vitepress/theme/index.js +0 -0
  44. {ingestr-0.14.1 → ingestr-0.14.3}/docs/commands/example-uris.md +0 -0
  45. {ingestr-0.14.1 → ingestr-0.14.3}/docs/commands/ingest.md +0 -0
  46. {ingestr-0.14.1 → ingestr-0.14.3}/docs/getting-started/core-concepts.md +0 -0
  47. {ingestr-0.14.1 → ingestr-0.14.3}/docs/getting-started/data-masking.md +0 -0
  48. {ingestr-0.14.1 → ingestr-0.14.3}/docs/getting-started/incremental-loading.md +0 -0
  49. {ingestr-0.14.1 → ingestr-0.14.3}/docs/getting-started/quickstart.md +0 -0
  50. {ingestr-0.14.1 → ingestr-0.14.3}/docs/getting-started/telemetry.md +0 -0
  51. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/applovin_max.png +0 -0
  52. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/athena.png +0 -0
  53. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/clickhouse_img.png +0 -0
  54. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/clickup_ingestion.png +0 -0
  55. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/cratedb-destination.png +0 -0
  56. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/cratedb-source.png +0 -0
  57. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/freshdesk_ingestion.png +0 -0
  58. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/gcp_spanner_ingestion.png +0 -0
  59. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/github.png +0 -0
  60. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/google_analytics_realtime_report.png +0 -0
  61. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/googleanalytics.png +0 -0
  62. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/ingestion_elasticsearch_img.png +0 -0
  63. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/kinesis.bigquery.png +0 -0
  64. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/linear.png +0 -0
  65. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/linkedin_ads.png +0 -0
  66. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/mixpanel_ingestion.png +0 -0
  67. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/personio.png +0 -0
  68. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/personio_duckdb.png +0 -0
  69. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/phantombuster.png +0 -0
  70. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/pipedrive.png +0 -0
  71. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/quickbook_ingestion.png +0 -0
  72. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/sftp.png +0 -0
  73. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/stripe_postgres.png +0 -0
  74. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/tiktok.png +0 -0
  75. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/wise_ingestion.png +0 -0
  76. {ingestr-0.14.1 → ingestr-0.14.3}/docs/media/zoom_ingestion.png +0 -0
  77. {ingestr-0.14.1/resources → ingestr-0.14.3/docs/public}/demo.gif +0 -0
  78. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/adjust.md +0 -0
  79. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/airtable.md +0 -0
  80. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/anthropic.md +0 -0
  81. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/applovin.md +0 -0
  82. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/applovin_max.md +0 -0
  83. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/appsflyer.md +0 -0
  84. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/appstore.md +0 -0
  85. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/asana.md +0 -0
  86. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/athena.md +0 -0
  87. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/attio.md +0 -0
  88. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/bigquery.md +0 -0
  89. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/chess.md +0 -0
  90. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/clickhouse.md +0 -0
  91. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/clickup.md +0 -0
  92. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/cratedb.md +0 -0
  93. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/csv.md +0 -0
  94. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/custom_queries.md +0 -0
  95. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/databricks.md +0 -0
  96. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/db2.md +0 -0
  97. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/docebo.md +0 -0
  98. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/duckdb.md +0 -0
  99. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/dynamodb.md +0 -0
  100. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/facebook-ads.md +0 -0
  101. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/frankfurter.md +0 -0
  102. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/freshdesk.md +0 -0
  103. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/fundraiseup.md +0 -0
  104. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/gcs.md +0 -0
  105. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/github.md +0 -0
  106. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/google-ads.md +0 -0
  107. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/google_analytics.md +0 -0
  108. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/gorgias.md +0 -0
  109. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/gsheets.md +0 -0
  110. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/hubspot.md +0 -0
  111. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/influxdb.md +0 -0
  112. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/isoc-pulse.md +0 -0
  113. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/kafka.md +0 -0
  114. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/kinesis.md +0 -0
  115. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/klaviyo.md +0 -0
  116. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/linear.md +0 -0
  117. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/linkedin_ads.md +0 -0
  118. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/mixpanel.md +0 -0
  119. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/motherduck.md +0 -0
  120. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/mssql.md +0 -0
  121. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/mysql.md +0 -0
  122. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/notion.md +0 -0
  123. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/oracle.md +0 -0
  124. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/personio.md +0 -0
  125. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/phantombuster.md +0 -0
  126. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/pinterest.md +0 -0
  127. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/pipedrive.md +0 -0
  128. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/postgres.md +0 -0
  129. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/quickbooks.md +0 -0
  130. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/redshift.md +0 -0
  131. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/revenuecat.md +0 -0
  132. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/s3.md +0 -0
  133. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/salesforce.md +0 -0
  134. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/sap-hana.md +0 -0
  135. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/sftp.md +0 -0
  136. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/shopify.md +0 -0
  137. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/slack.md +0 -0
  138. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/smartsheets.md +0 -0
  139. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/snowflake.md +0 -0
  140. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/solidgate.md +0 -0
  141. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/spanner.md +0 -0
  142. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/sqlite.md +0 -0
  143. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/stripe.md +0 -0
  144. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/tiktok-ads.md +0 -0
  145. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/trino.md +0 -0
  146. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/trustpilot.md +0 -0
  147. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/wise.md +0 -0
  148. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/zendesk.md +0 -0
  149. {ingestr-0.14.1 → ingestr-0.14.3}/docs/supported-sources/zoom.md +0 -0
  150. {ingestr-0.14.1 → ingestr-0.14.3}/docs/tutorials/load-kinesis-bigquery.md +0 -0
  151. {ingestr-0.14.1 → ingestr-0.14.3}/docs/tutorials/load-personio-duckdb.md +0 -0
  152. {ingestr-0.14.1 → ingestr-0.14.3}/docs/tutorials/load-stripe-postgres.md +0 -0
  153. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/conftest.py +0 -0
  154. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/main.py +0 -0
  155. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/.gitignore +0 -0
  156. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/adjust/__init__.py +0 -0
  157. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/adjust/adjust_helpers.py +0 -0
  158. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/airtable/__init__.py +0 -0
  159. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/anthropic/__init__.py +0 -0
  160. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/anthropic/helpers.py +0 -0
  161. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/applovin/__init__.py +0 -0
  162. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/applovin_max/__init__.py +0 -0
  163. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/appsflyer/__init__.py +0 -0
  164. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/appsflyer/client.py +0 -0
  165. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/appstore/__init__.py +0 -0
  166. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/appstore/client.py +0 -0
  167. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/appstore/errors.py +0 -0
  168. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/appstore/models.py +0 -0
  169. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/appstore/resources.py +0 -0
  170. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/arrow/__init__.py +0 -0
  171. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/asana_source/__init__.py +0 -0
  172. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/asana_source/helpers.py +0 -0
  173. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/asana_source/settings.py +0 -0
  174. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/attio/__init__.py +0 -0
  175. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/attio/helpers.py +0 -0
  176. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/blob.py +0 -0
  177. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/chess/__init__.py +0 -0
  178. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/chess/helpers.py +0 -0
  179. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/chess/settings.py +0 -0
  180. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/clickup/__init__.py +0 -0
  181. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/clickup/helpers.py +0 -0
  182. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/collector/spinner.py +0 -0
  183. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/docebo/__init__.py +0 -0
  184. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/docebo/client.py +0 -0
  185. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/docebo/helpers.py +0 -0
  186. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/dynamodb/__init__.py +0 -0
  187. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/elasticsearch/__init__.py +0 -0
  188. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/errors.py +0 -0
  189. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/facebook_ads/__init__.py +0 -0
  190. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/facebook_ads/exceptions.py +0 -0
  191. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/facebook_ads/helpers.py +0 -0
  192. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/facebook_ads/settings.py +0 -0
  193. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/facebook_ads/utils.py +0 -0
  194. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/filesystem/__init__.py +0 -0
  195. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/filesystem/helpers.py +0 -0
  196. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/filesystem/readers.py +0 -0
  197. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/filters.py +0 -0
  198. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/fluxx/helpers.py +0 -0
  199. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/frankfurter/__init__.py +0 -0
  200. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/frankfurter/helpers.py +0 -0
  201. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/freshdesk/__init__.py +0 -0
  202. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/freshdesk/freshdesk_client.py +0 -0
  203. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/freshdesk/settings.py +0 -0
  204. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/fundraiseup/__init__.py +0 -0
  205. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/fundraiseup/client.py +0 -0
  206. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/github/__init__.py +0 -0
  207. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/github/helpers.py +0 -0
  208. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/github/queries.py +0 -0
  209. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/github/settings.py +0 -0
  210. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_ads/__init__.py +0 -0
  211. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_ads/field.py +0 -0
  212. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_ads/metrics.py +0 -0
  213. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_ads/predicates.py +0 -0
  214. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_ads/reports.py +0 -0
  215. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_analytics/__init__.py +0 -0
  216. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_analytics/helpers.py +0 -0
  217. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_sheets/README.md +0 -0
  218. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_sheets/__init__.py +0 -0
  219. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_sheets/helpers/__init__.py +0 -0
  220. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_sheets/helpers/api_calls.py +0 -0
  221. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/google_sheets/helpers/data_processing.py +0 -0
  222. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/gorgias/__init__.py +0 -0
  223. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/gorgias/helpers.py +0 -0
  224. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/http_client.py +0 -0
  225. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/hubspot/helpers.py +0 -0
  226. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/hubspot/settings.py +0 -0
  227. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/influxdb/__init__.py +0 -0
  228. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/influxdb/client.py +0 -0
  229. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/isoc_pulse/__init__.py +0 -0
  230. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/kafka/__init__.py +0 -0
  231. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/kafka/helpers.py +0 -0
  232. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/kinesis/__init__.py +0 -0
  233. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/kinesis/helpers.py +0 -0
  234. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/klaviyo/__init__.py +0 -0
  235. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/klaviyo/client.py +0 -0
  236. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/klaviyo/helpers.py +0 -0
  237. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/linear/__init__.py +0 -0
  238. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/linear/helpers.py +0 -0
  239. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/linkedin_ads/__init__.py +0 -0
  240. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/linkedin_ads/dimension_time_enum.py +0 -0
  241. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/linkedin_ads/helpers.py +0 -0
  242. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/loader.py +0 -0
  243. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/masking.py +0 -0
  244. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/mixpanel/__init__.py +0 -0
  245. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/mixpanel/client.py +0 -0
  246. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/mongodb/__init__.py +0 -0
  247. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/notion/__init__.py +0 -0
  248. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/notion/helpers/__init__.py +0 -0
  249. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/notion/helpers/client.py +0 -0
  250. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/notion/helpers/database.py +0 -0
  251. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/notion/settings.py +0 -0
  252. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/partition.py +0 -0
  253. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/personio/__init__.py +0 -0
  254. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/personio/helpers.py +0 -0
  255. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/phantombuster/__init__.py +0 -0
  256. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/phantombuster/client.py +0 -0
  257. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/pinterest/__init__.py +0 -0
  258. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/pipedrive/__init__.py +0 -0
  259. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/pipedrive/helpers/__init__.py +0 -0
  260. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/pipedrive/helpers/custom_fields_munger.py +0 -0
  261. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/pipedrive/helpers/pages.py +0 -0
  262. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/pipedrive/settings.py +0 -0
  263. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/pipedrive/typing.py +0 -0
  264. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/quickbooks/__init__.py +0 -0
  265. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/resource.py +0 -0
  266. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/revenuecat/__init__.py +0 -0
  267. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/revenuecat/helpers.py +0 -0
  268. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/salesforce/__init__.py +0 -0
  269. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/salesforce/helpers.py +0 -0
  270. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/shopify/__init__.py +0 -0
  271. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/shopify/exceptions.py +0 -0
  272. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/shopify/helpers.py +0 -0
  273. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/shopify/settings.py +0 -0
  274. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/slack/__init__.py +0 -0
  275. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/slack/helpers.py +0 -0
  276. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/slack/settings.py +0 -0
  277. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/smartsheets/__init__.py +0 -0
  278. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/solidgate/__init__.py +0 -0
  279. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/solidgate/helpers.py +0 -0
  280. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/sql_database/__init__.py +0 -0
  281. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/sql_database/callbacks.py +0 -0
  282. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/stripe_analytics/__init__.py +0 -0
  283. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/stripe_analytics/helpers.py +0 -0
  284. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/stripe_analytics/settings.py +0 -0
  285. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/table_definition.py +0 -0
  286. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/telemetry/event.py +0 -0
  287. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/testdata/fakebqcredentials.json +0 -0
  288. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/tiktok_ads/__init__.py +0 -0
  289. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/tiktok_ads/tiktok_helpers.py +0 -0
  290. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/time.py +0 -0
  291. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/trustpilot/__init__.py +0 -0
  292. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/trustpilot/client.py +0 -0
  293. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/version.py +0 -0
  294. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/wise/__init__.py +0 -0
  295. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/wise/client.py +0 -0
  296. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/zendesk/__init__.py +0 -0
  297. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/zendesk/helpers/__init__.py +0 -0
  298. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/zendesk/helpers/api_helpers.py +0 -0
  299. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/zendesk/helpers/credentials.py +0 -0
  300. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/zendesk/helpers/talk_api.py +0 -0
  301. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/zendesk/settings.py +0 -0
  302. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/zoom/__init__.py +0 -0
  303. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/src/zoom/helpers.py +0 -0
  304. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/testdata/.gitignore +0 -0
  305. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/testdata/create_replace.csv +0 -0
  306. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/testdata/delete_insert_expected.csv +0 -0
  307. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/testdata/delete_insert_part1.csv +0 -0
  308. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/testdata/delete_insert_part2.csv +0 -0
  309. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/testdata/merge_expected.csv +0 -0
  310. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/testdata/merge_part1.csv +0 -0
  311. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/testdata/merge_part2.csv +0 -0
  312. {ingestr-0.14.1 → ingestr-0.14.3}/ingestr/tests/unit/test_smartsheets.py +0 -0
  313. {ingestr-0.14.1 → ingestr-0.14.3}/package-lock.json +0 -0
  314. {ingestr-0.14.1 → ingestr-0.14.3}/package.json +0 -0
  315. {ingestr-0.14.1 → ingestr-0.14.3}/pyproject.toml +0 -0
  316. {ingestr-0.14.1 → ingestr-0.14.3}/requirements-dev.txt +0 -0
  317. {ingestr-0.14.1 → ingestr-0.14.3}/requirements.in +0 -0
  318. {ingestr-0.14.1 → ingestr-0.14.3}/requirements.txt +0 -0
  319. {ingestr-0.14.1 → ingestr-0.14.3}/requirements_arm64.txt +0 -0
  320. {ingestr-0.14.1 → ingestr-0.14.3}/resources/demo.tape +0 -0
  321. {ingestr-0.14.1 → ingestr-0.14.3}/resources/ingestr.svg +0 -0
  322. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/AMPM.yml +0 -0
  323. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Acronyms.yml +0 -0
  324. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Colons.yml +0 -0
  325. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Contractions.yml +0 -0
  326. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/DateFormat.yml +0 -0
  327. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Ellipses.yml +0 -0
  328. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/EmDash.yml +0 -0
  329. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Exclamation.yml +0 -0
  330. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/FirstPerson.yml +0 -0
  331. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Gender.yml +0 -0
  332. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/GenderBias.yml +0 -0
  333. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/HeadingPunctuation.yml +0 -0
  334. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Headings.yml +0 -0
  335. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Latin.yml +0 -0
  336. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/LyHyphens.yml +0 -0
  337. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/OptionalPlurals.yml +0 -0
  338. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Ordinal.yml +0 -0
  339. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/OxfordComma.yml +0 -0
  340. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Parens.yml +0 -0
  341. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Passive.yml +0 -0
  342. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Periods.yml +0 -0
  343. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Quotes.yml +0 -0
  344. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Ranges.yml +0 -0
  345. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Semicolons.yml +0 -0
  346. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Slang.yml +0 -0
  347. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Spacing.yml +0 -0
  348. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Spelling.yml +0 -0
  349. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Units.yml +0 -0
  350. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/We.yml +0 -0
  351. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/Will.yml +0 -0
  352. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/WordList.yml +0 -0
  353. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/meta.json +0 -0
  354. {ingestr-0.14.1 → ingestr-0.14.3}/styles/Google/vocab.txt +0 -0
  355. {ingestr-0.14.1 → ingestr-0.14.3}/styles/bruin/Ingestr.yml +0 -0
  356. {ingestr-0.14.1 → ingestr-0.14.3}/styles/config/vocabularies/bruin/accept.txt +0 -0
  357. {ingestr-0.14.1 → ingestr-0.14.3}/test.env.template +0 -0
@@ -0,0 +1,151 @@
1
+ # WARN: this is used as a notification filter in our slack.
2
+ # When updating this, make sure to update the workflow subscription as well.
3
+ name: "Release ingestr on pip and ghcr.io"
4
+
5
+ on:
6
+ push:
7
+ tags:
8
+ - "v*.*.*"
9
+
10
+ env:
11
+ REGISTRY: ghcr.io
12
+ IMAGE: ghcr.io/${{ github.repository }}
13
+
14
+ jobs:
15
+ tests:
16
+ uses: ./.github/workflows/tests.yml
17
+ pip-release:
18
+ runs-on: ubuntu-latest
19
+ needs: tests
20
+ env:
21
+ TWINE_PASSWORD: ${{ secrets.PYPI_INGESTR_TOKEN }}
22
+ steps:
23
+ - name: checkout
24
+ uses: actions/checkout@v4
25
+ with:
26
+ fetch-depth: 0
27
+ - name: setup python
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version: '3.11'
31
+
32
+ # github actions invoke a fresh shell
33
+ # for each step. This causes us to lose our
34
+ # venv context. So we run all our build commands
35
+ # in a single step to simplify our pipeline.
36
+ - name: build and release
37
+ run: |
38
+ pip install uv
39
+ uv venv
40
+ source .venv/bin/activate
41
+ uv pip install -r requirements-dev.txt
42
+ make build
43
+ make upload-release
44
+
45
+ docker-build:
46
+ if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
47
+ runs-on: ubuntu-24.04-arm
48
+ strategy:
49
+ fail-fast: false
50
+ matrix:
51
+ platform:
52
+ - linux/amd64
53
+ - linux/arm64
54
+
55
+ permissions:
56
+ contents: read
57
+ packages: write
58
+
59
+ steps:
60
+ - name: Prepare
61
+ run: |
62
+ platform=${{ matrix.platform }}
63
+ echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
64
+
65
+ - name: Checkout repository
66
+ uses: actions/checkout@v4
67
+
68
+ - name: Log in to the Container registry
69
+ uses: docker/login-action@v3
70
+ with:
71
+ registry: ${{ env.REGISTRY }}
72
+ username: ${{ github.actor }}
73
+ password: ${{ secrets.GITHUB_TOKEN }}
74
+
75
+ - name: Extract metadata (tags, labels) for Docker
76
+ id: meta
77
+ uses: docker/metadata-action@v5
78
+ with:
79
+ images: ${{ env.IMAGE }}
80
+
81
+ - name: Set up Docker Buildx
82
+ uses: docker/setup-buildx-action@v3
83
+
84
+ - name: Build and push Docker image
85
+ uses: docker/build-push-action@v5
86
+ id: build
87
+ with:
88
+ context: .
89
+ platforms: ${{ matrix.platform }}
90
+ tags: ${{ env.IMAGE }}
91
+ labels: ${{ steps.meta.outputs.labels }}
92
+ outputs: type=image,push-by-digest=true,name-canonical=true,push=true
93
+
94
+ - name: Export digest
95
+ run: |
96
+ mkdir -p ${{ runner.temp }}/digests
97
+ digest="${{ steps.build.outputs.digest }}"
98
+ # The following strips the 'sha256:' prefix from the digest using bash parameter expansion.
99
+ touch "${{ runner.temp }}/digests/${digest#sha256:}"
100
+
101
+ - name: Upload digest
102
+ uses: actions/upload-artifact@v4
103
+ with:
104
+ name: digests-${{ env.PLATFORM_PAIR }}
105
+ path: ${{ runner.temp }}/digests/*
106
+ if-no-files-found: error
107
+ retention-days: 1
108
+
109
+ docker-publish:
110
+ permissions:
111
+ contents: read
112
+ packages: write
113
+
114
+ runs-on: ubuntu-latest
115
+ needs:
116
+ - docker-build
117
+ - tests
118
+ steps:
119
+ - name: Download digests
120
+ uses: actions/download-artifact@v4
121
+ with:
122
+ path: ${{ runner.temp }}/digests
123
+ pattern: digests-*
124
+ merge-multiple: true
125
+
126
+ - name: Log in to the Container registry
127
+ uses: docker/login-action@v3
128
+ with:
129
+ registry: ${{ env.REGISTRY }}
130
+ username: ${{ github.actor }}
131
+ password: ${{ secrets.GITHUB_TOKEN }}
132
+
133
+ - name: Set up Docker Buildx
134
+ uses: docker/setup-buildx-action@v3
135
+
136
+ - name: Docker meta
137
+ id: meta
138
+ uses: docker/metadata-action@v5
139
+ with:
140
+ images: ${{ env.IMAGE }}
141
+ tags: |
142
+ type=ref,event=tag
143
+ type=semver,pattern={{raw}}
144
+
145
+ - name: Create manifest list and push
146
+ working-directory: ${{ runner.temp }}/digests
147
+ run: |
148
+ docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
149
+ $(printf '${{ env.IMAGE }}@sha256:%s ' *)
150
+
151
+
@@ -26,7 +26,7 @@ RUN \
26
26
  export ACCEPT_EULA='Y' && \
27
27
  # Install build dependencies
28
28
  apt-get update && \
29
- apt-get install -y curl gcc gpg libpq-dev build-essential unixodbc-dev g++ apt-transport-https
29
+ apt-get install -y curl gcc gpg libpq-dev build-essential unixodbc-dev g++ apt-transport-https git
30
30
 
31
31
  RUN \
32
32
  # Install pyodbc db drivers for MSSQL and PostgreSQL
@@ -50,6 +50,9 @@ RUN if [ "$(uname -m)" = "aarch64" ]; then \
50
50
  cp /app/requirements_arm64.txt /app/requirements.txt; \
51
51
  fi
52
52
 
53
+ # Generate version file
54
+ RUN make write-build-info
55
+
53
56
  # Install all required packages and the application.
54
57
  RUN uv pip install --requirement requirements.txt pyodbc .
55
58
 
@@ -1,6 +1,6 @@
1
1
  SHELL := /bin/bash
2
2
  .ONESHELL:
3
- .PHONY: test lint format test-ci lint-ci build upload-release setup docker-shell
3
+ .PHONY: test lint format test-ci lint-ci build upload-release setup docker-shell write-build-info remove-build-info
4
4
 
5
5
  BUILDINFO=ingestr/src/buildinfo.py
6
6
 
@@ -46,8 +46,14 @@ lint-docs:
46
46
  tl: test lint
47
47
 
48
48
  build: lock-deps
49
- cat > ${BUILDINFO} <<< "version = \"$$(git describe --tags --abbrev=0)\""
49
+ $(MAKE) write-build-info
50
50
  rm -rf dist && python3 -m build
51
+ $(MAKE) remove-build-info
52
+
53
+ write-build-info:
54
+ cat > ${BUILDINFO} <<< "version = \"$$(git describe --tags --abbrev=0)\""
55
+
56
+ remove-build-info:
51
57
  rm -f ${BUILDINFO}
52
58
 
53
59
  upload-release:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ingestr
3
- Version: 0.14.1
3
+ Version: 0.14.3
4
4
  Summary: ingestr is a command-line application that ingests data from various sources and stores them in any database.
5
5
  Project-URL: Homepage, https://github.com/bruin-data/ingestr
6
6
  Project-URL: Issues, https://github.com/bruin-data/ingestr/issues
@@ -5,6 +5,17 @@ export default defineConfig({
5
5
  title: "ingestr",
6
6
  description: "Ingest & copy data between any source and any destination",
7
7
  base: "/ingestr/",
8
+ transformPageData(pageData) {
9
+ const canonicalUrl = `https://getbruin.com/docs/ingestr/${pageData.relativePath}`
10
+ .replace(/index\.md$/, '')
11
+ .replace(/\.md$/, '.html')
12
+
13
+ pageData.frontmatter.head ??= []
14
+ pageData.frontmatter.head.push([
15
+ 'link',
16
+ { rel: 'canonical', href: canonicalUrl }
17
+ ])
18
+ },
8
19
  head: [
9
20
  [
10
21
  "script",
@@ -141,6 +152,7 @@ export default defineConfig({
141
152
  { text: "Gorgias", link: "/supported-sources/gorgias.md" },
142
153
  { text: "HubSpot", link: "/supported-sources/hubspot.md" },
143
154
  { text: "Internet Society Pulse", link: "/supported-sources/isoc-pulse.md" },
155
+ { text: "Jira", link: "/supported-sources/jira.md" },
144
156
  { text: "Klaviyo", link: "/supported-sources/klaviyo.md" },
145
157
  { text: "Linear", link: "/supported-sources/linear.md" },
146
158
  { text: "LinkedIn Ads", link: "/supported-sources/linkedin_ads.md" },
@@ -7,7 +7,7 @@ hero:
7
7
  text: Copy data between any source and any destination
8
8
  tagline: "ingestr is a command-line application that allows copying data from any source into any destination database."
9
9
  image:
10
- src: https://github.com/bruin-data/ingestr/blob/main/resources/demo.gif?raw=true
10
+ src: /demo.gif
11
11
  alt: ingestr logo
12
12
  actions:
13
13
  - theme: brand
@@ -0,0 +1,80 @@
1
+ # Elasticsearch
2
+ [Elasticsearch](https://www.elastic.co/elasticsearch) is a distributed, RESTful search and analytics engine designed for fast and scalable data retrieval.
3
+
4
+ ingestr supports Elasticsearch as both a source and destination.
5
+
6
+ ## URI format
7
+ The URI format for Elasticsearch is as follows:
8
+
9
+ ```plaintext
10
+ elasticsearch://username:password@host:port?secure=<secure>&verify_certs=<verify_certs>
11
+ ```
12
+
13
+ URI parameters:
14
+ - `username`: The username used to authenticate with Elasticsearch (optional).
15
+ - `password`: The password associated with the specified username (optional).
16
+ - `host`: The host address of the Elasticsearch server.
17
+ - `port`: The port number used by the Elasticsearch server (default: 9200).
18
+ - `secure`: Enables HTTPS when set to true. By default, it is true. Set to false for HTTP connections.
19
+ - `verify_certs`: Verifies TLS certificates when set to true. By default, it is true. Only used for sources.
20
+
21
+ The same URI structure can be used both for sources and destinations.
22
+
23
+ ## Using Elasticsearch as a source
24
+
25
+ ### Source Table
26
+
27
+ `<index-name>`: Fetches all available documents from the specified index.
28
+
29
+ ```bash
30
+ ingestr ingest \
31
+ --source-uri "elasticsearch://elastic:changeme@localhost:9200?secure=false&verify_certs=false" \
32
+ --source-table 'test-index' \
33
+ --dest-uri "duckdb:///users.duckdb" \
34
+ --dest-table 'dest.users_detail'
35
+ ```
36
+
37
+ This command retrieves all documents from the test-index in Elasticsearch and copy them to the dest.users_detail table in DuckDB.
38
+
39
+ <img alt="ingestion_elasticsearch_img" src="../media/ingestion_elasticsearch_img.png" />
40
+
41
+ ## Using Elasticsearch as a destination
42
+
43
+ Elasticsearch can be used as a destination to load data from various sources. The `--dest-table` option specifies the index name where data will be loaded.
44
+
45
+ ### Elasticsearch Cloud (with authentication)
46
+
47
+ ```bash
48
+ ingestr ingest \
49
+ --source-uri "postgres://user:pass@localhost:5432/mydb" \
50
+ --source-table "public.users" \
51
+ --dest-uri "elasticsearch://username:password@cluster.cloud.es.io:443" \
52
+ --dest-table "users_index"
53
+ ```
54
+
55
+ > [!NOTE]
56
+ > Cloud Elasticsearch instances typically use HTTPS (port 443). The `secure` parameter defaults to `true`, so HTTPS is used automatically.
57
+
58
+ ### Local Elasticsearch with authentication
59
+
60
+ ```bash
61
+ ingestr ingest \
62
+ --source-uri "csv:///path/to/data.csv" \
63
+ --source-table "data" \
64
+ --dest-uri "elasticsearch://elastic:changeme@localhost:9200?secure=false" \
65
+ --dest-table "myindex"
66
+ ```
67
+
68
+ ### Local Elasticsearch without authentication
69
+
70
+ ```bash
71
+ ingestr ingest \
72
+ --source-uri "csv:///path/to/data.csv" \
73
+ --source-table "data" \
74
+ --dest-uri "elasticsearch://localhost:9200?secure=false" \
75
+ --dest-table "myindex"
76
+ ```
77
+
78
+ > [!TIP]
79
+ > By default, ingestr uses a "replace" strategy which deletes the existing index before loading new data. The target index will be created automatically if it doesn't exist.
80
+
@@ -104,6 +104,7 @@ Fluxx source allows ingesting the following sources into separate tables:
104
104
  | `affiliate_type` | id | - | replace | Affiliate Type management and tracking |
105
105
  | `aha_requirements_tickets` | id | - | replace | Aha Requirements Tickets management and tracking |
106
106
  | `alert` | id | - | replace | Alert management and tracking |
107
+ | `alert_email` | id | - | replace | Alert email configurations and templates for notification delivery |
107
108
  | `alert_email_user` | id | - | replace | Alert Email User management and tracking |
108
109
  | `alert_model_log` | id | - | replace | Alert Model Log management and tracking |
109
110
  | `alert_recipient` | id | - | replace | Alert Recipient management and tracking |
@@ -0,0 +1,57 @@
1
+ # Intercom
2
+
3
+ [Intercom](https://www.intercom.com/) is a customer messaging platform that helps businesses connect with customers through targeted, behavior-driven messages.
4
+
5
+ ingestr supports Intercom as a source.
6
+
7
+ ## URI format
8
+
9
+ The URI format for Intercom is as follows:
10
+
11
+ ```plaintext
12
+ intercom://?access_token=<access_token>&region=<region>
13
+ ```
14
+
15
+ URI parameters:
16
+
17
+ - `access_token`: The access token is used for authentication with the Intercom API.
18
+ - `region`: The data region where your Intercom workspace is hosted. Valid values are `us`, `eu`, or `au`. Defaults to `us`.
19
+
20
+ The URI is used to connect to the Intercom API for extracting data.
21
+
22
+ ## Setting up an Intercom Integration
23
+
24
+ Intercom requires a few steps to set up an integration, please follow the guide dltHub [has built here](https://dlthub.com/docs/dlt-ecosystem/verified-sources/intercom).
25
+
26
+ Once you complete the guide, you should have an access token. Let's say your access token is `dG9rOjE...` and your workspace is in the US region, here's a sample command that will copy the data from Intercom into a DuckDB database:
27
+
28
+ ```sh
29
+ ingestr ingest \
30
+ --source-uri 'intercom://?access_token=dG9rOjE...&region=us' \
31
+ --source-table 'contacts' \
32
+ --dest-uri duckdb:///intercom.duckdb \
33
+ --dest-table 'intercom.contacts'
34
+ ```
35
+
36
+ The result of this command will be a table in the `intercom.duckdb` database.
37
+
38
+ ## Tables
39
+
40
+ Intercom source allows ingesting the following sources into separate tables:
41
+
42
+ | Table | PK | Inc Key | Inc Strategy | Details |
43
+ |-------|----|---------|--------------|---------|
44
+ | [contacts](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Contacts/contact/) | id | updated_at | merge | Retrieves information about contacts (visitors, users, and leads) |
45
+ | [companies](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Companies/company/) | id | updated_at | merge | Retrieves information about companies |
46
+ | [conversations](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Conversations/conversation/) | id | updated_at | merge | Retrieves conversation data |
47
+ | [articles](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Articles/article/) | id | updated_at | merge | Retrieves help center articles |
48
+ | [tags](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tags/tag/) | id | - | replace | Retrieves tags used to organize contacts and companies |
49
+ | [segments](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Segments/segment/) | id | - | replace | Retrieves segments for filtering contacts and companies |
50
+ | [admins](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Admins/admin/) | id | - | replace | Retrieves admin user information |
51
+ | [teams](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Teams/team/) | id | - | replace | Retrieves team information |
52
+ | [data_attributes](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Data%20Attributes/dataattribute/) | name | - | replace | Retrieves data attributes (both built-in and custom attributes) |
53
+
54
+ Use these as `--source-table` parameter in the `ingestr ingest` command.
55
+
56
+ > [!TIP]
57
+ > Resources marked with "merge" Inc Strategy support incremental loading based on the `updated_at` timestamp, which means subsequent runs will only fetch new or updated records.
@@ -0,0 +1,61 @@
1
+ # Jira
2
+
3
+ [Jira](https://www.atlassian.com/software/jira) is a proprietary issue tracking product developed by Atlassian that allows bug tracking and agile project management.
4
+
5
+ ingestr supports Jira as a source through [Jira's REST API v3](https://developer.atlassian.com/cloud/jira/platform/rest/v3/).
6
+
7
+ ## URI format
8
+
9
+ The URI format for Jira is:
10
+
11
+ ```plaintext
12
+ jira://your-domain.atlassian.net?email=<email>&api_token=<api_token>
13
+ ```
14
+
15
+ URI parameters:
16
+ - `email`: the email address used for authentication with the Jira API
17
+ - `api_token`: the API token for authentication (required for Jira Cloud)
18
+
19
+ ## Example usage
20
+
21
+ Assuming your Jira domain is `company.atlassian.net`, email is `user@company.com`, and API token is `ATATT3xFfGF0...`, you can ingest issues into DuckDB using:
22
+
23
+ ```bash
24
+ ingestr ingest \
25
+ --source-uri 'jira://company.atlassian.net?email=user@company.com&api_token=ATATT3xFfGF0...' \
26
+ --source-table 'issues' \
27
+ --dest-uri duckdb:///jira.duckdb \
28
+ --dest-table 'dest.issues'
29
+ ```
30
+
31
+ ## Authentication
32
+
33
+ To connect to Jira, you need:
34
+
35
+ 1. **Email**: Your Atlassian account email
36
+ 2. **API Token**: Create one from your [Atlassian Account Settings](https://id.atlassian.com/manage-profile/security/api-tokens)
37
+
38
+ ## Tables
39
+
40
+ Jira source allows ingesting the following tables:
41
+
42
+ | Table | PK | Inc Key | Inc Strategy | Details |
43
+ | ----- | -- | ------- | ------------ | ------- |
44
+ | `projects` | id | - | replace | Fetches all projects from your Jira instance. |
45
+ | `issues` | id | fields.updated | merge | Fetches all issues with support for incremental loading based on updated timestamp. |
46
+ | `users` | accountId | - | replace | Fetches users from your Jira instance. |
47
+ | `issue_types` | id | - | replace | Fetches all issue types configured in your Jira instance. |
48
+ | `statuses` | id | - | replace | Fetches all workflow statuses from your Jira instance. |
49
+ | `priorities` | id | - | replace | Fetches all issue priorities from your Jira instance. |
50
+ | `resolutions` | id | - | replace | Fetches all issue resolutions from your Jira instance. |
51
+ | `project_versions` | id | - | replace | Fetches versions for each project. |
52
+ | `project_components` | id | - | replace | Fetches components for each project. |
53
+
54
+ Use these as the `--source-table` parameter in the `ingestr ingest` command.
55
+
56
+ ## Incremental Loading
57
+
58
+ The `issues` table supports incremental loading based on the `updated` field. This means subsequent runs will only fetch issues that have been modified since the last run, making the data ingestion more efficient for large Jira instances.
59
+
60
+ > [!NOTE]
61
+ > Most tables use "replace" write disposition, meaning they will overwrite existing data on each run. Only the `issues` table supports incremental loading with "merge" disposition.
@@ -1,11 +1,13 @@
1
1
  # MongoDB
2
2
  MongoDB is a popular, open source NoSQL database known for its flexibility, scalability, and wide adoption in a variety of applications.
3
3
 
4
- ingestr supports MongoDB as a source.
4
+ ingestr supports MongoDB as both a source and destination.
5
5
 
6
6
  ## URI format
7
- The URI format for MongoDB is as follows:
8
7
 
8
+ MongoDB supports two connection string formats:
9
+
10
+ ### Standard format (local/self-hosted)
9
11
  ```plaintext
10
12
  mongodb://user:password@host:port
11
13
  ```
@@ -16,12 +18,21 @@ URI parameters:
16
18
  - `host`: the host address of the database server
17
19
  - `port`: the port number the database server is listening on, default is 27017 for MongoDB
18
20
 
21
+ ### SRV format (MongoDB Atlas)
22
+ ```plaintext
23
+ mongodb+srv://user:password@cluster.xxxxx.mongodb.net/?retryWrites=true&w=majority
24
+ ```
19
25
 
20
- > [!CAUTION]
21
- > Do not put the database name at the end of the URI for MongoDB, instead make it a part of `--source-table` option as `database.collection` format.
26
+ URI parameters:
27
+ - `user`: the user name to connect to the database
28
+ - `password`: the password for the user
29
+ - `cluster.xxxxx.mongodb.net`: the cluster hostname provided by MongoDB Atlas
30
+ - Query parameters like `retryWrites` and `w` are optional but recommended for Atlas connections
22
31
 
32
+ > [!CAUTION]
33
+ > Do not put the database name at the end of the URI for MongoDB, instead make it a part of `--source-table` or `--dest-table` option as `database.collection` format.
23
34
 
24
- You can read more about MongoDB's connection string format [here](https://docs.mongodb.com/manual/reference/connection-string/).
35
+ The same URI structure can be used both for sources and destinations. You can read more about MongoDB's connection string format [here](https://docs.mongodb.com/manual/reference/connection-string/).
25
36
 
26
37
  ## Source table format
27
38
 
@@ -148,3 +159,43 @@ ingestr performs several validations on custom aggregation pipelines:
148
159
  - Add appropriate indexes to support your aggregation pipeline
149
160
  - Consider using `$limit` to restrict the number of documents processed
150
161
  - For large datasets, MongoDB's `allowDiskUse: true` option is automatically enabled for aggregation pipelines
162
+
163
+ ## Using MongoDB as a destination
164
+
165
+ MongoDB can be used as a destination to load data from various sources. The `--dest-table` option follows the same format: `database.collection`.
166
+
167
+ ### MongoDB Atlas
168
+
169
+ ```bash
170
+ ingestr ingest \
171
+ --source-uri "postgres://user:pass@localhost:5432/mydb" \
172
+ --source-table "public.users" \
173
+ --dest-uri "mongodb+srv://username:password@cluster0.xxxxx.mongodb.net/?retryWrites=true&w=majority" \
174
+ --dest-table "mydb.users"
175
+ ```
176
+
177
+ > [!NOTE]
178
+ > When using MongoDB Atlas as a destination, ensure your IP address is whitelisted in Network Access settings.
179
+
180
+ ### Local MongoDB with authentication
181
+
182
+ ```bash
183
+ ingestr ingest \
184
+ --source-uri "csv:///path/to/data.csv" \
185
+ --source-table "data" \
186
+ --dest-uri "mongodb://username:password@localhost:27017/?authSource=admin" \
187
+ --dest-table "mydb.mycollection"
188
+ ```
189
+
190
+ ### Local MongoDB without authentication
191
+
192
+ ```bash
193
+ ingestr ingest \
194
+ --source-uri "csv:///path/to/data.csv" \
195
+ --source-table "data" \
196
+ --dest-uri "mongodb://localhost:27017" \
197
+ --dest-table "mydb.mycollection"
198
+ ```
199
+
200
+ > [!TIP]
201
+ > By default, ingestr uses a "replace" strategy which deletes existing data in the collection before loading new data. The target database and collection will be created automatically if they don't exist.
@@ -0,0 +1 @@
1
+ version = "v0.14.3"
@@ -813,30 +813,7 @@ class ElasticsearchDestination:
813
813
 
814
814
  class MongoDBDestination:
815
815
  def dlt_dest(self, uri: str, **kwargs):
816
- from urllib.parse import urlparse
817
-
818
- parsed_uri = urlparse(uri)
819
-
820
- # Extract connection details from URI
821
- host = parsed_uri.hostname or "localhost"
822
- port = parsed_uri.port or 27017
823
- username = parsed_uri.username
824
- password = parsed_uri.password
825
- database = (
826
- parsed_uri.path.lstrip("/") if parsed_uri.path.lstrip("/") else "ingestr_db"
827
- )
828
-
829
- # Build connection string
830
- if username and password:
831
- connection_string = f"mongodb://{username}:{password}@{host}:{port}"
832
- else:
833
- connection_string = f"mongodb://{host}:{port}"
834
-
835
- # Add query parameters if any
836
- if parsed_uri.query:
837
- connection_string += f"?{parsed_uri.query}"
838
-
839
- return mongodb_insert(connection_string, database)
816
+ return mongodb_insert(uri)
840
817
 
841
818
  def dlt_run_params(self, uri: str, table: str, **kwargs) -> dict:
842
819
  return {
@@ -1,6 +1,7 @@
1
1
  """Elasticsearch destination helpers"""
2
2
 
3
3
  import json
4
+ import logging
4
5
  from typing import Any, Dict, Iterator
5
6
  from urllib.parse import urlparse
6
7
 
@@ -9,6 +10,10 @@ import dlt
9
10
  from elasticsearch import Elasticsearch
10
11
  from elasticsearch.helpers import bulk
11
12
 
13
+ # Suppress Elasticsearch transport logging
14
+ logging.getLogger("elasticsearch.transport").setLevel(logging.WARNING)
15
+ logging.getLogger("elastic_transport.transport").setLevel(logging.WARNING)
16
+
12
17
 
13
18
  def process_file_items(file_path: str) -> Iterator[Dict[str, Any]]:
14
19
  """Process items from a file path (JSONL format)."""
@@ -52,15 +57,36 @@ def elasticsearch_insert(
52
57
  parsed = urlparse(connection_string)
53
58
 
54
59
  # Build Elasticsearch client configuration
55
- hosts = [
56
- {
57
- "host": parsed.hostname or "localhost",
58
- "port": parsed.port or 9200,
59
- "scheme": parsed.scheme or "http",
60
- }
61
- ]
62
-
63
- es_config: Dict[str, Any] = {"hosts": hosts}
60
+ actual_url = connection_string
61
+ secure = True # Default to HTTPS (secure by default)
62
+
63
+ if connection_string.startswith("elasticsearch://"):
64
+ actual_url = connection_string.replace("elasticsearch://", "")
65
+
66
+ # Parse to check for query parameters
67
+ temp_parsed = urlparse("http://" + actual_url)
68
+ from urllib.parse import parse_qs
69
+
70
+ query_params = parse_qs(temp_parsed.query)
71
+
72
+ # Check ?secure parameter (defaults to true)
73
+ if "secure" in query_params:
74
+ secure = query_params["secure"][0].lower() in ["true", "1", "yes"]
75
+
76
+ # Remove query params from URL for ES client
77
+ actual_url = actual_url.split("?")[0]
78
+
79
+ # Add scheme
80
+ scheme = "https" if secure else "http"
81
+ actual_url = f"{scheme}://{actual_url}"
82
+
83
+ parsed = urlparse(actual_url)
84
+
85
+ es_config: Dict[str, Any] = {
86
+ "hosts": [actual_url],
87
+ "verify_certs": secure,
88
+ "ssl_show_warn": False,
89
+ }
64
90
 
65
91
  # Add authentication if present
66
92
  if parsed.username and parsed.password:
@@ -54,7 +54,9 @@ from ingestr.src.sources import (
54
54
  GorgiasSource,
55
55
  HubspotSource,
56
56
  InfluxDBSource,
57
+ IntercomSource,
57
58
  IsocPulseSource,
59
+ JiraSource,
58
60
  KafkaSource,
59
61
  KinesisSource,
60
62
  KlaviyoSource,
@@ -166,6 +168,8 @@ class SourceDestinationFactory:
166
168
  "fluxx": FluxxSource,
167
169
  "slack": SlackSource,
168
170
  "hubspot": HubspotSource,
171
+ "intercom": IntercomSource,
172
+ "jira": JiraSource,
169
173
  "airtable": AirtableSource,
170
174
  "klaviyo": KlaviyoSource,
171
175
  "mixpanel": MixpanelSource,
@@ -96,6 +96,15 @@ FLUXX_RESOURCES = {
96
96
  "workflow_events": {"data_type": "json", "field_type": "relation"},
97
97
  },
98
98
  },
99
+ "alert_email": {
100
+ "endpoint": "alert_email",
101
+ "fields": {
102
+ "alert_id": {"data_type": "bigint", "field_type": "column"},
103
+ "created_at": {"data_type": "timestamp", "field_type": "column"},
104
+ "id": {"data_type": "bigint", "field_type": "column"},
105
+ "updated_at": {"data_type": "timestamp", "field_type": "column"},
106
+ },
107
+ },
99
108
  "affiliate": {
100
109
  "endpoint": "affiliate",
101
110
  "fields": {