ingestr v1.1.57 was published on 28 September 2026. The main addition is a Salesforce reverse ETL destination, so a pipeline can merge, update, append, delete, or replace records in Salesforce objects. The tag also stops single table runs from renaming the source schema before the read, and it adds QuickBooks purchases and bills.
The full release notes and downloads are on the GitHub release page. Five pull requests sit between v1.1.56 and v1.1.57 on the compare view. The tag is not a prerelease.
Salesforce reverse ETL destination ¶
Pull request 1215 adds the destination. Writes use Bulk API 2.0 unless load_method is set to rest on the destination table. That parameter is not part of the connection URI. Match on an External ID or on a lookup field such as Email. Parent links work, including a polymorphic lookup like Who.Contact.Ext_Id__c. Objects and fields are checked before the write. Salesforce login moved into internal/salesforceauth, shared with the existing source.
Append refuses a match field on both HubSpot and Salesforce. On append, --primary-key only labels rejected rows. The destination table parameter write_nulls is removed. Null handling goes through --write-nulls. An unknown --schema-naming value is now an error when the destination keeps column names verbatim.
Bulk loads reject a literal #N/A, refuse binary fields, and scope delete by id. Lookup names match without regard to case. A replace whose every row was rejected skips the replace sweep, so a total reject does not clear the object. A null AccountId next to a set Account.Ext__c relationship is not sent, because sending it would clear the link.
Single table runs keep source column names ¶
Single table runs were renaming columns on the schema object the source uses to build its query. Pull request 1214 clones that schema before the naming convention runs. The old path renamed in place on the TableSchema from GetSchema. Sources that read that object, instead of opts.Schema, queried the database with destination names. The multi table path already cloned first, inside normalizeMultiTableInfo. Reads now keep source names. ColumnRenamer still maps each batch onto the destination names.
The symptom depended on the engine. Oracle and HANA raised ORA-00904 on ordinary uppercase tables. ClickHouse, DuckDB, BigQuery, Databricks, Fabric, and Vertica raised unknown column errors for camel case and Pascal case names. A Postgres CDC snapshot failed when a renamed column such as customer_name was missing under the source name. SQL Server CDC, Twenty, and Abra did not fail. Renamed columns loaded as NULL and the run exited success. A green history on those three does not prove the destination holds source values. After this tag those columns should fill, and a downstream model that treated the NULL as real input will shift.
QuickBooks purchases and bills ¶
The v1 QuickBooks source had five tables, and none of them held expense transactions. Spend and accounts payable models had to stay on the Python v0 source. Pull request 1219 adds purchases and bills, mapped to Purchase and Bill. Both names are registered in supportedTables and tableMapping inside pkg/source/quickbooks/quickbooks.go.
The new tables keep the existing contract. The primary key is id. The incremental column is lastupdatedtime. The write strategy is merge. The read is SELECT * FROM Purchase or SELECT * FROM Bill. Sandbox fixtures held 35 purchases and 15 bills, and a second merge did not duplicate rows. The other five v1 tables are untouched.
Help text and the MinIO test image ¶
ingest --help printed the wrong default for --write-nulls. Pull request 1217 changes that line to (default: true), which matches reverse ETL runs that write nulls unless told otherwise. --reject-mode now prints (default: fail). The string is display only. The flag still has no stored default, because any value that is not empty is rejected on warehouse destinations. Load behavior does not change. A wrapper that scrapes the old (default: false) line will see a different string.
Pull request 1216 does not ship in the binary. quay.io/minio/minio started requiring a login, and minio/minio left Docker Hub. The Iceberg MinIO end to end test failed, and blob storage tests skipped. CI now pulls pgsty/minio ahead of the job, and the integration tests use that image. Production ingest paths do not pull it.
Upgrade notes ¶
Append jobs on Salesforce or HubSpot that also set a match field will fail. Drop the match field, or switch to merge or update when the match is required. --primary-key on append only marks rejected rows.
Remove write_nulls from destination table parameters and set --write-nulls if you want an explicit choice. Reverse ETL already wrote nulls by default. An unrecognized --schema-naming value now fails reverse ETL runs that keep column names verbatim.
Sample single table pipelines that apply a naming convention. Oracle, HANA, and the camel case warehouses should start loading where they previously errored. SQL Server CDC, Twenty, and Abra may change stored values from NULL to the source data. Compare a few keys if a downstream filter depends on those columns.
QuickBooks assets pinned to the Python v0 source only for Purchase and Bill can move to v1. Leave the pin if another object still exists only on v0.
Where to get it ¶
- Release page: v1.1.57
- Repository:
bruin-data/ingestr - Tag:
v1.1.57