Configure the Dataform connector
Create the Google Cloud connection and the Dataform job in the Blindata Agent, with every configuration option explained
This page walks you through the connection, the job, and then every field of the job configuration, from top to bottom. The job type is DATAFORM.
Before you start, complete Prepare Google Cloud : you need the service account key file (or Application Default Credentials), and the ids of the Google Cloud projects that hold your Dataform repositories.
Create the Google Cloud connection
Create the connection in the Blindata Agent, on the agent that will run the job. Open the agent, go to Connections, create a connection of type Google Cloud (see Manage Connections
), and fill in the properties below. Use the connection name as the value of connectionName.
The connection is generic: it holds how to sign in to Google Cloud, not which project to read. The projects are listed in the job. It uses shared (service principal) credentials.
In the connection wizard, search for Google Cloud (searching for “Dataform” or “BigQuery” finds it too). The wizard fields map to the properties below:
- Authentication section: the Use Application Default Credentials switch (
useApplicationDefaultCredentials) and, only while the switch is off, the Service account key file upload (keyFile), asked for in the credentials step. - Impersonation section: Impersonated service account (
impersonateServiceAccount). - Regional endpoints section: Dataform endpoint (
dataformEndpoint).
| Property | Required | Default | Description |
|---|---|---|---|
useApplicationDefaultCredentials |
No | false |
true signs in with the identity of the agent’s environment (ADC). true or false, in any case. |
keyFile |
Yes, unless ADC is true |
none | The service account key (JSON file), attached to the connection as a secret file. It must have "type": "service_account", a client_email and a private_key. It is ignored when ADC is true. |
impersonateServiceAccount |
No | none | E-mail of a target service account to impersonate, such as reader@my-project.iam.gserviceaccount.com. It must end in .gserviceaccount.com. |
dataformEndpoint |
No | https://dataform.googleapis.com |
Regional Dataform endpoint, such as https://dataform.europe-west3.rep.googleapis.com. It must be an https URL with no path. A trailing / is removed. |
Leave impersonateServiceAccount and dataformEndpoint empty unless you need them. Blindata treats the key file as a secret: it is stored encrypted and cannot be viewed after it is saved.
How the agent authenticates
For each run, the agent builds its Google credentials from the connection:
- Key file: the service account in the key file. ADC: the identity the agent runs as, found the way Google client libraries find it.
- With impersonation, it then asks Google for short-lived tokens of the target service account, using the first identity.
- It requests an access token for the platform scope (
https://www.googleapis.com/auth/cloud-platform) and sends it to the Dataform and BigQuery REST APIs. The token is refreshed when it expires, and once when Google answers 401.
Calls that Google answers with 429, 500, 502, 503 or 504 are retried, up to limits.retryMaxAttempts attempts, waiting for the time Google asks for or, otherwise, a few seconds more each time (up to 30).
The connection test only checks that a token can be obtained, including through impersonation. It does not name a project, so it cannot tell whether a project is readable: use a dry run for that.
If the connection is not valid, the job stops before any Google call, with one of these messages. They never contain the key:
| Message | Cause |
|---|---|
Incomplete Google Cloud connection configuration: keyFile is required when useApplicationDefaultCredentials is false |
No key file and ADC is off. |
Invalid Google Cloud connection configuration: useApplicationDefaultCredentials must be true or false |
Another value in the property. |
Invalid Google Cloud connection configuration: keyFile cannot be read |
The attached file is missing or unreadable. |
Invalid Google Cloud connection configuration: keyFile must be a JSON service account key |
The file is not JSON. |
Invalid Google Cloud connection configuration: keyFile must have type service_account |
The JSON is not a service account key (for example, a user’s OAuth client file). |
Invalid Google Cloud connection configuration: keyFile must contain client_email and private_key |
The key is incomplete. |
Invalid Google Cloud connection configuration: impersonateServiceAccount must be a service account e-mail ending in .gserviceaccount.com |
The value is not a service account e-mail. |
Invalid Google Cloud connection configuration: dataformEndpoint must be an https URL with no path |
The endpoint is not https, or has a path. |
Unable to obtain a Google access token: <exception> |
Google refused the key, the ADC lookup found nothing, or impersonation is not allowed. |
The connection is used only to read Google Cloud. Writes go to Blindata through a separate connection, named in outputOptions.targetConnectionName, which must be a Blindata connection (type BLINDATA). That connection is used only when dryRun is false. See Blindata permissions
for what its user needs.
Create the job
- Open the agent, go to Schedules, and create a schedule with job type
DATAFORM. Set the cron expression and the time zone. - Paste the job configuration (JSON, below) as the job’s configuration.
- Save the schedule. Run it, then check its log in the agent’s Runs tab.
The job configuration is a JSON object. Unknown fields are ignored without an error (see Common mistakes ).
Job configuration parameters
The job configuration has these top-level fields. Only connectionName, projects and dataFlowScope are always required.
| Field | Type | Default | Required | Description | When to change |
|---|---|---|---|---|---|
connectionName |
string | none | Yes | Name of the Google Cloud connection on this agent. | Always set. |
projects |
string[] | none | Yes | Google Cloud project ids that hold the Dataform repositories to read. At least one. | Always set. |
dataFlowScope |
string | none | Yes | Scope written on every data flow this job creates. The post-run cleanup also uses it. | Use a value used by this job only. It must not end with (Dataform). |
locations |
string[] | [] |
No | Locations to read in each project, such as europe-west3. Empty reads every location of the project. |
To read only some locations. |
repositories
|
object | all | No | Include and exclude rules for repositories. | To catalog a subset of the repositories. |
environments
|
object | all enabled release configurations | No | Which release configurations are read, and what to do for repositories without any. | To read production only. |
systems
|
object | see below | No | How BigQuery projects and the Dataform System map to Blindata Systems. | To reuse the Systems a BigQuery crawl already created, or to rename them. |
capabilities
|
object | see below | No | Which kinds of metadata are read and published. | To turn off features you do not need. |
runtimeLineage
|
object | { "mode": "OFF" } |
No | Reserved. Only OFF is accepted. |
Never. |
quality
|
object | see below | No | How much run history is imported for new quality checks. | To import more or less history on the first run. |
queryBucketPattern |
string | <projectId>/<repository>/<environment> (Dataform) |
No | Name of the query bucket created for each repository environment. | To follow a naming convention. |
limits
|
object | see below | No | Parallelism, retries and read budgets. | Only when Google throttles the run, or for very large repositories. |
outputOptions
|
object | dry run | No | Where to upload the result, and whether to upload at all. | To move from a dry run to a live upload. |
cleanupOptions
|
object | off | No | Removes stale content after a full upload. | To enable post-run cleanup. |
Omitting outputOptions, or leaving dryRun out of it, makes the job a dry run.
Project ids are the ids, not the names or numbers: 6 to 30 characters, lowercase letters, digits and hyphens, starting with a letter. A domain-scoped id such as example.com:my-project is accepted.
queryBucketPattern accepts the placeholders <projectId>, <location>, <repository> and <environment>, and must contain <repository> and <environment>. Bucket names are unique in Blindata, so keep <projectId> in the pattern when two projects can have a repository with the same id.
repositories
| Field | Type | Default | Description |
|---|---|---|---|
includePatterns |
regex[] | [] |
If not empty, a repository is read only if a pattern matches its whole id, or <projectId>/<repositoryId>. |
excludePatterns |
regex[] | [] |
A repository that matches any pattern is skipped. Exclude wins over include. |
Patterns are Java regular expressions. They are case-sensitive, and they must match the whole id (prod-.* matches prod-orders, but orders does not match prod-orders). A repository that is filtered out is reported as skipped, with the reason FILTERED.
Repositories are classified by their labels. Regular Dataform repositories and BigQuery pipelines are read. Standalone BigQuery Studio assets (saved queries, notebooks, data canvases and data preparations that are not part of a repository or pipeline) are skipped and counted in the run report.
environments
An environment is a repository plus the release configuration that produced the compilation the job reads. It is named after the release configuration id.
| Field | Type | Default | Description |
|---|---|---|---|
releaseConfigs |
string[] | [] |
Release configurations to read, as <releaseConfigId> or <repositoryId>/<releaseConfigId>. Empty reads every release configuration that is enabled. A configuration you list is read even if it is disabled. |
fallback |
string | INVOCATION_THEN_COMPILATION |
What to read for a repository that has no release configuration. INVOCATION_THEN_COMPILATION: the compilation of its latest successful run, else its latest compilation that is not a workspace. The environment is named default. NONE: nothing. |
Workspace and user-scoped compilations are never read. A repository whose release configurations are all left out by releaseConfigs is skipped, with the reason NO_SELECTED_ENVIRONMENT. A selected release configuration that has not produced a compilation yet gives the gap NO_COMPILATION_RESULT for that environment: the repository is still cataloged.
Each environment can write different tables, because release configurations can add suffixes or prefixes, or change the default project or dataset. Reading development environments adds their tables and lineage to the catalog. Most teams read production only: see Recommended setups .
systems
| Field | Type | Default | Description |
|---|---|---|---|
projectSystems |
object[] | [] |
Pins a BigQuery project to a Blindata System. Each entry has projectId (required), and systemName or systemUuid, with no repeated projectId. |
projectSystemNamePattern |
string | <projectId> |
Name of the System created for a BigQuery project that is not pinned and not found. It must contain <projectId>. |
dataformSystem.name |
string | Google Dataform |
Name of the System that holds repositories and process-only actions. |
dataformSystem.uuid |
string | none | Uuid of an existing System to use instead of the name. |
The System of a BigQuery project is found in this order: a projectSystems entry; a System that already carries the property bigQueryProjectId with that project id; a System with the name given by projectSystemNamePattern; otherwise a new System is created. A systemName that does not exist is created. A systemUuid that does not exist stops the run with an error (in a dry run it is planned as a new System).
Every project that the pipelines read or write gets a System, including source projects you did not list in projects. See Dataform to Blindata catalog
.
capabilities
| Field | Type | Default | Description | When to change |
|---|---|---|---|---|
bigQueryMetadata |
boolean | true |
Reads the metadata of every BigQuery table the pipelines name (type, columns, GoogleSQL types, position, descriptions) and of the routines they create. When false, no BigQuery call is made. |
Set false when the service account has no BigQuery role. |
processLayer |
boolean | true |
Publishes the Google Dataform System with a repository entity per repository, and the operations without output and notebooks. Also holds the scripts that are analyzed as routines. When false, none of these is published and scripted operations are not analyzed (SCRIPT_NOT_ANALYZED). |
Set false to enrich only the BigQuery Systems. |
columnLineage |
boolean | true |
Sends the SQL of the actions to a query bucket for column-level lineage. When false, only table flows are published, and no bucket, statement or script routine is created. |
Set false to publish table lineage only. |
qualityChecks |
boolean | true |
Publishes assertions as quality checks and their run results. When false, nothing is written to quality and no run is read for quality. |
Set false if you do not use assertions or the quality module. |
assertionViews |
boolean | false |
Also catalogs the views Dataform creates to run assertions, as VIEW entities in the assertion schema. |
Set true to see assertion views in the catalog. |
runMetadata |
boolean | false |
Reads the runs of each repository and adds the state, time, failure and BigQuery job of the last run as properties of each table. It reads more runs, within the limits below. | Set true to show freshness and failures on the entity. |
runtimeLineage
| Field | Type | Default | Description |
|---|---|---|---|
mode |
string | OFF |
Only OFF is accepted in this release. COMPLEMENT is rejected: see Validation errors
. |
Runtime lineage from Dataplex is not available yet. The other keys of this block are accepted and have no effect.
quality
| Field | Type | Default | Description |
|---|---|---|---|
firstImportLookbackDays |
integer | 7 |
For a check that has no result yet, imports the runs that started in the last N days, from 0 to 30. With 0, no past run is imported the first time. |
After the first import, only runs newer than the check’s last result are imported. See Assertions as quality checks .
limits
| Field | Type | Default | Range | Description |
|---|---|---|---|---|
maxParallelism |
integer | 4 |
1 to 16 | Google reads in parallel. |
retryMaxAttempts |
integer | 5 |
1 to 10 | Attempts for a call that Google throttles or answers with a server error. |
invocationRequestsPerMinute |
integer | 50 |
1 to 60 | Requests per minute to read workflow runs. Google allows 60 per minute and project. |
maxInvocationsPerRepository |
integer | 500 |
1 to 5000 | Most runs listed per repository, newest first, to choose a fallback environment, import assertion results and read last run properties. Older runs are not read, and the run reports RUN_BUDGET_EXHAUSTED. |
maxInvocationsQueriedPerEnvironment |
integer | 50 |
1 to 1000 | Runs read per environment, newest first, for assertion results and last run properties. |
maxCompilationResultsListed |
integer | 200 |
1 to 1000 | Compilation results listed per repository when looking for the latest one. |
maxTablesListedPerDataset |
integer | 10000 |
100 to 100000 | Tables listed in a dataset to find the schema of a wildcard table such as events_*. Beyond it, the table gets no fields (WILDCARD_SCHEMA_UNAVAILABLE). |
outputOptions
| Field | Type | Default | Description |
|---|---|---|---|
dryRun |
boolean | true |
true reads Google Cloud and counts what it would upload. Nothing is written to Blindata. |
targetConnectionName |
string | none | Name of the Blindata connection (type BLINDATA) that receives the upload. Required when dryRun is false. |
defaultHidden |
string | none | Passed as the isHidden query parameter of the Blindata CSV upload. Leave it empty unless you need it. |
A dry run reads everything and reports what the run would create. Because it reads nothing from Blindata, it treats every System and entity as new, so its counts are an upper bound, and links from quality checks to tables are not resolved. The run report has dryRun: true.
cleanupOptions
cleanupOptions is the standard Blindata system cleanup, the same object the other agent connectors use. After a successful run, it deletes content of the Google Dataform System that was not updated for daysFromLastUpdate days. Cleanup runs only when all the following are true:
daysFromLastUpdateis greater than 0.- The run is not a dry run.
- The run is complete: no project or location was unreadable, every environment was read without compilation errors and with all the BigQuery metadata it needed, and lineage finished for every environment.
- The Google Dataform System exists, that is,
capabilities.processLayeris on.
When a condition fails, the log says which one.
| Field | Type | Default | Description |
|---|---|---|---|
daysFromLastUpdate |
integer | 0 |
Content not updated for this number of days is deleted. 0 turns cleanup off. |
physicalEntitiesDeletionEnabled |
boolean | false |
Deletes stale physical entities (repositories and process entities) of the Google Dataform System. |
physicalFieldsDeletionEnabled |
boolean | false |
Deletes stale physical fields of the Google Dataform System. |
systemRoutinesDeletionEnabled |
boolean | false |
Deletes stale system routines of the Google Dataform System (the scripts analyzed as routines). |
dataFlowsDeletionEnabled |
boolean | false |
Deletes stale data flows of your dataFlowScope. |
allResourcesDeletionEnabled |
boolean | false |
Deletes stale resources of every type above. |
limit |
integer | none | Maximum number of resources deleted per type in one cleanup. |
The flags are sent to Blindata as you write them: only the ones you set to true delete anything. The job sets the cleanup level to SYSTEM, the System to the Google Dataform System and the data flow scope to your dataFlowScope.
Good to know:
- BigQuery project Systems are never cleaned: they may belong to a BigQuery crawl. A table that is deleted in BigQuery stays in Blindata until your crawl removes it.
- Flows of query buckets are not in your
dataFlowScope. The job removes stale statements, and with them their flows, itself, on every run, for each environment it read completely. It also removes the script routines it no longer plans, together with their statements. - Script routines that were not analyzed for a while. When a script is held back (for example, because a table it reads has no columns in Blindata), its routine is not updated. With
systemRoutinesDeletionEnabled, cleanup deletes it afterdaysFromLastUpdatedays, and the next run removes its statements and the lineage they produced. The lineage comes back when the script can be analyzed again.
Full example
This configuration lists every field with its default value, except the pinned projectSystems entry and the project, which are examples. Anything you leave out takes the default shown.
{
"connectionName": "google-cloud",
"projects": ["my-dataform-project"],
"locations": [],
"dataFlowScope": "dataform",
"repositories": { "includePatterns": [], "excludePatterns": [] },
"environments": {
"releaseConfigs": [],
"fallback": "INVOCATION_THEN_COMPILATION"
},
"systems": {
"projectSystems": [
{
"projectId": "my-raw-project",
"systemName": "BigQuery Raw"
}
],
"projectSystemNamePattern": "<projectId>",
"dataformSystem": { "name": "Google Dataform" }
},
"capabilities": {
"bigQueryMetadata": true,
"processLayer": true,
"columnLineage": true,
"qualityChecks": true,
"assertionViews": false,
"runMetadata": false
},
"runtimeLineage": { "mode": "OFF" },
"quality": { "firstImportLookbackDays": 7 },
"queryBucketPattern": "<projectId>/<repository>/<environment> (Dataform)",
"limits": {
"maxParallelism": 4,
"retryMaxAttempts": 5,
"invocationRequestsPerMinute": 50,
"maxInvocationsPerRepository": 500,
"maxInvocationsQueriedPerEnvironment": 50,
"maxCompilationResultsListed": 200,
"maxTablesListedPerDataset": 10000
},
"outputOptions": {
"dryRun": false,
"targetConnectionName": "blindata-prod"
},
"cleanupOptions": { "daysFromLastUpdate": 0 }
}
Recommended setups
Each example shows only the fields that differ from the defaults.
1. First run: dry run. Use the defaults and a dry run. Check the run report before you enable the upload.
{
"connectionName": "google-cloud",
"projects": ["my-dataform-project"],
"dataFlowScope": "dataform",
"outputOptions": { "dryRun": true }
}
2. Nightly upload of production only. Read the production release configuration of every repository, upload, and remove content that was not updated for 30 days. Repositories without release configurations are still read through the fallback.
{
"connectionName": "google-cloud",
"projects": ["my-dataform-project"],
"dataFlowScope": "dataform",
"environments": { "releaseConfigs": ["production"] },
"outputOptions": { "dryRun": false, "targetConnectionName": "blindata-prod" },
"cleanupOptions": {
"daysFromLastUpdate": 30,
"dataFlowsDeletionEnabled": true,
"physicalEntitiesDeletionEnabled": true,
"physicalFieldsDeletionEnabled": true
}
}
3. Reuse the Systems of a BigQuery crawl. Pin the BigQuery projects to the Systems your crawl already created, so Dataform enriches them instead of creating new ones. A System that already has the property bigQueryProjectId is found without this.
{
"connectionName": "google-cloud",
"projects": ["my-dataform-project"],
"dataFlowScope": "dataform",
"systems": {
"projectSystems": [
{
"projectId": "my-dataform-project",
"systemName": "BigQuery Analytics"
},
{ "projectId": "my-raw-project", "systemName": "BigQuery Raw" }
]
},
"outputOptions": { "dryRun": false, "targetConnectionName": "blindata-prod" }
}
4. Enrichment only, without the process layer. Add Dataform context and lineage to your BigQuery entities, with no Google Dataform System and no quality checks. Scripted operations are not analyzed in this setup, because they are analyzed as routines of the Dataform System.
{
"connectionName": "google-cloud",
"projects": ["my-dataform-project"],
"dataFlowScope": "dataform",
"capabilities": { "processLayer": false, "qualityChecks": false },
"outputOptions": { "dryRun": false, "targetConnectionName": "blindata-prod" }
}
5. No BigQuery access. The service account can read Dataform but not BigQuery. The job does not call BigQuery, and relies on the columns your BigQuery crawl already stored. Tables with no stored columns are published without column lineage.
{
"connectionName": "google-cloud",
"projects": ["my-dataform-project"],
"dataFlowScope": "dataform",
"capabilities": { "bigQueryMetadata": false },
"outputOptions": { "dryRun": false, "targetConnectionName": "blindata-prod" }
}
6. One team’s repositories. Read two locations and only the repositories whose id starts with sales-, except the sandbox.
{
"connectionName": "google-cloud",
"projects": ["my-dataform-project"],
"locations": ["europe-west3", "europe-west8"],
"dataFlowScope": "dataform-sales",
"repositories": {
"includePatterns": ["sales-.*"],
"excludePatterns": [".*-sandbox"]
},
"outputOptions": { "dryRun": false, "targetConnectionName": "blindata-prod" }
}
7. Table lineage and catalog only. No SQL analysis and no quality: the lightest run.
{
"connectionName": "google-cloud",
"projects": ["my-dataform-project"],
"dataFlowScope": "dataform",
"capabilities": { "columnLineage": false, "qualityChecks": false },
"outputOptions": { "dryRun": false, "targetConnectionName": "blindata-prod" }
}
Validation errors
The job rejects the configuration before it calls Google Cloud. Every message starts with Configuration cannot be parsed: , followed by:
| Reason | When |
|---|---|
connectionName is required |
connectionName is empty. |
dataFlowScope is required |
dataFlowScope is empty. |
targetConnectionName is required when dryRun is false |
A live run has no target connection. |
projects must not be empty |
No project is listed. |
projects entry is not a valid project id: <value> |
An entry is not a project id (a name or a number, for example). |
invalid regex <pattern> |
A repository pattern does not compile. |
environments.releaseConfigs entry must be <releaseConfigId> or <repositoryId>/<releaseConfigId>: <value> |
An entry has another form. |
environments.fallback must be INVOCATION_THEN_COMPILATION or NONE |
Another value. |
systems.projectSystems.projectId is required |
An entry has no projectId. |
systems.projectSystems needs systemName or systemUuid for <projectId> |
An entry has neither. |
systems.projectSystems has a duplicate projectId: <projectId> |
A project is pinned twice. |
projectSystemNamePattern must contain <projectId> |
The pattern has no <projectId>. |
queryBucketPattern must contain <repository> and <environment> |
The pattern lacks one of them. |
runtimeLineage.mode must be OFF or COMPLEMENT |
Another value. |
runtimeLineage.lookbackDays must be between 1 and 30 |
The value is outside the range. |
runtimeLineage.mode COMPLEMENT is not available in this release |
COMPLEMENT is set. Use OFF or leave the block out. |
quality.firstImportLookbackDays must be between 0 and 30 |
The value is outside the range. |
limits.<name> must be between <min> and <max> |
A limit is outside the range in the limits table. |
cleanupOptions.daysFromLastUpdate must be >= 0 |
A negative number. |
cleanupOptions.limit must be >= 1 |
A limit of 0 or less. |
dataFlowScope must not end with (Dataform) |
The scope would collide with the name of a query bucket. |
A configuration that is not valid JSON fails with Configuration cannot be parsed.
A systemUuid in systems.projectSystems that Blindata does not know stops a live run with systems.projectSystems[<project>] not found.
Read the run report
Every run ends with a report. Read it after a dry run, and whenever something is missing.
| Key | What it tells you |
|---|---|
dryRun, cleanupExecuted |
Whether the run uploaded, and whether cleanup ran. |
crawledDataform |
Projects and locations read, repositories by kind, environments, the repositories skipped with the reason, and the scope gaps (a project or location that could not be read, with the Google reason). |
systems |
Systems created, found and stamped with a project id. |
physicalEntities, physicalFields, and their ...AdditionalProperties |
Rows found, created, updated and discarded. |
dataFlows, queryBuckets, queryStatements |
Flows uploaded, buckets used, statements posted by verdict, statements not posted by gap, statements deleted. |
systemRoutines |
Scripts uploaded, analyzed, unchanged, pending, failed and removed, and BigQuery routines cataloged, already present and temporary. |
qualityChecks, qualityResults |
Suites, checks created, updated, disabled, unchanged and in conflict, and results uploaded, discarded and skipped by state. |
environments |
For each repository environment: where its compilation came from, actions by kind, edges by evidence, statements by verdict and gaps. |
edgesByEvidence, gapsByReason |
Totals. gapsByReason is the first place to look: see Why is my lineage missing?
. |
targetCollisions |
Tables built by two repositories: see Dataform to Blindata catalog . |
warnings |
Everything that degraded the run, in the same words as the log. |
A run that degraded (an unreadable project, a table without metadata, a quality permission that is missing) finishes with a warning and still publishes the rest. Only an invalid configuration, a System you pinned that does not exist, and a refused Blindata upload end it in error.
Common mistakes
- Unknown fields are ignored. The job does not fail on a misspelled key, so a setting you typed wrongly is simply not applied. Check the run report after the first run.
dryRundefaults totrue. A job withoutputOptionsthat sets onlytargetConnectionNameis still a dry run. Set"dryRun": false.- Repository patterns are whole-name and case-sensitive.
salesdoes not matchsales-orders. Usesales-.*. - Development environments add tables. By default every enabled release configuration is read, so a
devconfiguration with a table prefix adds its tables and lineage to the catalog. List the ones you want inenvironments.releaseConfigs. - Source projects are cataloged without being listed.
projectsbounds which repositories are read, not which projects get a System. If a source project’s datasets are not readable, its tables are reported asMETADATA_UNAVAILABLE. - Changing
queryBucketPatterncreates new buckets. The job reconciles only the buckets it uses in the run: the old bucket keeps its statements and flows until you delete it. - Steward edits to quality checks do not last. The checks are managed by the job. See Assertions as quality checks .
dataFlowScopeis shared by cleanup. Use a value that no other job uses, or cleanup of this job can remove the flows of the other.