From 30540eeddfa93118fd37beef4eb97c200f40492a Mon Sep 17 00:00:00 2001 From: Jonathan Moss <2729151+jwmoss@users.noreply.github.com> Date: Mon, 7 Sep 2026 22:41:46 -0400 Subject: [PATCH] feat: hint the resources layout for narrowed exports Print one hint after a written export when the user passes --resources or --name and the effective layout is workspace. The hint uses the existing progress channel, so --quiet and --json suppress it. Document the --resources and --module-layout pairing in resource selection. Add CHANGELOG.md for every published tag and an Unreleased section. --- CHANGELOG.md | 89 +++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 1 + docs/resource-selection.md | 14 ++++++ internal/cli/export.go | 25 ++++++++++- internal/cli/export_test.go | 28 ++++++++++++ 5 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..004ffaf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,89 @@ +# Changelog + +All notable changes to this project are recorded in this file. + +The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Hint the `resources` module layout after a narrowed export in the workspace layout. + +### Changed + +- Document how `--resources`, `--name`, and `--module-layout` work together in resource selection. + +## [0.5.0] - 2026-09-07 + +### Added + +- Scaffold individual Registry resource modules with `--module-layout resources`. #34 + +## [0.4.0] - 2026-09-07 + +### Added + +- Show a cached release update notice. #33 + +## [0.3.1] - 2026-09-07 + +### Fixed + +- Select the `536tech/workspace/databricks` pattern module for scaffolded exports. #32 +- Use stable release archive names. #31 + +## [0.3.0] - 2026-09-07 + +### Added + +- Select individual resources by exact name with `--name`. #28 +- Add actionable CLI diagnostics for common failures. #29 +- Add opt-in CLI telemetry with the `telemetry` command. #30 + +### Changed + +- Move and shorten the export permission guide. #24 +- Add an OpenTofu export and import example. #25 + +## [0.2.0] - 2026-09-07 + +### Added + +- Add selected exports and a local MiniLake import demo. #21 +- Document the export permissions and the visibility limits. #23 + +### Changed + +- Use Registry module v0.1.0 for exports. #22 +- Simplify the export code and verify the Windows downloads. #26 +- Simplify the public documentation and the versioned releases. #20 + +## [0.1.0] - 2026-09-03 + +### Added + +- Add the datatf CLI with the `auth status`, `inventory`, `export`, and `version` commands. +- Export separate workspace and shared Terraform roots. #12 +- Add the `auth status` command in place of `doctor`. #11 +- Add Windows distribution and signing hooks. +- Document the supported product boundary. #13 + +### Fixed + +- Group the import blocks and consolidate `terraform.tfvars`. #9 +- Force LF checkouts so the golden tests pass on Windows. #5 +- Use `homebrew_casks.binaries` for the Homebrew cask. #3 + +### Removed + +- Remove the commercial licensing features. #10 + +[Unreleased]: https://github.com/536tech/datatf/compare/v0.5.0...HEAD +[0.5.0]: https://github.com/536tech/datatf/compare/v0.4.0...v0.5.0 +[0.4.0]: https://github.com/536tech/datatf/compare/v0.3.1...v0.4.0 +[0.3.1]: https://github.com/536tech/datatf/compare/v0.3.0...v0.3.1 +[0.3.0]: https://github.com/536tech/datatf/compare/v0.2.0...v0.3.0 +[0.2.0]: https://github.com/536tech/datatf/compare/v0.1.0...v0.2.0 +[0.1.0]: https://github.com/536tech/datatf/releases/tag/v0.1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 649626c..6a98ae5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,6 +42,7 @@ Review the generated diff. Open a pull request with the change and its test resu ## Releases +Add an entry under `## [Unreleased]` in [CHANGELOG.md](CHANGELOG.md) with each pull request. Use [Semantic Versioning](https://semver.org/spec/v2.0.0.html) with tags named `vMAJOR.MINOR.PATCH`. The tag is the version source. During `0.x`, use a patch for compatible fixes and a minor for features or breaking changes. Describe breaking CLI or Terraform output changes in the pull request. diff --git a/docs/resource-selection.md b/docs/resource-selection.md index b2788d9..8cae569 100644 --- a/docs/resource-selection.md +++ b/docs/resource-selection.md @@ -36,6 +36,20 @@ For service principals, use `key` from the inventory instead of the display name Duplicate display names have an identifier suffix in that key. Selection preserves the same key and import address as an export of the whole group. +## Selection and module layout + +`--resources` and `--name` choose the objects. `--module-layout` chooses the modules and the +Terraform addresses. A narrower selection does not change the layout. +The default `workspace` layout calls the `536tech/workspace/databricks` pattern module. +Use `--module-layout resources` to call the individual `536tech` Registry modules directly: + +```sh +datatf export --profile analytics --resources catalogs --module-layout resources --scaffold +``` + +A selected catalog keeps its schemas in both layouts. +See [module layouts](module-layouts.md) for the module table, the versions, and the state rules. + ## Catalogs and dependencies A selected catalog includes its supported schemas, direct grants, and workspace bindings. diff --git a/internal/cli/export.go b/internal/cli/export.go index f8d1a03..78ede52 100644 --- a/internal/cli/export.go +++ b/internal/cli/export.go @@ -169,7 +169,11 @@ func (opts *exportOptions) run(cmd *cobra.Command, rc *runtime) error { if err != nil { return outputError(err) } - return writeExportSummary(rc, written, rep) + if err := writeExportSummary(rc, written, rep); err != nil { + return err + } + opts.hintLayout(cmd, rc) + return nil } func (opts *exportOptions) files(ex *contract.Export, rep *contract.Report) ( @@ -234,6 +238,25 @@ func (opts *exportOptions) checkReport(rc *runtime, rep *contract.Report) error return rc.partialError("export", rep.Issues) } +const layoutHint = "Hint: this export selects one or more resource groups. " + + "Use --module-layout resources to call the individual Registry modules. " + + "See docs/module-layouts.md." + +// needsLayoutHint reports whether a narrowed export in the workspace layout needs the hint. +func needsLayoutHint(narrowed bool, layout string) bool { + return narrowed && layout == "workspace" +} + +// hintLayout writes the resource layout hint to the progress channel after a written export. +func (opts *exportOptions) hintLayout(cmd *cobra.Command, rc *runtime) { + narrowed := cmd.Flags().Changed("resources") || cmd.Flags().Changed("name") + log := rc.progress() + if log == nil || !needsLayoutHint(narrowed, opts.moduleLayout) { + return + } + log("%s", layoutHint) +} + func writeExportSummary(rc *runtime, files []string, rep *contract.Report) error { if rc.out.IsJSON() { return rc.out.JSON(rep) diff --git a/internal/cli/export_test.go b/internal/cli/export_test.go index 8fb4f7a..c1b48ce 100644 --- a/internal/cli/export_test.go +++ b/internal/cli/export_test.go @@ -137,6 +137,34 @@ func TestExportScaffold(t *testing.T) { } } +func TestExportHintsResourceLayout(t *testing.T) { + srv := fakews.New(t) + isolateAuth(t, srv) + tests := []struct { + name string + args []string + want bool + }{ + {"selected group", []string{"--resources", "warehouses"}, true}, + {"selected name", []string{"--resources", "warehouses", "--name", "Analytics WH"}, true}, + {"default groups", nil, false}, + {"resource layout", []string{"--resources", "warehouses", "--module-layout", "resources"}, false}, + {"quiet", []string{"--resources", "warehouses", "--quiet"}, false}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + args := append([]string{"export", "--out", filepath.Join(t.TempDir(), "out")}, test.args...) + code, _, stderr := run(t, args...) + if code != exitOK { + t.Fatalf("exit %d: %s", code, stderr) + } + if got := strings.Contains(stderr, "--module-layout resources"); got != test.want { + t.Fatalf("hint = %v, want %v: %s", got, test.want, stderr) + } + }) + } +} + func TestExportScaffoldRegistryDefault(t *testing.T) { srv := fakews.New(t) isolateAuth(t, srv)