Add JSON output to bundle init reporting where the template materialized - #6161
Conversation
…lized
`bundle init` gave callers no machine-readable indication of where it wrote
the template. The success message is the template's own rendered text, so a
caller that passes `--output-dir` could not learn which subdirectory under it
became the bundle root, and had to assume it is named after the project. That
assumption holds for the built-in templates, which output `{{.project_name}}/`,
but not for a custom template whose output path is nested.
Add an `InitResult` reported by `bundle init -o json`:
{
"template_name": "custom",
"output_dir": "/path/to/output",
"bundle_roots": ["projects/alpha/yz"]
}
`bundle_roots` are the directories that received a bundle configuration file,
relative to the resolved output directory, slash-separated and sorted. They are
derived from the files `persistToDisk` actually persisted, so a configuration
file removed by a `{{skip}}` directive is not reported. Paths stay relative and
slash-based so the contract is identical for the local and workspace filers.
A template may emit more than one bundle configuration file, in which case each
root is an independent bundle, so this is a list; callers that expect exactly
one should handle len != 1 explicitly.
The default text output is unchanged: rendering is gated on JSON output, and
the success message is still printed by `Materialize`. `Configure` now resolves
the output directory with `filepath.Abs` and retains it, so a relative
`--output-dir` such as `..` can be joined with a bundle root by the caller.
Integration test reportCommit: 8ef7a04
8 interesting tests: 4 RECOVERED, 4 SKIP
Top 9 slowest tests (at least 2 minutes):
|
The two new acceptance tests compared `output_dir` verbatim, but it is an OS path, so Windows rendered it backslash-separated and the golden files only matched on Unix. Pipe the JSON through sed to normalize the separators, keeping a single golden per case. `bundle_roots` are always slash-separated, so they are unaffected. Also drop the unit cases that the acceptance tests already cover end to end (nested root, a root at the output directory, and the empty input). The remaining rows cover what the acceptance tests cannot reach without a template fixture each: the four configuration file names, ordering, de-duplication, and files merely named like a configuration file.
`template_name` and `output_dir` echoed back values the caller already passed as
arguments, so they carried no information. Replace all three fields with a
single `outputs` array listing the files the template wrote, relative to the
output directory and sorted:
{ "outputs": ["projects/alpha/yz/databricks.yml", "projects/alpha/yz/src/yz.py"] }
A caller that needs the bundle root can select the entry whose base name is a
bundle configuration file, which also removes the need for this package to
duplicate the list of configuration file names.
Since the output no longer contains an OS path, `Configure` no longer has to
retain the resolved output directory, so `constructOutputFiler` keeps resolving
it as before, and the acceptance tests no longer need to normalize path
separators for Windows.
`InitResult` is new in this change and its only caller invokes it after a
successful `Materialize`, so the renderer is always set. The nil branch was
never reachable, and removing it also removes the test that existed only to
cover it; the acceptance tests pin the sorting and the {{skip}} filtering that
remain.
| # after the project. This pins the contract for the standard shape. | ||
| # | ||
| # stderr is dropped so that the golden output only pins the JSON payload. | ||
| trace $CLI bundle init default-minimal --config-file ./input.json --output-dir output -o json 2>/dev/null |
There was a problem hiding this comment.
We have a bunch of template tests, should we just use this option on some of those tests and drop this one?
There was a problem hiding this comment.
Done — dropped this case and passed -o json in the existing default-minimal/python test instead. The JSON is appended after the success message (the message goes to stderr, the payload to stdout), so that case still asserts everything it did before.
I kept nested-output, since no existing case uses a template whose output path is nested — that shape is the reason for this change, and the case also pins that the CLI creates no stray top-level directory. Happy to fold it into an existing case too if you would rather not have a new one.
Rather than add a test case that only differs by `-o json`, pass the flag in the existing default-minimal case, which already initializes a built-in template and validates the result. The JSON is appended to that test's output, so the case keeps asserting everything it did before.
|
Windows runners are not picking up CI jobs. Linux ones passed 👍 |
## Release v1.11.0 ### CLI * Fixed `databricks repos get/update/delete` failing with `object at path "..." is not a repo` for Git-CLI-enabled folders (currently in preview), which the workspace API reports as directories rather than repos ([#6181](#6181)). * Support `dbfs:/Skills/...` paths in `databricks fs` commands, routed to the Files API. ([#6147](#6147)) ### Bundles * For jobs where `ai_runtime_task.code_source_path` is a relative path to a local directory, the directory is now packaged into a tarball (honoring `.gitignore` and `sync.include`/`sync.exclude`), uploaded during deployment, and `code_source_path` is rewritten to the uploaded workspace path. ([#6110](#6110)) * Added JSON output to `bundle init`. Running `databricks bundle init <template> -o json` now reports the files the template wrote, relative to the output directory. This lets callers that pass `--output-dir` learn where the template materialized instead of assuming the output is a single directory named after the project. The default text output is unchanged. ([#6161](#6161)) * The terraform deployment engine is deprecated and will stop working in a future version of the CLI. Setting `bundle.engine: terraform` now emits a deprecation warning. See https://docs.databricks.com/aws/en/dev-tools/bundles/direct for how to migrate to the direct deployment engine. ([#6099](#6099)) * Fixed the direct deployment engine planning a spurious `create` for an empty `grants: []` list. Terraform records no grants resource for such a list, so `bundle plan` after `bundle deployment migrate` no longer reports an action for it. Emptying a previously deployed list still revokes the grants, after which the node is dropped from the deployment state instead of being reported as unchanged forever. ([#6039](#6039)) * Fixed `bundle generate` downloading notebooks found inside a folder without their file extension. They are now exported like top-level notebooks, so a Python notebook lands as `notebook.py` instead of an extensionless file ([#6144](#6144)). * direct: `webhook_notifications.on_*` destinations on jobs, tasks, and `for_each_task` are now compared as unordered sets. Previously the Jobs API returning these lists in a different order than submitted produced a phantom diff that `bundle plan` and `bundle deploy` could never converge past, reporting `1 to change` on every run ([#6060](#6060)). * Fixed a pipeline with `allow_duplicate_names: true` never converging on the direct engine: the field is only accepted on create/update and is never returned by the pipelines GET API, so every subsequent `bundle plan` reported the pipeline as a perpetual update. ([#6076](#6076)) * direct: A local change to an input-only field (one the API accepts on write but never returns on read, e.g. pipelines' `run_as` or external locations' `skip_validation`) is no longer silently skipped when the new value coincidentally matches the field's fabricated remote value. Previously such a change could hit the `remote_already_set` shortcut and be dropped from the plan. ([#6112](#6112)) * Revert usage of RedactiveSenstiveFields (added in [#5896](#5896), released in 1.10.0) which lead to incorrect behaviour (permanent drift) for duration field in Postgres resources ([#6179](#6179)). * Document postgres resource fields in the json schema ([#6164](#6164), [#6163](#6163)). * direct: Recreating a `vector_search_indexes` resource no longer fails with "Index ... is currently pending deletion" when the backend has not yet released the index name. The create is now retried until the name becomes available. ([#6143](#6143)) ### Dependency Updates * Bump `github.com/databricks/databricks-sdk-go` from v0.165.0 to v0.166.0. ([#6175](#6175)) * Upgrade Terraform provider to 1.124.0. ([#6174](#6174))
bundle initgives callers no machine-readable indication of what it wrote, so a caller that passes--output-dirhas to assume the output is a single directory named after the project. That holds for the built-in templates, which output{{.project_name}}/, but not for a custom template whose output path is nested: with output pathprojects/{{.group}}/{{.project_name}}/the bundle lands at<output-dir>/projects/alpha/yz/, and a caller looking for<output-dir>/yz/misses it.Related: #6142.
Adds JSON output to
bundle init:{ "outputs": [ "projects/alpha/yz/databricks.yml", "projects/alpha/yz/src/yz.py" ] }outputsare the files the template wrote, relative to the output directory, slash-separated and sorted. They come from the filespersistToDiskactually persisted, so a file removed by a{{skip}}directive is not listed. Paths are relative rather than absolute and slash-separated rather than OS-specific, so the contract is identical for the local and workspace filers. A caller that needs the bundle root can select the entry whose base name is a bundle configuration file.Field names are part of the JSON contract — new fields should be additive so consumers tolerate CLI versions that predate this change.
Compatibility. Default text output is unchanged: rendering is gated on
flags.OutputJSON, and the success message is still printed byMaterialize.Materialize's signature is untouched, socmd/pipelines/init.gois unaffected.Tests. The standard shape is covered by passing
-o jsonin the existingdefault-minimal/pythoncase. A newnested-outputcase covers a custom template whose output path is nested, asserting the outputs are underprojects/alpha/yzand that no stray top-levelyz/directory is created. The goldens cover the sorting and the{{skip}}filtering — verified by removing each and confirming they fail.