Google Dataform connector

Assertions as quality checks

How Dataform assertions become quality suites, checks and pass or fail results in Blindata, and who owns them

Dataform pipelines carry their own data quality tests: assertions. The connector brings them into Blindata’s data quality module, so the same checks that gate your pipeline appear next to your other quality checks , linked to the tables they verify, with a result every time Dataform runs them.

This is on by default. To turn it off, set capabilities.qualityChecks to false.

What is created

In Dataform In Blindata
The assertions of one repository environment One quality suite, published, named <projectId>/<repositoryId> (<environment>)
One assertion One quality check in that suite, linked to the table it verifies
One run of an assertion that succeeded or failed One result for that check: pass or fail

An environment with no assertion has no suite. The suite description says it is managed by the Blindata agent. The suite has the code dataform:<project>/<location>/<repository>/<environment>. The job finds its suites by name and code, so do not rename or recode them: it would not recognize the suite.

Checks

Kinds of assertion

Kind Where it comes from Check description Linked to
uniqueKey The assertions: { uniqueKey: [...] } setting of a table The description given in Dataform, else Unique key on <table> The table that declares it
rowConditions The assertions: { rowConditions: [...] } setting of a table The description given in Dataform, else Row conditions on <table> The table that declares it
manual An assertion you wrote as its own action (a type: "assertion" file) The description given in Dataform, else Manual assertion on <tables> Every table it depends on: relations, declarations, data preparations and operations with an output

If a table that should be linked is not in the Blindata catalog, the check is created without that link, and the run reports TARGET_NOT_CATALOGUED. In a dry run no link is created.

Identity and settings

Field Value
Code The suite code, a /, then the assertion’s schema.name. Codes longer than 255 characters are shortened, ending with a hash, and stay unique.
Name The assertion’s schema.name, for example dataform_assertions.reporting_customer_orders_assertions_uniqueKey_0
Enabled true, unless the assertion is disabled in Dataform
Scoring A pass scores 100 (green) and a fail scores 0 (red). Both thresholds are 100.
Properties dataformAssertionKind, dataformActionId, dataformAssertionView, dataformFilePath, dataformTags and dataformAssertionSql (the assertion’s query)

The check is not manual: it has no “Add result” action in the UI, because results come from Dataform.

A check code is unique in the tenant. If a code already belongs to a check in another suite, the connector does not touch it, and reports CHECK_CODE_CONFLICT for that assertion.

Results

Each time Dataform runs an assertion, it succeeds or fails. The connector turns the outcome into a quality result:

Dataform outcome Quality result
SUCCEEDED A pass: metric 0, score 100
FAILED A fail: metric 1, score 0, with the failure reason from Dataform as the description (up to 1,000 characters)
SKIPPED, DISABLED, CANCELLED, RUNNING, PENDING No result. They are counted by state in the run report (qualityResults.skippedByState).

The result has the start and end time Dataform gives to the assertion, and a single element (the assertion). Pass or fail is all it tells you: the number of failing rows is not imported.

Which runs count:

  • Only the runs of that environment: the runs whose compilation was produced by the environment’s release configuration. A run of another release configuration of the same repository is ignored.
  • Newest first, at most limits.maxInvocationsQueriedPerEnvironment runs (50 by default).
  • Only runs newer than the check’s last result. Nothing is imported twice.
  • For a check with no result yet, the runs that started in the last quality.firstImportLookbackDays days (7 by default). With 0, no past run is imported the first time.

All the results of a run of the job are uploaded together, oldest first, so each check ends on its latest outcome. Runs happen in Dataform on their own schedule: the job picks up what Dataform ran since the previous job run, within the number of runs it reads, so schedule the job often enough that fewer runs than that happen between two job runs.

Ownership and edits

The suites and checks created by the connector are managed by the job. On every run it compares what it would write with what is stored, and updates the check when anything differs. This means:

  • Edits to the managed fields do not last. Name, description, enabled state, scoring and thresholds, linked tables and additional properties are set back to what Dataform defines. A property a steward adds to a check is removed on the next update.
  • A suite stays published. The job restores the description and the published state of its suites. Do not unpublish one: turn off qualityChecks instead.
  • Fields the job does not manage are kept. Last results, and anything else you can set on a check that the job does not write, stay as they are.
  • Other checks are never touched. The job modifies only the checks whose code it generated, in its own suites.
  • Checks are not deleted. When an assertion disappears from Dataform, its check is disabled (for an environment that was read completely), so the history of results stays. Disable or delete it in Blindata if you do not want to see it.

To stop the job from managing quality at all, turn off capabilities.qualityChecks. The suites and checks already created stay in Blindata as they are.

Permissions

The Blindata user behind the target connection needs QUALITY_ADMIN to create and update suites, and QUALITY_EDITOR to create and update checks and upload results. If either is missing, the quality round stops, the run reports QUALITY_PERMISSION_MISSING once, and the catalog and the lineage are still published. See Prepare Google Cloud .

Example

In the repository ecommerce-demo described in Dataform to Blindata catalog , the table reporting.customer_orders declares a unique key on customer_id and a row condition order_count >= 0. Deployed with a production release configuration, the job creates:

Object Value
Suite Code dataform:acme-analytics/us/ecommerce-demo/production, name acme-analytics/ecommerce-demo (production)
Check dataform_assertions.reporting_customer_orders_assertions_uniqueKey_0, kind uniqueKey, linked to reporting.customer_orders
Check dataform_assertions.reporting_customer_orders_assertions_rowConditions, kind rowConditions, linked to reporting.customer_orders

If the last run of the workflow succeeded on the first assertion and failed on the second, the first check gets a result with score 100 and the second one a result with score 0 and Dataform’s failure reason. Results appear in the quality cockpit and in each check, as for any other check. How results are read is explained in Collecting results .

Limits

  • Pass or fail only. No failing-row counts, and no link from a result to the failing columns.
  • Assertions do not become flows. They are never part of lineage.
  • Suites exist only for environments that have an assertion. If every assertion of an environment disappears, there is no suite left for the job to update, so its old checks stay enabled until you disable them.
  • The job reads results from Dataform’s runs only. Assertions are never executed by the agent.