Skip to content

Add bundle bitmap for per-field telemetry - #6104

Draft
denik wants to merge 33 commits into
mainfrom
denik/bundle-bitmap
Draft

denik wants to merge 33 commits into
mainfrom
denik/bundle-bitmap

Conversation

@denik

@denik denik commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor

Why

Today each tracked DABs feature needs custom code (a key constant plus a SetBoolValue call), so only hand-picked features are tracked. The bundle bitmap encodes the presence of every bundle config field as one bit, derived by reflecting over config.Root, so all current and future fields are covered for free (http://go/dabs-telemetry).

Changes

  • Hidden databricks bundle bitmap group: schema, bitmap -o compressed|text|json (compressed is DEFLATE + base64, the default), decode (stdin, same -o, defaults to text) and update-schema [--validate]. The schema lives in bundle/bitmap/schema.txt, is embedded into the binary, and is append-only so bit positions stay stable; task generate appends new fields. Bool fields also record their value.
  • Bits describe the config as the user wrote it: a snapshot taken at the start of Initialize, plus resources added by Python, before defaults are filled in.
  • Boolean deploy telemetry lives in a typed bundle.Telemetry struct (metric tags): one assignment per call site instead of a key constant plus SetBoolValue. Flags measured per artifact or per resource are a BoolSet (SetBool(v)) and report each value taken once: *_lifecycle_started is true if any resource is started and false if any is stopped (it used to take a random resource's value), and artifact_*_is_set no longer repeats a value once per artifact. Otherwise bool_values keeps the same entries, now in field order. The bitmap is not sent yet.
  • databricks.bundles._bitmap in databricks-bundles: a self-contained decoder with the schema embedded.

Tests

Go and Python unit tests for presence, bool variants and the wire format. acceptance/bundle/bitmap/presence pins the set bits of a fixture and checks that the CLI (text, JSON) and Python decoders reproduce it; bitmap/full records the whole schema with each field's bit, split per resource type; python/telemetry covers a Python-defined resource; invariant/validate_bitmap (local-only) runs validate on every invariant config and checks that both decoders reproduce the bits from the encoded bitmap.

This pull request and its description were written by Isaac.

@denik
denik force-pushed the denik/bundle-bitmap branch from 221d417 to 39faace Compare July 30, 2026 10:11
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jul 30, 2026 •

Copy link
Copy Markdown
Collaborator

✅ Integration test report

Commit: 689a00d

Run: 42195369592

Env ✅​pass 🙈​skip Time
✅​ aws linux-2core-8gb 271 23 5:08
✅​ aws-windows-latest-4core-16gb 273 21 3:19
✅​ azure linux-2core-8gb 270 23 5:07
✅​ azure-windows-latest-4core-16gb 272 21 3:13
✅​ gcp linux-2core-8gb 271 23 5:05
✅​ gcp-windows-latest-4core-16gb 273 21 3:06
Top 6 slowest tests (at least 2 minutes):
duration env testname
3:59 azure linux-2core-8gb TestAccept
3:55 aws linux-2core-8gb TestAccept
3:54 gcp linux-2core-8gb TestAccept
3:14 aws-windows-latest-4core-16gb TestAccept
3:08 azure-windows-latest-4core-16gb TestAccept
3:00 gcp-windows-latest-4core-16gb TestAccept

@denik
denik force-pushed the denik/bundle-bitmap branch 2 times, most recently from eb6b1f0 to 29c5b44 Compare August 3, 2026 10:01
@denik
denik force-pushed the denik/bundle-bitmap branch 2 times, most recently from 45b8bfe to 9ad0bbb Compare August 17, 2026 11:52
@github-actions

Copy link
Copy Markdown
Contributor

This PR has not received an update in a while. If you want to keep this PR open, please leave a comment below or push a new commit and auto-close will be canceled.

@github-actions github-actions Bot added the Stale label Oct 17, 2026
@denik
denik force-pushed the denik/bundle-bitmap branch from 9ad0bbb to 96a6df5 Compare November 3, 2026 16:34
@github-actions github-actions Bot added the DABs DABs related issues label Nov 3, 2026
@denik
denik force-pushed the denik/bundle-bitmap branch from 96a6df5 to f972c44 Compare November 3, 2026 16:42
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Commit: 689a00d81 | Workflow run

Regression test report

Selected 8 changed tests (limit=20, 0 not selected)

75 tests: regression=74 unreleased=0 coverage=1 failing=0
test branch main (c461a8f) latest (v1.24.0)
TestAccept/bundle/bitmap/full ✅ ❌ ❌
TestAccept/bundle/bitmap/presence/DMS= ✅ ❌ ❌
TestAccept/bundle/bitmap/presence/DMS=true ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=alert.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=app.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=catalog.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=catalog_optional_fields.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=cluster.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=cluster_libraries.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=cluster_policy.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=dashboard.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=data_quality_monitor.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=database_catalog.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=database_instance.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=experiment.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=external_location.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=feature.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=genie_space.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=instance_pool.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_apply_policy_default_values_for_each_task.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_apply_policy_default_values_job_cluster.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_apply_policy_default_values_task_cluster.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_cross_resource_ref.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_escaped_refs.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_permission_ref.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_pydabs_1000_tasks.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_pydabs_10_tasks.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_run.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_run_job_ref.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_table_update_trigger.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_with_depends_on.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=job_with_task.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=model.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=model_service.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=model_serving_endpoint.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=model_serving_endpoint_telemetry.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=model_with_permissions.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=pipeline.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=pipeline_allow_duplicate_names.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=pipeline_apply_policy_default_values.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=pipeline_config_dots.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=postgres_branch.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=postgres_catalog.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=postgres_data_api.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=postgres_database.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=postgres_endpoint.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=postgres_project.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=postgres_role.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=postgres_synced_table.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=registered_model.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=schema.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=schema_empty_grants.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=schema_grant_ref.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=schema_tf_compat.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=schema_uppercase_name.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=secret.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=secret_scope.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=secret_scope_default_backend_type.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=sql_warehouse.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=synced_database_table.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=uc_trailing_slash.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=vector_search_endpoint.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=vector_search_index.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=volume.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=volume_external.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=volume_path_job_ref.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/invariant/validate_bitmap/INPUT_CONFIG=volume_uppercase_name.yml.tmpl ✅ ❌ ❌
TestAccept/bundle/python/telemetry/DMS=/PYDAB_VERSION=current ✅ ❌ ❌
TestAccept/bundle/telemetry/deploy-app-lifecycle-started/DMS= ✅ ❌ ❌
TestAccept/bundle/telemetry/deploy/DMS= ✅ ❌ ❌
TestAccept/bundle/templates/default-python/classic/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/templates/default-python/classic/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/selftest/selection ✅ ✅ ✅
TestAccept/bundle/bitmap/full: branch ✅ | main (c461a8f) ❌ | latest (v1.24.0) ❌

main (c461a8f):

acceptance_test.go:1316: Missing output file: output/features.txt
    acceptance_test.go:1316: Missing output file: output/apps.txt
    acceptance_test.go:1316: Missing output file: output/cluster_policies.txt
    acceptance_test.go:1316: Missing output file: output/postgres_catalogs.txt
    acceptance_test.go:1316: Missing output file: output/postgres_synced_tables.txt
    acceptance_test.go:1316: Missing output file: output/sql_warehouses.txt
    acceptance_test.go:1316: Missing output file: output/job_runs.txt
    acceptance_test.go:1316: Missing output file: output/mcp_services.txt
    acceptance_test.go:1316: Missing output file: output/models.txt
    acceptance_test.go:1316: Missing output file: output/postgres_projects.txt
    acceptance_test.go:1316: Missing output file: output/schemas.txt
    acceptance_test.go:1316: Missing output file: output/synced_database_tables.txt
    acceptance_test.go:1316: Missing output file: output/alerts.txt
    acceptance_test.go:1316: Missing output file: output/database_catalogs.txt
    acceptance_test.go:1316: Missing output file: output/database_instances.txt
    acceptance_test.go:1316: Missing output file: output/instance_pools.txt
    acceptance_test.go:1316: Missing output file: output/quality_monitors.txt
    acceptance_test.go:1345: Diff:
        --- bundle/bitmap/full/output/root.txt
        +++ /tmp/TestAcceptbundlebitmapfull3229794256/001/output/root.txt
        @@ -1,371 +1,42 @@
        -variables	0
        -variables.*	1
        -variables.*.type	2
        -variables.*.default	3
        -variables.*.description	4
        -variables.*.sensitive	5
        -variables.*.sensitive=true	6
        -variables.*.sensitive=false	7
        -variables.*.value	8
        -variables.*.lookup	9
        -variables.*.lookup.alert	10
        -variables.*.lookup.cluster_policy	11
        -variables.*.lookup.cluster	12
        -variables.*.lookup.dashboard	13
        -variables.*.lookup.instance_pool	14
        -variables.*.lookup.job	15
        -variables.*.lookup.metastore	16
        -variables.*.lookup.notification_destination	17
        -variables.*.lookup.pipeline	18
        -variables.*.lookup.query	19
        -variables.*.lookup.service_principal	20
        -variables.*.lookup.warehouse	21
        -bundle	22
        -bundle.name	23
        -bundle.target	24
        -bundle.environment	25
        -bundle.terraform	26
        -bundle.terraform.exec_path	27
        -bundle.force	28
        -bundle.force=true	29
        -bundle.force=false	30
        -bundle.git	31
        -bundle.git.branch	32
        -bundle.git.origin_url	33
        -bundle.git.commit	34
        -bundle.git.bundle_root_path	35
        -bundle.git.actual_branch	36
        -bundle.mode	37
        -bundle.compute_id	38
        -bundle.cluster_id	39
        -bundle.engine	40
        -bundle.deployment	41
        -bundle.deployment.fail_on_active_runs	42
        -bundle.deployment.fail_on_active_runs=true	43
        -bundle.deployment.fail_on_active_runs=false	44
        -bundle.deployment.lock	45
        -bundle.deployment.lock.enabled	46
        -bundle.deployment.lock.enabled=true	47
        -bundle.deployment.lock.enabled=false	48
        -bundle.deployment.lock.force	49
        -bundle.deployment.lock.force=true	50
        -bundle.deployment.lock.force=false	51
        -bundle.deployment.deployment_id	52
        -bundle.deployment.latest_version_id	53
        -bundle.databricks_cli_version	54
        -bundle.uuid	55
        -include	56
        -include[*]	57
        -workspace	58
        -workspace.host	59
        -workspace.profile	60
        -workspace.auth_type	61
        -workspace.metadata_service_url	62
        -workspace.client_id	63
        -workspace.google_service_account	64
        -workspace.azure_workspace_resource_id	65
        -workspace.azure_use_msi	66
        -workspace.azure_use_msi=true	67
        -workspace.azure_use_msi=false	68
        -workspace.azure_client_id	69
        -workspace.azure_tenant_id	70
        -workspace.azure_environment	71
        -workspace.azure_login_app_id	72
        -workspace.experimental_is_unified_host	73
        -workspace.experimental_is_unified_host=true	74
        -workspace.experimental_is_unified_host=false	75
        -workspace.account_id	76
        -workspace.workspace_id	77
        -workspace.current_user	78
        -workspace.current_user.short_name	79
        -workspace.current_user.domain_friendly_name	80
        -workspace.current_user.active	81
        -workspace.current_user.active=true	82
        -workspace.current_user.active=false	83
        -workspace.current_user.displayName	84
        -workspace.current_user.emails	85
        -workspace.current_user.emails[*]	86
        -workspace.current_user.emails[*].display	87
        -workspace.current_user.emails[*].primary	88
        -workspace.current_user.emails[*].primary=true	89
        -workspace.current_user.emails[*].primary=false	90
        -workspace.current_user.emails[*].$ref	91
        -workspace.current_user.emails[*].type	92
        -workspace.current_user.emails[*].value	93
        -workspace.current_user.entitlements	94
        -workspace.current_user.entitlements[*]	95
        -workspace.current_user.entitlements[*].display	96
        -workspace.current_user.entitlements[*].primary	97
        -workspace.current_user.entitlements[*].primary=true	98
        -workspace.current_user.entitlements[*].primary=false	99
        -workspace.current_user.entitlements[*].$ref	100
        -workspace.current_user.entitlements[*].type	101
        -workspace.current_user.entitlements[*].value	102
        -workspace.current_user.externalId	103
        -workspace.current_user.groups	104
        -workspace.current_user.groups[*]	105
        -workspace.current_user.groups[*].display	106
        -workspace.current_user.groups[*].primary	107
        -workspace.current_user.groups[*].primary=true	108
        -workspace.current_user.groups[*].primary=false	109
        -workspace.current_user.groups[*].$ref	110
        -workspace.current_user.groups[*].type	111
        -workspace.current_user.groups[*].value	112
        -workspace.current_user.id	113
        -workspace.current_user.name	114
        -workspace.current_user.name.familyName	115
        -workspace.current_user.name.givenName	116
        -workspace.current_user.roles	117
        -workspace.current_user.roles[*]	118
        -workspace.current_user.roles[*].display	119
        -workspace.current_user.roles[*].primary	120
        -workspace.current_user.roles[*].primary=true	121
        -workspace.current_user.roles[*].primary=false	122
        -workspace.current_user.roles[*].$ref	123
        -workspace.current_user.roles[*].type	124
        -workspace.current_user.roles[*].value	125
        -workspace.current_user.schemas	126
        -workspace.current_user.schemas[*]	127
        -workspace.current_user.userName	128
        -workspace.root_path	129
        -workspace.file_path	130
        -workspace.resource_path	131
        -workspace.artifact_path	132
        -workspace.state_path	133
        -workspace.sync_mode	134
        -artifacts	135
        -artifacts.*	136
        -artifacts.*.type	137
        -artifacts.*.path	138
        -artifacts.*.files	139
        -artifacts.*.files[*]	140
        -artifacts.*.files[*].source	141
        -artifacts.*.files[*].patched	142
        -artifacts.*.files[*].remote_path	143
        -artifacts.*.build	144
        -artifacts.*.executable	145
        -artifacts.*.dynamic_version	146
        -artifacts.*.dynamic_version=true	147
        -artifacts.*.dynamic_version=false	148
        -artifacts.*.include	149
        -artifacts.*.include[*]	150
        -artifacts.*.git	151
        -artifacts.*.git.branch	152
        -artifacts.*.git.commit	153
        -resources	154
        -sync	4968
        -sync.paths	4969
        -sync.paths[*]	4970
        -sync.include	4971
        -sync.include[*]	4972
        -sync.exclude	4973
        -sync.exclude[*]	4974
        -run_as	4975
        -run_as.group_name	4976
        -run_as.service_principal_name	4977
        -run_as.user_name	4978
        -presets	4979
        -presets.name_prefix	4980
        -presets.pipelines_development	4981
        -presets.pipelines_development=true	4982
        -presets.pipelines_development=false	4983
        -presets.trigger_pause_status	4984
        -presets.jobs_max_concurrent_runs	4985
        -presets.source_linked_deployment	4986
        -presets.source_linked_deployment=true	4987
        -presets.source_linked_deployment=false	4988
        -presets.artifacts_dynamic_version	4989
        -presets.artifacts_dynamic_version=true	4990
        -presets.artifacts_dynamic_version=false	4991
... (261 more lines truncated, raise DATABRICKS_CLI_TEST_MAX_LOG to see more)

latest (v1.24.0):

acceptance_test.go:1316: Missing output file: output/clusters.txt
    acceptance_test.go:1316: Missing output file: output/model_provider_services.txt
    acceptance_test.go:1316: Missing output file: output/sql_warehouses.txt
    acceptance_test.go:1316: Missing output file: output/vector_search_indexes.txt
    acceptance_test.go:1316: Missing output file: output/alerts.txt
    acceptance_test.go:1316: Missing output file: output/catalogs.txt
    acceptance_test.go:1316: Missing output file: output/database_instances.txt
    acceptance_test.go:1316: Missing output file: output/external_locations.txt
    acceptance_test.go:1316: Missing output file: output/quality_monitors.txt
    acceptance_test.go:1316: Missing output file: output/secret_scopes.txt
    acceptance_test.go:1316: Missing output file: output/apps.txt
    acceptance_test.go:1316: Missing output file: output/experiments.txt
    acceptance_test.go:1316: Missing output file: output/genie_spaces.txt
    acceptance_test.go:1316: Missing output file: output/jobs.txt
    acceptance_test.go:1316: Missing output file: output/pipelines.txt
    acceptance_test.go:1316: Missing output file: output/synced_database_tables.txt
    acceptance_test.go:1316: Missing output file: output/vector_search_endpoints.txt
    acceptance_test.go:1316: Missing output file: output/cluster_policies.txt
    acceptance_test.go:1316: Missing output file: output/job_runs.txt
    acceptance_test.go:1316: Missing output file: output/model_services.txt
    acceptance_test.go:1316: Missing output file: output/postgres_branches.txt
    acceptance_test.go:1316: Missing output file: output/postgres_catalogs.txt
    acceptance_test.go:1316: Missing output file: output/postgres_databases.txt
    acceptance_test.go:1316: Missing output file: output/postgres_snapshot_schedules.txt
    acceptance_test.go:1316: Missing output file: output/schemas.txt
    acceptance_test.go:1316: Missing output file: output/models.txt
    acceptance_test.go:1316: Missing output file: output/postgres_roles.txt
    acceptance_test.go:1316: Missing output file: output/postgres_synced_tables.txt
    acceptance_test.go:1316: Missing output file: output/secrets.txt
    acceptance_test.go:1316: Missing output file: output/volumes.txt
    acceptance_test.go:1316: Missing output file: output/database_catalogs.txt
    acceptance_test.go:1316: Missing output file: output/internal_immutable_snapshots.txt
    acceptance_test.go:1316: Missing output file: output/materialization_sets.txt
    acceptance_test.go:1316: Missing output file: output/postgres_data_apis.txt
    acceptance_test.go:1316: Missing output file: output/postgres_endpoints.txt
    acceptance_test.go:1316: Missing output file: output/postgres_projects.txt
    acceptance_test.go:1345: Diff:
        --- bundle/bitmap/full/output/root.txt
        +++ /tmp/TestAcceptbundlebitmapfull3446434216/001/output/root.txt
        @@ -1,371 +1,42 @@
        -variables	0
        -variables.*	1
        -variables.*.type	2
        -variables.*.default	3
        -variables.*.description	4
        -variables.*.sensitive	5
        -variables.*.sensitive=true	6
        -variables.*.sensitive=false	7
        -variables.*.value	8
        -variables.*.lookup	9
        -variables.*.lookup.alert	10
        -variables.*.lookup.cluster_policy	11
        -variables.*.lookup.cluster	12
        -variables.*.lookup.dashboard	13
        -variables.*.lookup.instance_pool	14
        -variables.*.lookup.job	15
        -variables.*.lookup.metastore	16
        -variables.*.lookup.notification_destination	17
        -variables.*.lookup.pipeline	18
        -variables.*.lookup.query	19
        -variables.*.lookup.service_principal	20
        -variables.*.lookup.warehouse	21
        -bundle	22
        -bundle.name	23
        -bundle.target	24
        -bundle.environment	25
        -bundle.terraform	26
        -bundle.terraform.exec_path	27
        -bundle.force	28
        -bundle.force=true	29
        -bundle.force=false	30
        -bundle.git	31
        -bundle.git.branch	32
        -bundle.git.origin_url	33
        -bundle.git.commit	34
        -bundle.git.bundle_root_path	35
        -bundle.git.actual_branch	36
        -bundle.mode	37
        -bundle.compute_id	38
        -bundle.cluster_id	39
        -bundle.engine	40
        -bundle.deployment	41
        -bundle.deployment.fail_on_active_runs	42
        -bundle.deployment.fail_on_active_runs=true	43
        -bundle.deployment.fail_on_active_runs=false	44
        -bundle.deployment.lock	45
        -bundle.deployment.lock.enabled	46
        -bundle.deployment.lock.enabled=true	47
        -bundle.deployment.lock.enabled=false	48
        -bundle.deployment.lock.force	49
        -bundle.deployment.lock.force=true	50
        -bundle.deployment.lock.force=false	51
        -bundle.deployment.deployment_id	52
        -bundle.deployment.latest_version_id	53
        -bundle.databricks_cli_version	54
        -bundle.uuid	55
        -include	56
        -include[*]	57
        -workspace	58
        -workspace.host	59
        -workspace.profile	60
        -workspace.auth_type	61
        -workspace.metadata_service_url	62
        -workspace.client_id	63
        -workspace.google_service_account	64
        -workspace.azure_workspace_resource_id	65
        -workspace.azure_use_msi	66
        -workspace.azure_use_msi=true	67
        -workspace.azure_use_msi=false	68
        -workspace.azure_client_id	69
        -workspace.azure_tenant_id	70
        -workspace.azure_environment	71
        -workspace.azure_login_app_id	72
        -workspace.experimental_is_unified_host	73
        -workspace.experimental_is_unified_host=true	74
        -workspace.experimental_is_unified_host=false	75
        -workspace.account_id	76
        -workspace.workspace_id	77
        -workspace.current_user	78
        -workspace.current_user.short_name	79
        -workspace.current_user.domain_friendly_name	80
        -workspace.current_user.active	81
        -workspace.current_user.active=true	82
        -workspace.current_user.active=false	83
        -workspace.current_user.displayName	84
        -workspace.current_user.emails	85
        -workspace.current_user.emails[*]	86
        -workspace.current_user.emails[*].display	87
        -workspace.current_user.emails[*].primary	88
        -workspace.current_user.emails[*].primary=true	89
        -workspace.current_user.emails[*].primary=false	90
        -workspace.current_user.emails[*].$ref	91
        -workspace.current_user.emails[*].type	92
        -workspace.current_user.emails[*].value	93
        -workspace.current_user.entitlements	94
        -workspace.current_user.entitlements[*]	95
        -workspace.current_user.entitlements[*].display	96
        -workspace.current_user.entitlements[*].primary	97
        -workspace.current_user.entitlements[*].primary=true	98
        -workspace.current_user.entitlements[*].primary=false	99
        -workspace.current_user.entitlements[*].$ref	100
        -workspace.current_user.entitlements[*].type	101
        -workspace.current_user.entitlements[*].value	102
        -workspace.current_user.externalId	103
        -workspace.current_user.groups	104
        -workspace.current_user.groups[*]	105
        -workspace.current_user.groups[*].display	106
        -workspace.current_user.groups[*].primary	107
        -workspace.current_user.groups[*].primary=true	108
        -workspace.current_user.groups[*].primary=false	109
        -workspace.current_user.groups[*].$ref	110
        -workspace.current_user.groups[*].type	111
        -workspace.current_user.groups[*].value	112
        -workspace.current_user.id	113
        -workspace.current_user.name	114
        -workspace.current_user.name.familyName	115
        -workspace.current_user.name.givenName	116
        -workspace.current_user.roles	117
        -workspace.current_user.roles[*]	118
        -workspace.current_user.roles[*].display	119
        -workspace.current_user.roles[*].primary	120
        -workspace.current_user.roles[*].primary=true	121
        -workspace.current_user.roles[*].primary=false	122
        -workspace.current_user.roles[*].$ref	123
        -workspace.current_user.roles[*].type	124
        -workspace.current_user.roles[*].value	125
        -workspace.current_user.schemas	126
        -workspace.current_user.schemas[*]	127
        -workspace.current_user.userName	128
        -workspace.root_path	129
        -workspace.file_path	130
        -workspace.resource_path	131
        -workspace.artifact_path	132
        -workspace.state_path	133
        -workspace.sync_mode	134
        -artifacts	135
        -artifacts.*	136
        -artifacts.*.type	137
        -artifacts.*.path	138
        -artifacts.*.files	139
        -artifacts.*.files[*]	140
        -artifacts.*.files[*].source	141
        -artifacts.*.files[*].patched	142
        -artifacts.*.files[*].remote_path	143
        -artifacts.*.build	144
        -artifacts.*.executable	145
        -artifacts.*.dynamic_version	146
        -artifacts.*.dynamic_version=true	147
        -artifacts.*.dynamic_version=false	148
        -artifacts.*.include	149
        -artifacts.*.include[*]	150
        -artifacts.*.git	151
        -artifacts.*.git.branch	152
        -artifacts.*.git.commit	153
        -resources	154
        -sync	4968
        -sync.paths	4969
        -sync.paths[*]	4970
        -sync.include	4971
        -sync.include[*]	4972
... (261 more lines truncated, raise DATABRICKS_CLI_TEST_MAX_LOG to see more)
TestAccept/bundle/bitmap/presence/DMS=: branch ✅ | main (c461a8f) ❌ | latest (v1.24.0) ❌

main (c461a8f):

acceptance_test.go:1345: Diff:
        --- bundle/bitmap/presence/output.txt
        +++ /tmp/TestAcceptbundlebitmappresenceDMS=401796867/002/output.txt
        @@ -10,46 +10,36 @@
         >>> [CLI] bundle bitmap decode -o json
         
         >>> [CLI] bundle bitmap decode -o compressed
        +Error: invalid argument "compressed" for "-o, --output" flag: accepted arguments are json and text
         
        ->>> uv run --isolated --no-project --reinstall-package databricks-bundles --with [DATABRICKS_BUNDLES_WHEEL] -q python -m databricks.bundles._bitmap
        -
        ->>> [CLI] bundle bitmap update-schema --validate
        -
        -=== decode rejects input that is not an encoded bitmap
        -
        ->>> musterr [CLI] bundle bitmap decode
        -Error: base64: illegal base64 data at input byte 3
        -
        -=== -o accepts compressed, text and json
        -
        ->>> musterr [CLI] bundle bitmap bitmap -o yaml
        -Error: invalid argument "yaml" for "-o, --output" flag: accepted values are compressed, text and json
        -
         Usage:
        -  databricks bundle bitmap bitmap [flags]
        +  databricks bundle [command]
         
        +Available Commands:
        +  deploy             Deploy bundle
        +  deployment         Deployment related commands
        +  destroy            Destroy deployed bundle resources
        +  generate           Generate bundle configuration
        +  init               Initialize using a bundle template
        +  open               Open a resource in the browser
        +  plan               Show deployment plan
        +  run                Run a job, pipeline update or app
        +  schema             Generate JSON Schema for bundle configuration
        +  summary            Summarize resources deployed by this bundle
        +  sync               Synchronize bundle tree to the workspace
        +  validate           Validate configuration
        +
         Flags:
        -  -h, --help            help for bitmap
        -  -o, --output format   output format:
        -                          compressed: base64 of the DEFLATE-compressed wire format
        -                          text:       a "size=N context=C" header, then one "<value> <field>" line per
        -                                      set field: "T" or "F" for a boolean field holding that value, "1"
        -                                      for any other field; unset fields are omitted
        -                          json:       size, context, and trees of the fields present ("presence") and of
        -                                      the boolean fields seen holding "true" and "false" (default compressed)
        +  -h, --help          help for bundle
        +      --var strings   set values for variables defined in bundle config. Example: --var="foo=bar"
         
         Global Flags:
               --debug            enable debug logging
        +  -o, --output type      output type: text or json (default text)
           -p, --profile string   ~/.databrickscfg profile
           -t, --target string    bundle target to use (if applicable)
        -      --var strings      set values for variables defined in bundle config. Example: --var="foo=bar"
         
        +Use "databricks bundle [command] --help" for more information about a command.
         
        -=== An invalid bundle fails instead of printing a bitmap
         
        ->>> musterr [CLI] bundle bitmap bitmap
        -Error: Artifact not properly configured
        -  in databricks.yml:5:10
        -
        -please specify artifact properties
        -
        +Exit code: 1
        
    acceptance_test.go:1345: Diff:
        --- bundle/bitmap/presence/out.bitmap.json
        +++ /tmp/TestAcceptbundlebitmappresenceDMS=401796867/001/out.bitmap.json
        @@ -1,144 +1,42 @@
        -{
        -  "size": [SCHEMA_SIZE],
        -  "context": 0,
        -  "presence": {
        -    "artifacts": {
        -      "*": {
        -        "build": true,
        -        "files": {
        -          "[*]": {
        -            "source": true
        -          }
        -        },
        -        "type": true
        -      }
        -    },
        -    "bundle": {
        -      "environment": true,
        -      "name": true,
        -      "target": true
        -    },
        -    "experimental": true,
        -    "presets": {
        -      "name_prefix": true,
        -      "pipelines_development": true
        -    },
        -    "resources": {
        -      "clusters": {
        -        "*": {
        -          "cluster_name": true,
        -          "lifecycle": {
        -            "started": true
        -          }
        -        }
        -      },
        -      "jobs": {
        -        "*": {
        -          "description": true,
        -          "email_notifications": true,
        -          "max_concurrent_runs": true,
        -          "name": true,
        -          "notification_settings": {
        -            "no_alert_for_skipped_runs": true
        -          },
        -          "parameters": true,
        -          "queue": {
        -            "enabled": true
        -          },
        -          "tags": {
        -            "*": true
        -          },
        -          "tasks": {
        -            "[*]": {
        -              "depends_on": {
        -                "[*]": {
        -                  "task_key": true
        -                }
        -              },
        -              "disable_auto_optimization": true,
        -              "notebook_task": {
        -                "notebook_path": true
        -              },
        -              "task_key": true
        -            }
        -          },
        -          "timeout_seconds": true
        -        }
        -      }
        -    },
        -    "run_as": {
        -      "service_principal_name": true
        -    },
        -    "telemetry": {
        -      "ArtifactBuildCommandIsSet": true,
        -      "ArtifactFilesIsSet": true,
        -      "ConfigHasDoubleDollarBrace": true,
        -      "PresetsNamePrefixIsSet": true,
        -      "RunAsSet": true,
        -      "UseLegacyRunAs": true
        -    },
        -    "variables": {
        -      "*": {
        -        "default": true,
        -        "description": true,
        -        "type": true
        -      }
        -    }
        -  },
        -  "true": {
        -    "resources": {
        -      "clusters": {
        -        "*": {
        -          "lifecycle": {
        -            "started": true
        -          }
        -        }
        -      },
        -      "jobs": {
        -        "*": {
        -          "queue": {
        -            "enabled": true
        -          }
        -        }
        -      }
        -    },
        -    "telemetry": {
        -      "ArtifactBuildCommandIsSet": true,
        -      "ArtifactFilesIsSet": true,
        -      "ConfigHasDoubleDollarBrace": true,
        -      "PresetsNamePrefixIsSet": true,
        -      "RunAsSet": true
        -    }
        -  },
        -  "false": {
        -    "presets": {
        -      "pipelines_development": true
        -    },
        -    "resources": {
        -      "clusters": {
        -        "*": {
        -          "lifecycle": {
        -            "started": true
        -          }
        -        }
        -      },
... (171 more lines truncated, raise DATABRICKS_CLI_TEST_MAX_LOG to see more)

latest (v1.24.0): same output as main (c461a8f)

TestAccept/bundle/bitmap/presence/DMS=true: branch ✅ | main (c461a8f) ❌ | latest (v1.24.0) ❌

main (c461a8f):

acceptance_test.go:1345: Diff:
        --- bundle/bitmap/presence/output.txt
        +++ /tmp/TestAcceptbundlebitmappresenceDMS=true1359661343/002/output.txt
        @@ -10,46 +10,36 @@
         >>> [CLI] bundle bitmap decode -o json
         
         >>> [CLI] bundle bitmap decode -o compressed
        +Error: invalid argument "compressed" for "-o, --output" flag: accepted arguments are json and text
         
        ->>> uv run --isolated --no-project --reinstall-package databricks-bundles --with [DATABRICKS_BUNDLES_WHEEL] -q python -m databricks.bundles._bitmap
        -
        ->>> [CLI] bundle bitmap update-schema --validate
        -
        -=== decode rejects input that is not an encoded bitmap
        -
        ->>> musterr [CLI] bundle bitmap decode
        -Error: base64: illegal base64 data at input byte 3
        -
        -=== -o accepts compressed, text and json
        -
        ->>> musterr [CLI] bundle bitmap bitmap -o yaml
        -Error: invalid argument "yaml" for "-o, --output" flag: accepted values are compressed, text and json
        -
         Usage:
        -  databricks bundle bitmap bitmap [flags]
        +  databricks bundle [command]
         
        +Available Commands:
        +  deploy             Deploy bundle
        +  deployment         Deployment related commands
        +  destroy            Destroy deployed bundle resources
        +  generate           Generate bundle configuration
        +  init               Initialize using a bundle template
        +  open               Open a resource in the browser
        +  plan               Show deployment plan
        +  run                Run a job, pipeline update or app
        +  schema             Generate JSON Schema for bundle configuration
        +  summary            Summarize resources deployed by this bundle
        +  sync               Synchronize bundle tree to the workspace
        +  validate           Validate configuration
        +
         Flags:
        -  -h, --help            help for bitmap
        -  -o, --output format   output format:
        -                          compressed: base64 of the DEFLATE-compressed wire format
        -                          text:       a "size=N context=C" header, then one "<value> <field>" line per
        -                                      set field: "T" or "F" for a boolean field holding that value, "1"
        -                                      for any other field; unset fields are omitted
        -                          json:       size, context, and trees of the fields present ("presence") and of
        -                                      the boolean fields seen holding "true" and "false" (default compressed)
        +  -h, --help          help for bundle
        +      --var strings   set values for variables defined in bundle config. Example: --var="foo=bar"
         
         Global Flags:
               --debug            enable debug logging
        +  -o, --output type      output type: text or json (default text)
           -p, --profile string   ~/.databrickscfg profile
           -t, --target string    bundle target to use (if applicable)
        -      --var strings      set values for variables defined in bundle config. Example: --var="foo=bar"
         
        +Use "databricks bundle [command] --help" for more information about a command.
         
        -=== An invalid bundle fails instead of printing a bitmap
         
        ->>> musterr [CLI] bundle bitmap bitmap
        -Error: Artifact not properly configured
        -  in databricks.yml:5:10
        -
        -please specify artifact properties
        -
        +Exit code: 1
        
    acceptance_test.go:1345: Diff:
        --- bundle/bitmap/presence/out.bitmap.json
        +++ /tmp/TestAcceptbundlebitmappresenceDMS=true1359661343/001/out.bitmap.json
        @@ -1,144 +1,42 @@
        -{
        -  "size": [SCHEMA_SIZE],
        -  "context": 0,
        -  "presence": {
        -    "artifacts": {
        -      "*": {
        -        "build": true,
        -        "files": {
        -          "[*]": {
        -            "source": true
        -          }
        -        },
        -        "type": true
        -      }
        -    },
        -    "bundle": {
        -      "environment": true,
        -      "name": true,
        -      "target": true
        -    },
        -    "experimental": true,
        -    "presets": {
        -      "name_prefix": true,
        -      "pipelines_development": true
        -    },
        -    "resources": {
        -      "clusters": {
        -        "*": {
        -          "cluster_name": true,
        -          "lifecycle": {
        -            "started": true
        -          }
        -        }
        -      },
        -      "jobs": {
        -        "*": {
        -          "description": true,
        -          "email_notifications": true,
        -          "max_concurrent_runs": true,
        -          "name": true,
        -          "notification_settings": {
        -            "no_alert_for_skipped_runs": true
        -          },
        -          "parameters": true,
        -          "queue": {
        -            "enabled": true
        -          },
        -          "tags": {
        -            "*": true
        -          },
        -          "tasks": {
        -            "[*]": {
        -              "depends_on": {
        -                "[*]": {
        -                  "task_key": true
        -                }
        -              },
        -              "disable_auto_optimization": true,
        -              "notebook_task": {
        -                "notebook_path": true
        -              },
        -              "task_key": true
        -            }
        -          },
        -          "timeout_seconds": true
        -        }
        -      }
        -    },
        -    "run_as": {
        -      "service_principal_name": true
        -    },
        -    "telemetry": {
        -      "ArtifactBuildCommandIsSet": true,
        -      "ArtifactFilesIsSet": true,
        -      "ConfigHasDoubleDollarBrace": true,
        -      "PresetsNamePrefixIsSet": true,
        -      "RunAsSet": true,
        -      "UseLegacyRunAs": true
        -    },
        -    "variables": {
        -      "*": {
        -        "default": true,
        -        "description": true,
        -        "type": true
        -      }
        -    }
        -  },
        -  "true": {
        -    "resources": {
        -      "clusters": {
        -        "*": {
        -          "lifecycle": {
        -            "started": true
        -          }
        -        }
        -      },
        -      "jobs": {
        -        "*": {
        -          "queue": {
        -            "enabled": true
        -          }
        -        }
        -      }
        -    },
        -    "telemetry": {
        -      "ArtifactBuildCommandIsSet": true,
        -      "ArtifactFilesIsSet": true,
        -      "ConfigHasDoubleDollarBrace": true,
        -      "PresetsNamePrefixIsSet": true,
        -      "RunAsSet": true
        -    }
        -  },
        -  "false": {
        -    "presets": {
        -      "pipelines_development": true
        -    },
        -    "resources": {
        -      "clusters": {
        -        "*": {
        -          "lifecycle": {
        -            "started": true
        -          }
        -        }
        -      },
... (171 more lines truncated, raise DATABRICKS_CLI_TEST_MAX_LOG to see more)

latest (v1.24.0): same output as main (c461a8f)

71 more failure details omitted, see the full report in the run.

@denik
denik force-pushed the denik/bundle-bitmap branch from f972c44 to 1cc9186 Compare November 4, 2026 10:08
@github-actions github-actions Bot added the PyDABs label Nov 4, 2026
@denik
denik force-pushed the denik/bundle-bitmap branch 2 times, most recently from ae3e5d4 to f9387c0 Compare November 4, 2026 13:57
denik added 14 commits November 5, 2026 14:43
Co-authored-by: Isaac
Encode presence of every bundle config field as one bit. The schema is
derived by reflecting over config.Root, recorded in bundle/bitmap/schema.txt,
and embedded into the binary. Append-only so bit positions stay stable.

Adds hidden `databricks bundle bitmap` group: schema, update-schema
[--validate], bitmap-text, bitmap. Wires generate-bitmap-schema into the
Taskfile and runs the encoder over all no_drift invariant configs.

Co-authored-by: Isaac
Kept in PR history for context; not landed.

Co-authored-by: Isaac
- Every bool/*bool field now gets a "#true" value bit in addition to its
  presence bit, so a *bool encodes unset/false/true as 00/10/11.
- decode_bitmap.py decodes the base64 bitmap against the schema; the dedicated
  acceptance test asserts it round-trips to bitmap-text.
- Record the encoded bitmap and set-bit list for the default-python template.

Co-authored-by: Isaac
Replace the string-keyed BoolValues map with a typed bundle.Telemetry struct
whose fields feed both the deploy telemetry wire (via BoolValues()) and the
bundle bitmap (namespaced under telemetry.*).

Value-bearing flags whose false is meaningful are stored as True/False pairs so
the bitmap can represent both outcomes; BoolValues() collapses each pair back to
its single wire key. libs/cache gets a concrete Metrics struct (embedded into
Telemetry) instead of the old interface.

The wire is unchanged except that redundant false entries of one-hot groups
(state_path_*, dms_undeclared_*) are no longer emitted; their true member is
preserved.

Co-authored-by: Isaac
decode_bitmap.py was committed without the executable bit, so the round-trip
step failed with "permission denied" (exit code differed across OSes, breaking
the golden). Mark it executable.

bitmap-text and bitmap are separate invocations sharing a cache dir, so the
second recorded a cache hit instead of a miss and the round-trip check
diverged. Give each its own cache dir so both observe a cold miss.

Co-authored-by: Isaac
On a CRLF checkout (Windows) the embedded schema.txt lines kept a trailing \r,
so they never matched the clean paths from WalkType. Merge's dedup then failed
and the schema doubled, breaking bundle bitmap schema/bitmap-text on Windows.
splitLines now normalizes CRLF.

Co-authored-by: Isaac
The schema had telemetry fields appended at the tail (from append-only merges
across a rebase). Since the PR has not landed, bit positions need not be
stable yet, so regenerate from scratch to put telemetry fields in natural walk
order.

generate-bitmap-schema now also regenerates the bitmap acceptance goldens
(out.schema.txt, out.bitmap-text.txt, encoded bitmap), which embed the schema
and depend on bit positions; otherwise they go stale when the schema changes.

Co-authored-by: Isaac
Existing telemetry (bundle/metrics AddBoolValue/SetBoolValue and the wire) is
unchanged. Add a Telemetry struct on Bundle with a field per bool flag; each
metrics call site additionally sets the matching field so the same signal
reaches the bitmap. Value-bearing flags use True/False pairs so the
presence-only bitmap can distinguish measured-false from not-measured. Fields
have no json tags, so they are invisible to the config schema and walked into
the bitmap under their Go field names (telemetry.*).

Verified the telemetry and resource_deps goldens are byte-identical to main:
the change is strictly additive to the existing wire.

Co-authored-by: Isaac
The four dms_undeclared_* flags are independent booleans recorded with
their real value on every deploy, so a measured false is meaningful (it
is the common "no undeclared writers" case). As single presence bits a
false collapsed to 0, indistinguishable from "not measured", losing the
signal. Store each as a True/False pair like the other value-bearing
flags. The telemetry wire (BoolValues) is unchanged.

Co-authored-by: Isaac
The dms_undeclared_* flags are always co-emitted with the one-hot
DMSCompat verdict, so a 0 bit is unambiguously "measured false" rather
than "not measured" — a True/False pair adds no information. A pair is
only warranted for a lone boolean with no co-located signal that the
measurement ran (e.g. run_as_set). Adds a comment recording why.

Co-authored-by: Isaac
The telemetry struct's fields have no json tags, so structwalk.Walk does
not honor omitempty and visits every field regardless of value. Bits()
ignored the visited value and set the bit on mere presence, so every
telemetry bit was 1 on every deploy (the acceptance golden showed all
mutually-exclusive one-hot members set at once). Gate the telemetry walk
on the visited bool value so a field maps to a bit only when true.

Also drop blank lines in splitLines so a stray one can never shift bit
indices in the append-only schema, and make the test stand-in tagless to
match the real struct (the tagged stand-in masked the bug).

Co-authored-by: Isaac
Rebase onto main picked up new config fields (resources.secrets.*) and
removed the acceptance Local option, which now fails as an undecoded key.

Co-authored-by: Isaac
denik and others added 18 commits November 5, 2026 14:43
Main added resources.pipelines.*.cascade_on_destroy, which shifts the
schema and the encoded bitmaps.

Co-authored-by: Isaac
Main moved the select/source-linked metrics into mark_select_used.go and
apply_sync_mode.go, dropped the dry-run migration metrics, and added
plan-error, recreate-planned, via-default, deployment-history,
immutable-snapshot, and ai_runtime_task metrics. Mirror them into
Telemetry, regenerate the (still unreleased) schema from scratch, and drop
the engine matrix from the bitmap test now that direct is the only engine.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
… tests

- Compute bits from bundle.UserConfig, a snapshot of the config taken at the
  start of Initialize (plus resources added by Python before their defaults are
  filled in), so the bitmap records what users configure rather than CLI
  defaults (workspace paths, current_user, job format/queue, ...).
- Walk the dyn.Value instead of the typed struct: interface-typed fields
  (variables.*.default) and empty containers were never marked, and zero
  non-omitempty fields always were.
- Replace True/False field pairs and SetPaired with a BoolPair type; per-artifact
  flags call Set per artifact, so mixed artifacts set both bits.
- bundle bitmap now fails on an invalid bundle instead of printing a bitmap.
- Goldens record only set bits; the schema and encoded blob are scratch files
  checked by the round trip, so an added config field touches only schema.txt.
  test-acc/test-update no longer regenerate the schema and goldens first.
- Decode: overflow-safe size check; tests for header errors, byte boundaries,
  non-zero context; Python decoder checks the context; unique-schema test.
- Acceptance coverage for interface defaults, empty containers, explicit zero,
  dotted map keys, target overrides, run_as, escapes, mixed artifacts, an
  invalid bundle, and a Python-defined resource.

Co-authored-by: Isaac <no-reply@databricks.com>
Split acceptance/bundle/bitmap into presence/ (set bits, round trip, invalid
bundle) and full/, which records the complete bitmap-text so a PR adding a
config field shows where it landed. generate-bitmap-schema refreshes full/.

Co-authored-by: Isaac <no-reply@databricks.com>
- bundle.Telemetry is now the single source of the deploy event's bool_values:
  fields are bool (reported when true), *bool (a measured value) or []bool (one
  value per item), keyed by a `metric` tag. Call sites set one field instead of
  a Metrics call plus a mirror. The wire has the same entries in field order;
  has_<task_type> and local.cache.* stay in Metrics.BoolValues.
- The bitmap records each bool field's value: the schema has "=true"/"=false"
  entries after every bool field (config and telemetry).
- bitmap-text and the new `bundle bitmap decode` (stdin) print one line per set
  field: "T"/"F" for a bool value, "1" otherwise.
- acceptance/bundle/bitmap/full records the whole schema; presence covers bool
  variants (SDK omitempty false, non-omitempty true/false, *bool false, an
  unresolved reference) and pins the known gap: an explicit false on an
  omitempty bool of a CLI-defined struct is dropped by the loader.

Co-authored-by: Isaac <no-reply@databricks.com>
databricks.bundles._bitmap decodes an encoded bundle bitmap without the CLI:
it embeds the schema, raw-DEFLATE compressed and base64 encoded, and
decompresses it on import. `python -m databricks.bundles._bitmap` reads a
bitmap on stdin and prints the same lines as `bundle bitmap decode`.

bundle/bitmap/genpython writes the embedded schema; compressing in Go keeps
the generated file identical regardless of the Python's zlib build. It runs as
part of `task generate-bitmap-schema`.

The presence test and every no_drift invariant config check that the Python
decoder's output matches the CLI's. The tests pass --reinstall-package because
the wheel's version does not change with the code and uv would otherwise reuse
a cached install.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
pydabs-codegen deletes every databricks/bundles package except core before
regenerating, which removed _bitmap (and then ruff re-sorted the test's
imports). Exclude it there, and skip private packages in the generated docs.

Co-authored-by: Isaac <no-reply@databricks.com>
Configs with warnings (e.g. the deprecated pipeline development property)
leaked them into output.txt once stdout and stderr were split. Log stderr and
keep the panic check on it.

Co-authored-by: Isaac <no-reply@databricks.com>
Runs over every invariant config without deploying: bundle validate (text
and JSON) must succeed, and both the CLI and Python decoders must reproduce
the bitmap-text bits from the encoded bitmap. Replaces the bitmap block in
no_drift, which only compared the two decoders and ran on cloud too.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
bitmap-text is folded into "bundle bitmap bitmap -o text"; the default stays
the compressed form. decode takes the same flag and defaults to text. The
text form starts with a "size=N context=C" header, and -o json renders size,
context and trees of the present fields and of the bool fields seen true and
false. The Python decoder prints the same header.

The presence test pins the JSON form and checks that decode reproduces it and
that re-encoding is byte-identical; validate_bitmap round-trips JSON on every
invariant config.

Co-authored-by: Isaac <no-reply@databricks.com>
Like acceptance/bundle/refschema: resources.<type>.* goes to
output/<type>.txt and everything else to output/root.txt. Each line carries
its bit, so a file still shows where its fields sit in the schema.

Co-authored-by: Isaac <no-reply@databricks.com>
…nother

Co-authored-by: Isaac <no-reply@databricks.com>
app_lifecycle_started, cluster_lifecycle_started and
sql_warehouse_lifecycle_started took the value of whichever resource came
first in map order, so with one app started and another stopped the
reported value changed from run to run. They now report true if any
resource of the type sets started: true and false if any sets false, each
value once; a bundle whose resources agree still sends a single entry.

The fields become []bool, which changes their bitmap entries; the schema
is not released yet, so it is regenerated from scratch.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
@denik
denik force-pushed the denik/bundle-bitmap branch from 5e60941 to 445b523 Compare November 5, 2026 13:52
@github-actions github-actions Bot removed the Stale label Nov 5, 2026
The per-artifact and per-resource flags were []bool fields grown with
append. They are now BoolSet, which records the values a measurement took:
call sites read b.Telemetry.ArtifactFilesIsSet.SetBool(x), bool_values gets
each value taken once (true before false), and the bitmap gives the field a
presence bit plus its =true/=false bits, the same entries as any bool.

The lifecycle.started loops call SetBool per resource, which replaces the
startedValues helper. Telemetry bits are now set directly instead of through
a dyn conversion. The schema is not released yet, so it is regenerated.

Co-authored-by: Isaac <no-reply@databricks.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DABs DABs related issues PyDABs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants